Skip to content

Commit

Permalink
xfs: hoist out xfs_resizefs_init_new_ags()
Browse files Browse the repository at this point in the history
Move out related logic for initializing new added AGs to a new helper
in preparation for shrinking. No logic changes.

Reviewed-by: Darrick J. Wong <[email protected]>
Signed-off-by: Gao Xiang <[email protected]>
Signed-off-by: Darrick J. Wong <[email protected]>
  • Loading branch information
Gao Xiang authored and Darrick J. Wong committed Mar 25, 2021
1 parent 014695c commit c789c83
Showing 1 changed file with 64 additions and 43 deletions.
107 changes: 64 additions & 43 deletions fs/xfs/xfs_fsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,64 @@
#include "xfs_ag.h"
#include "xfs_ag_resv.h"

/*
* Write new AG headers to disk. Non-transactional, but need to be
* written and completed prior to the growfs transaction being logged.
* To do this, we use a delayed write buffer list and wait for
* submission and IO completion of the list as a whole. This allows the
* IO subsystem to merge all the AG headers in a single AG into a single
* IO and hide most of the latency of the IO from us.
*
* This also means that if we get an error whilst building the buffer
* list to write, we can cancel the entire list without having written
* anything.
*/
static int
xfs_resizefs_init_new_ags(
struct xfs_trans *tp,
struct aghdr_init_data *id,
xfs_agnumber_t oagcount,
xfs_agnumber_t nagcount,
xfs_rfsblock_t delta,
bool *lastag_extended)
{
struct xfs_mount *mp = tp->t_mountp;
xfs_rfsblock_t nb = mp->m_sb.sb_dblocks + delta;
int error;

*lastag_extended = false;

INIT_LIST_HEAD(&id->buffer_list);
for (id->agno = nagcount - 1;
id->agno >= oagcount;
id->agno--, delta -= id->agsize) {

if (id->agno == nagcount - 1)
id->agsize = nb - (id->agno *
(xfs_rfsblock_t)mp->m_sb.sb_agblocks);
else
id->agsize = mp->m_sb.sb_agblocks;

error = xfs_ag_init_headers(mp, id);
if (error) {
xfs_buf_delwri_cancel(&id->buffer_list);
return error;
}
}

error = xfs_buf_delwri_submit(&id->buffer_list);
if (error)
return error;

xfs_trans_agblocks_delta(tp, id->nfree);

if (delta) {
*lastag_extended = true;
error = xfs_ag_extend_space(mp, tp, id, delta);
}
return error;
}

/*
* growfs operations
*/
Expand All @@ -34,6 +92,7 @@ xfs_growfs_data_private(
xfs_agnumber_t nagimax = 0;
xfs_rfsblock_t nb, nb_div, nb_mod;
xfs_rfsblock_t delta;
bool lastag_extended;
xfs_agnumber_t oagcount;
struct xfs_trans *tp;
struct aghdr_init_data id = {};
Expand Down Expand Up @@ -74,58 +133,20 @@ xfs_growfs_data_private(
if (error)
return error;

/*
* Write new AG headers to disk. Non-transactional, but need to be
* written and completed prior to the growfs transaction being logged.
* To do this, we use a delayed write buffer list and wait for
* submission and IO completion of the list as a whole. This allows the
* IO subsystem to merge all the AG headers in a single AG into a single
* IO and hide most of the latency of the IO from us.
*
* This also means that if we get an error whilst building the buffer
* list to write, we can cancel the entire list without having written
* anything.
*/
INIT_LIST_HEAD(&id.buffer_list);
for (id.agno = nagcount - 1;
id.agno >= oagcount;
id.agno--, delta -= id.agsize) {

if (id.agno == nagcount - 1)
id.agsize = nb -
(id.agno * (xfs_rfsblock_t)mp->m_sb.sb_agblocks);
else
id.agsize = mp->m_sb.sb_agblocks;

error = xfs_ag_init_headers(mp, &id);
if (error) {
xfs_buf_delwri_cancel(&id.buffer_list);
goto out_trans_cancel;
}
}
error = xfs_buf_delwri_submit(&id.buffer_list);
error = xfs_resizefs_init_new_ags(tp, &id, oagcount, nagcount,
delta, &lastag_extended);
if (error)
goto out_trans_cancel;

xfs_trans_agblocks_delta(tp, id.nfree);

/* If there are new blocks in the old last AG, extend it. */
if (delta) {
error = xfs_ag_extend_space(mp, tp, &id, delta);
if (error)
goto out_trans_cancel;
}

/*
* Update changed superblock fields transactionally. These are not
* seen by the rest of the world until the transaction commit applies
* them atomically to the superblock.
*/
if (nagcount > oagcount)
xfs_trans_mod_sb(tp, XFS_TRANS_SB_AGCOUNT, nagcount - oagcount);
if (nb > mp->m_sb.sb_dblocks)
xfs_trans_mod_sb(tp, XFS_TRANS_SB_DBLOCKS,
nb - mp->m_sb.sb_dblocks);
if (delta)
xfs_trans_mod_sb(tp, XFS_TRANS_SB_DBLOCKS, delta);
if (id.nfree)
xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, id.nfree);

Expand All @@ -152,7 +173,7 @@ xfs_growfs_data_private(
* If we expanded the last AG, free the per-AG reservation
* so we can reinitialize it with the new size.
*/
if (delta) {
if (lastag_extended) {
struct xfs_perag *pag;

pag = xfs_perag_get(mp, id.agno);
Expand Down

0 comments on commit c789c83

Please sign in to comment.