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
|