Re: [PATCH 6/7] xfs: separate secondary sb update in growfs
From: Brian Foster <hidden>
Date: 2018-02-09 16:11:55
On Thu, Feb 01, 2018 at 05:42:01PM +1100, Dave Chinner wrote:
From: Dave Chinner <redacted> This happens after all the transactions to update the superblock occur, and errors need to be handled slightly differently. Seperate
Separate
quoted hunk ↗ jump to hunk
out the code into it's own function, and clean up the error goto stack in the core growfs code as it is now much simpler. Signed-Off-By: Dave Chinner <redacted> --- fs/xfs/xfs_fsops.c | 154 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 67 deletions(-)diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 5c844e540320..113be7dbdc81 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c
...
quoted hunk ↗ jump to hunk
@@ -572,16 +572,79 @@ xfs_growfs_data_private( error = xfs_ag_resv_free(pag); xfs_perag_put(pag); if (error) - goto out; + return error; } /* Reserve AG metadata blocks. */ - error = xfs_fs_reserve_ag_blocks(mp); - if (error && error != -ENOSPC) - goto out; + return xfs_fs_reserve_ag_blocks(mp);
It looks like we change the semantics of -ENOSPC during perag reservation init. No mention of whether this is intentional and/or why..? Brian
quoted hunk ↗ jump to hunk
+ +out_trans_cancel: + xfs_trans_cancel(tp); + return error; +} + +static int +xfs_growfs_log_private( + xfs_mount_t *mp, /* mount point for filesystem */ + xfs_growfs_log_t *in) /* growfs log input struct */ +{ + xfs_extlen_t nb; + + nb = in->newblocks; + if (nb < XFS_MIN_LOG_BLOCKS || nb < XFS_B_TO_FSB(mp, XFS_MIN_LOG_BYTES)) + return -EINVAL; + if (nb == mp->m_sb.sb_logblocks && + in->isint == (mp->m_sb.sb_logstart != 0)) + return -EINVAL; + /* + * Moving the log is hard, need new interfaces to sync + * the log first, hold off all activity while moving it. + * Can have shorter or longer log in the same space, + * or transform internal to external log or vice versa. + */ + return -ENOSYS; +} + +static int +xfs_growfs_imaxpct( + struct xfs_mount *mp, + __u32 imaxpct) +{ + struct xfs_trans *tp; + int dpct; + int error; + + if (imaxpct > 100) + return -EINVAL; + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata, + XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp); + if (error) + return error; + + dpct = imaxpct - mp->m_sb.sb_imax_pct; + xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct); + xfs_trans_set_sync(tp); + return xfs_trans_commit(tp); +} + +/* + * After a grow operation, we need to update all the secondary superblocks + * to match the new state of the primary. Read/init the superblocks and update + * them appropriately. + */ +static int +xfs_growfs_update_superblocks( + struct xfs_mount *mp, + xfs_agnumber_t oagcount) +{ + struct xfs_buf *bp; + xfs_agnumber_t agno; + int saved_error = 0; + int error = 0; /* update secondary superblocks. */ - for (agno = 1; agno < nagcount; agno++) { + for (agno = 1; agno < mp->m_sb.sb_agcount; agno++) { error = 0; /* * new secondary superblocks need to be zeroed, not read from@@ -631,57 +694,7 @@ xfs_growfs_data_private( } } - out: return saved_error ? saved_error : error; - - error0: - xfs_trans_cancel(tp); - return error; -} - -static int -xfs_growfs_log_private( - xfs_mount_t *mp, /* mount point for filesystem */ - xfs_growfs_log_t *in) /* growfs log input struct */ -{ - xfs_extlen_t nb; - - nb = in->newblocks; - if (nb < XFS_MIN_LOG_BLOCKS || nb < XFS_B_TO_FSB(mp, XFS_MIN_LOG_BYTES)) - return -EINVAL; - if (nb == mp->m_sb.sb_logblocks && - in->isint == (mp->m_sb.sb_logstart != 0)) - return -EINVAL; - /* - * Moving the log is hard, need new interfaces to sync - * the log first, hold off all activity while moving it. - * Can have shorter or longer log in the same space, - * or transform internal to external log or vice versa. - */ - return -ENOSYS; -} - -static int -xfs_growfs_imaxpct( - struct xfs_mount *mp, - __u32 imaxpct) -{ - struct xfs_trans *tp; - int64_t dpct; - int error; - - if (imaxpct > 100) - return -EINVAL; - - error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata, - XFS_GROWFS_SPACE_RES(mp), 0, XFS_TRANS_RESERVE, &tp); - if (error) - return error; - - dpct = (int64_t)imaxpct - mp->m_sb.sb_imax_pct; - xfs_trans_mod_sb(tp, XFS_TRANS_SB_IMAXPCT, dpct); - xfs_trans_set_sync(tp); - return xfs_trans_commit(tp); } /*@@ -694,6 +707,7 @@ xfs_growfs_data( struct xfs_mount *mp, struct xfs_growfs_data *in) { + xfs_agnumber_t oagcount; int error = 0; if (!capable(CAP_SYS_ADMIN))@@ -708,6 +722,7 @@ xfs_growfs_data( goto out_error; } + oagcount = mp->m_sb.sb_agcount; error = xfs_growfs_data_private(mp, in); if (error) goto out_error;@@ -722,6 +737,11 @@ xfs_growfs_data( } else mp->m_maxicount = 0; + /* + * Update secondary superblocks now the physical grow has completed + */ + error = xfs_growfs_update_superblocks(mp, oagcount); + out_error: /* * Increment the generation unconditionally, the error could be from-- 2.15.1 -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html