growfs rewrites all secondary supers, and relabel must do so as well; factor out the code which does this for use by both operations. Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx> --- fs/xfs/xfs_fsops.c | 131 +++++++++++++++++++++++++++++++--------------------- fs/xfs/xfs_fsops.h | 2 + 2 files changed, 80 insertions(+), 53 deletions(-) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index b4d7582..b49b4e4 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -140,6 +140,79 @@ xfs_growfs_get_hdr_buf( return bp; } +/* + * Copy the contents of the primary super to all backup supers. + * %agcount is current number of ags in the filesystem. + * %nagcount is used during growfs when we may have new secondaries. + * If %nagcount is 0 (no growfs), we use %agcount in its place. + */ +int +xfs_update_secondary_supers( + xfs_mount_t *mp, + xfs_agnumber_t agcount, + xfs_agnumber_t nagcount) +{ + int error, saved_error; + xfs_agnumber_t agno; + xfs_buf_t *bp; + + error = saved_error = 0; + + if (nagcount == 0) + nagcount = agcount; + + for (agno = 1; agno < nagcount; agno++) { + error = 0; + if (agno < agcount) { + error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), + XFS_FSS_TO_BB(mp, 1), 0, &bp, + &xfs_sb_buf_ops); + } else { + /* + * new secondary superblocks need to be zeroed, not read + * from disk as the contents of the new area we are + * growing into is completely unknown. + */ + bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), + XFS_FSS_TO_BB(mp, 1), 0); + if (bp) { + bp->b_ops = &xfs_sb_buf_ops; + xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); + } else + error = -ENOMEM; + } + + /* + * If we get an error reading or writing alternate superblocks, + * continue. xfs_repair chooses the "best" superblock based + * on most matches; if we break early, we'll leave more + * superblocks un-updated than updated, and xfs_repair may + * pick them over the properly-updated primary. + */ + if (error) { + xfs_warn(mp, + "error %d reading secondary superblock for ag %d", + error, agno); + saved_error = error; + continue; + } + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); + + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) { + xfs_warn(mp, + "write error %d updating secondary superblock for ag %d", + error, agno); + saved_error = error; + continue; + } + } + return saved_error ? saved_error : error; +} + static int xfs_growfs_data_private( xfs_mount_t *mp, /* mount point for filesystem */ @@ -155,7 +228,7 @@ xfs_growfs_data_private( xfs_buf_t *bp; int bucket; int dpct; - int error, saved_error = 0; + int error; xfs_agnumber_t nagcount; xfs_agnumber_t nagimax = 0; xfs_rfsblock_t nb, nb_mod; @@ -502,59 +575,11 @@ xfs_growfs_data_private( mp->m_maxicount = 0; xfs_set_low_space_thresholds(mp); - /* update secondary superblocks. */ - for (agno = 1; agno < nagcount; agno++) { - error = 0; - /* - * new secondary superblocks need to be zeroed, not read from - * disk as the contents of the new area we are growing into is - * completely unknown. - */ - if (agno < oagcount) { - error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, - XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), - XFS_FSS_TO_BB(mp, 1), 0, &bp, - &xfs_sb_buf_ops); - } else { - bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp, - XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), - XFS_FSS_TO_BB(mp, 1), 0); - if (bp) { - bp->b_ops = &xfs_sb_buf_ops; - xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); - } else - error = -ENOMEM; - } - - /* - * If we get an error reading or writing alternate superblocks, - * continue. xfs_repair chooses the "best" superblock based - * on most matches; if we break early, we'll leave more - * superblocks un-updated than updated, and xfs_repair may - * pick them over the properly-updated primary. - */ - if (error) { - xfs_warn(mp, - "error %d reading secondary superblock for ag %d", - error, agno); - saved_error = error; - continue; - } - xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); - - error = xfs_bwrite(bp); - xfs_buf_relse(bp); - if (error) { - xfs_warn(mp, - "write error %d updating secondary superblock for ag %d", - error, agno); - saved_error = error; - continue; - } - } - return saved_error ? saved_error : error; + /* Copy new geometry to all backup superblocks */ + error = xfs_update_secondary_supers(mp, oagcount, nagcount); + return error; - error0: +error0: xfs_trans_cancel(tp); return error; } diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h index f32713f..82e8dc7 100644 --- a/fs/xfs/xfs_fsops.h +++ b/fs/xfs/xfs_fsops.h @@ -19,6 +19,8 @@ #define __XFS_FSOPS_H__ extern int xfs_fs_geometry(xfs_mount_t *mp, xfs_fsop_geom_t *geo, int nversion); +extern int xfs_update_secondary_supers(xfs_mount_t *mp, xfs_agnumber_t aogcount, + xfs_agnumber_t nagcount); extern int xfs_growfs_data(xfs_mount_t *mp, xfs_growfs_data_t *in); extern int xfs_growfs_log(xfs_mount_t *mp, xfs_growfs_log_t *in); extern int xfs_fs_counts(xfs_mount_t *mp, xfs_fsop_counts_t *cnt); -- 1.7.1 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs