]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: pass the exact range to initialize to xfs_initialize_perag
authorChristoph Hellwig <hch@lst.de>
Sun, 8 Sep 2024 07:53:41 +0000 (10:53 +0300)
committerChristoph Hellwig <hch@lst.de>
Fri, 20 Sep 2024 12:04:53 +0000 (14:04 +0200)
Currently only the new agcount is passed to xfs_initialize_perag, which
requires lookups of existing AGs to skip them and complicates error
handling.  Also pass the previous agcount so that the range that
xfs_initialize_perag operates on is exactly defined.  That way the
extra lookups can be avoided, and error handling can clean up the
exact range from the old count to the last added perag structure.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/libxfs/xfs_ag.c
fs/xfs/libxfs/xfs_ag.h
fs/xfs/xfs_fsops.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_mount.c

index 5f0494702e0b55a2343a3f8e08ed33e5e1974f81..652376aa52e9901a9851a1a4ec3076033cdf631c 100644 (file)
@@ -296,27 +296,19 @@ xfs_free_unused_perag_range(
 int
 xfs_initialize_perag(
        struct xfs_mount        *mp,
-       xfs_agnumber_t          agcount,
+       xfs_agnumber_t          old_agcount,
+       xfs_agnumber_t          new_agcount,
        xfs_rfsblock_t          dblocks,
        xfs_agnumber_t          *maxagi)
 {
        struct xfs_perag        *pag;
        xfs_agnumber_t          index;
-       xfs_agnumber_t          first_initialised = NULLAGNUMBER;
        int                     error;
 
-       /*
-        * Walk the current per-ag tree so we don't try to initialise AGs
-        * that already exist (growfs case). Allocate and insert all the
-        * AGs we don't find ready for initialisation.
-        */
-       for (index = 0; index < agcount; index++) {
-               pag = xfs_perag_get(mp, index);
-               if (pag) {
-                       xfs_perag_put(pag);
-                       continue;
-               }
+       if (old_agcount >= new_agcount)
+               return 0;
 
+       for (index = old_agcount; index < new_agcount; index++) {
                pag = kzalloc(sizeof(*pag), GFP_KERNEL | __GFP_RETRY_MAYFAIL);
                if (!pag) {
                        error = -ENOMEM;
@@ -353,21 +345,17 @@ xfs_initialize_perag(
                /* Active ref owned by mount indicates AG is online. */
                atomic_set(&pag->pag_active_ref, 1);
 
-               /* first new pag is fully initialized */
-               if (first_initialised == NULLAGNUMBER)
-                       first_initialised = index;
-
                /*
                 * Pre-calculated geometry
                 */
-               pag->block_count = __xfs_ag_block_count(mp, index, agcount,
+               pag->block_count = __xfs_ag_block_count(mp, index, new_agcount,
                                dblocks);
                pag->min_block = XFS_AGFL_BLOCK(mp);
                __xfs_agino_range(mp, pag->block_count, &pag->agino_min,
                                &pag->agino_max);
        }
 
-       index = xfs_set_inode_alloc(mp, agcount);
+       index = xfs_set_inode_alloc(mp, new_agcount);
 
        if (maxagi)
                *maxagi = index;
@@ -381,8 +369,7 @@ out_remove_pag:
 out_free_pag:
        kfree(pag);
 out_unwind_new_pags:
-       /* unwind any prior newly initialized pags */
-       xfs_free_unused_perag_range(mp, first_initialised, agcount);
+       xfs_free_unused_perag_range(mp, old_agcount, index);
        return error;
 }
 
index d9cccd093b60e06a5d16f79662471e67455329fc..69fc31e7b8472832c23d63091737399e46158983 100644 (file)
@@ -146,8 +146,9 @@ __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
 
 void xfs_free_unused_perag_range(struct xfs_mount *mp, xfs_agnumber_t agstart,
                        xfs_agnumber_t agend);
-int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t agcount,
-                       xfs_rfsblock_t dcount, xfs_agnumber_t *maxagi);
+int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t old_agcount,
+               xfs_agnumber_t agcount, xfs_rfsblock_t dcount,
+               xfs_agnumber_t *maxagi);
 int xfs_initialize_perag_data(struct xfs_mount *mp, xfs_agnumber_t agno);
 void xfs_free_perag(struct xfs_mount *mp);
 
index 3643cc843f62711c3b52ec49c770f530923391fc..de2bf0594cb47489f2cf7977d48a84d452086f89 100644 (file)
@@ -87,6 +87,7 @@ xfs_growfs_data_private(
        struct xfs_mount        *mp,            /* mount point for filesystem */
        struct xfs_growfs_data  *in)            /* growfs data input struct */
 {
+       xfs_agnumber_t          oagcount = mp->m_sb.sb_agcount;
        struct xfs_buf          *bp;
        int                     error;
        xfs_agnumber_t          nagcount;
@@ -94,7 +95,6 @@ xfs_growfs_data_private(
        xfs_rfsblock_t          nb, nb_div, nb_mod;
        int64_t                 delta;
        bool                    lastag_extended = false;
-       xfs_agnumber_t          oagcount;
        struct xfs_trans        *tp;
        struct aghdr_init_data  id = {};
        struct xfs_perag        *last_pag;
@@ -138,16 +138,14 @@ xfs_growfs_data_private(
        if (delta == 0)
                return 0;
 
-       oagcount = mp->m_sb.sb_agcount;
-       /* allocate the new per-ag structures */
-       if (nagcount > oagcount) {
-               error = xfs_initialize_perag(mp, nagcount, nb, &nagimax);
-               if (error)
-                       return error;
-       } else if (nagcount < oagcount) {
-               /* TODO: shrinking the entire AGs hasn't yet completed */
+       /* TODO: shrinking the entire AGs hasn't yet completed */
+       if (nagcount < oagcount)
                return -EINVAL;
-       }
+
+       /* allocate the new per-ag structures */
+       error = xfs_initialize_perag(mp, oagcount, nagcount, nb, &nagimax);
+       if (error)
+               return error;
 
        if (delta > 0)
                error = xfs_trans_alloc(mp, &M_RES(mp)->tr_growdata,
index 1a74fe22672e3e78443ae804bc6e05431bce925b..2af02b32f419c2494e0a1c4134450d5c2172e85d 100644 (file)
@@ -3346,6 +3346,7 @@ xlog_do_recover(
        struct xfs_mount        *mp = log->l_mp;
        struct xfs_buf          *bp = mp->m_sb_bp;
        struct xfs_sb           *sbp = &mp->m_sb;
+       xfs_agnumber_t          old_agcount = sbp->sb_agcount;
        int                     error;
 
        trace_xfs_log_recover(log, head_blk, tail_blk);
@@ -3393,8 +3394,8 @@ xlog_do_recover(
        /* re-initialise in-core superblock and geometry structures */
        mp->m_features |= xfs_sb_version_to_features(sbp);
        xfs_reinit_percpu_counters(mp);
-       error = xfs_initialize_perag(mp, sbp->sb_agcount, sbp->sb_dblocks,
-                       &mp->m_maxagi);
+       error = xfs_initialize_perag(mp, old_agcount, sbp->sb_agcount,
+                       sbp->sb_dblocks, &mp->m_maxagi);
        if (error) {
                xfs_warn(mp, "Failed post-recovery per-ag init: %d", error);
                return error;
index 460f93a9ce00d136cfa56409ae8f230a2741fb64..0f4f56a7f02d9a8f0be3acc560690c9c22a337e0 100644 (file)
@@ -806,8 +806,8 @@ xfs_mountfs(
        /*
         * Allocate and initialize the per-ag data.
         */
-       error = xfs_initialize_perag(mp, sbp->sb_agcount, mp->m_sb.sb_dblocks,
-                       &mp->m_maxagi);
+       error = xfs_initialize_perag(mp, 0, sbp->sb_agcount,
+                       mp->m_sb.sb_dblocks, &mp->m_maxagi);
        if (error) {
                xfs_warn(mp, "Failed per-ag init: %d", error);
                goto out_free_dir;