]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: split xfs_initialize_perag
authorChristoph Hellwig <hch@lst.de>
Mon, 4 Nov 2024 04:18:36 +0000 (20:18 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 5 Nov 2024 21:38:27 +0000 (13:38 -0800)
Factor out a xfs_perag_alloc helper that allocates a single perag
structure.

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

index 9de48f3c71235dff797b20e381453c7d382b59f4..3e232b3d4c4262010f9288137b5d5e8da8ac75e0 100644 (file)
@@ -272,6 +272,10 @@ xfs_agino_range(
        return __xfs_agino_range(mp, xfs_ag_block_count(mp, agno), first, last);
 }
 
+/*
+ * Update the perag of the previous tail AG if it has been changed during
+ * recovery (i.e. recovery of a growfs).
+ */
 int
 xfs_update_last_ag_size(
        struct xfs_mount        *mp,
@@ -289,69 +293,57 @@ xfs_update_last_ag_size(
        return 0;
 }
 
-int
-xfs_initialize_perag(
+static int
+xfs_perag_alloc(
        struct xfs_mount        *mp,
-       xfs_agnumber_t          old_agcount,
-       xfs_agnumber_t          new_agcount,
-       xfs_rfsblock_t          dblocks,
-       xfs_agnumber_t          *maxagi)
+       xfs_agnumber_t          index,
+       xfs_agnumber_t          agcount,
+       xfs_rfsblock_t          dblocks)
 {
        struct xfs_perag        *pag;
-       xfs_agnumber_t          index;
        int                     error;
 
-       for (index = old_agcount; index < new_agcount; index++) {
-               pag = kzalloc(sizeof(*pag), GFP_KERNEL);
-               if (!pag) {
-                       error = -ENOMEM;
-                       goto out_unwind_new_pags;
-               }
-               pag->pag_agno = index;
-               pag->pag_mount = mp;
+       pag = kzalloc(sizeof(*pag), GFP_KERNEL);
+       if (!pag)
+               return -ENOMEM;
 
-               error = xa_insert(&mp->m_perags, index, pag, GFP_KERNEL);
-               if (error) {
-                       WARN_ON_ONCE(error == -EBUSY);
-                       goto out_free_pag;
-               }
+       pag->pag_agno = index;
+       pag->pag_mount = mp;
+
+       error = xa_insert(&mp->m_perags, index, pag, GFP_KERNEL);
+       if (error) {
+               WARN_ON_ONCE(error == -EBUSY);
+               goto out_free_pag;
+       }
 
 #ifdef __KERNEL__
-               /* Place kernel structure only init below this point. */
-               spin_lock_init(&pag->pag_ici_lock);
-               spin_lock_init(&pag->pagb_lock);
-               spin_lock_init(&pag->pag_state_lock);
-               INIT_DELAYED_WORK(&pag->pag_blockgc_work, xfs_blockgc_worker);
-               INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
-               xfs_defer_drain_init(&pag->pag_intents_drain);
-               init_waitqueue_head(&pag->pagb_wait);
-               pag->pagb_tree = RB_ROOT;
-               xfs_hooks_init(&pag->pag_rmap_update_hooks);
+       /* Place kernel structure only init below this point. */
+       spin_lock_init(&pag->pag_ici_lock);
+       spin_lock_init(&pag->pagb_lock);
+       spin_lock_init(&pag->pag_state_lock);
+       INIT_DELAYED_WORK(&pag->pag_blockgc_work, xfs_blockgc_worker);
+       INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
+       xfs_defer_drain_init(&pag->pag_intents_drain);
+       init_waitqueue_head(&pag->pagb_wait);
+       pag->pagb_tree = RB_ROOT;
+       xfs_hooks_init(&pag->pag_rmap_update_hooks);
 #endif /* __KERNEL__ */
 
-               error = xfs_buf_cache_init(&pag->pag_bcache);
-               if (error)
-                       goto out_remove_pag;
-
-               /* Active ref owned by mount indicates AG is online. */
-               atomic_set(&pag->pag_active_ref, 1);
-
-               /*
-                * Pre-calculated geometry
-                */
-               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);
-       }
+       error = xfs_buf_cache_init(&pag->pag_bcache);
+       if (error)
+               goto out_remove_pag;
 
-       index = xfs_set_inode_alloc(mp, new_agcount);
+       /* Active ref owned by mount indicates AG is online. */
+       atomic_set(&pag->pag_active_ref, 1);
 
-       if (maxagi)
-               *maxagi = index;
+       /*
+        * Pre-calculated geometry
+        */
+       pag->block_count = __xfs_ag_block_count(mp, index, agcount, dblocks);
+       pag->min_block = XFS_AGFL_BLOCK(mp);
+       __xfs_agino_range(mp, pag->block_count, &pag->agino_min,
+                       &pag->agino_max);
 
-       mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp);
        return 0;
 
 out_remove_pag:
@@ -359,8 +351,35 @@ out_remove_pag:
        pag = xa_erase(&mp->m_perags, index);
 out_free_pag:
        kfree(pag);
+       return error;
+}
+
+int
+xfs_initialize_perag(
+       struct xfs_mount        *mp,
+       xfs_agnumber_t          orig_agcount,
+       xfs_agnumber_t          new_agcount,
+       xfs_rfsblock_t          dblocks,
+       xfs_agnumber_t          *maxagi)
+{
+       xfs_agnumber_t          index;
+       int                     error;
+
+       if (orig_agcount >= new_agcount)
+               return 0;
+
+       for (index = orig_agcount; index < new_agcount; index++) {
+               error = xfs_perag_alloc(mp, index, new_agcount, dblocks);
+               if (error)
+                       goto out_unwind_new_pags;
+       }
+
+       *maxagi = xfs_set_inode_alloc(mp, new_agcount);
+       mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp);
+       return 0;
+
 out_unwind_new_pags:
-       xfs_free_perag_range(mp, old_agcount, index);
+       xfs_free_perag_range(mp, orig_agcount, index);
        return error;
 }
 
index e0f567d90debeedaf611022b04c143d542692094..8787823ae37f9f05e9915e38c0976cc1e29dcec1 100644 (file)
@@ -142,8 +142,8 @@ __XFS_AG_OPSTATE(prefers_metadata, PREFERS_METADATA)
 __XFS_AG_OPSTATE(allows_inodes, ALLOWS_INODES)
 __XFS_AG_OPSTATE(agfl_needs_reset, AGFL_NEEDS_RESET)
 
-int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t old_agcount,
-               xfs_agnumber_t agcount, xfs_rfsblock_t dcount,
+int xfs_initialize_perag(struct xfs_mount *mp, xfs_agnumber_t orig_agcount,
+               xfs_agnumber_t new_agcount, xfs_rfsblock_t dcount,
                xfs_agnumber_t *maxagi);
 void xfs_free_perag_range(struct xfs_mount *mp, xfs_agnumber_t first_agno,
                xfs_agnumber_t end_agno);
index 5180cbf5a90b4bef8ffd448ef753c1c667e0cf2e..c627ad3a3bbbfdf56dcce3b73aaea8fb11db6c0e 100644 (file)
@@ -724,9 +724,8 @@ xlog_recover_do_primary_sb_buffer(
        }
 
        /*
-        * Growfs can also grow the last existing AG.  In this case we also need
-        * to update the length in the in-core perag structure and values
-        * depending on it.
+        * If the last AG was grown or shrunk, we also need to update the
+        * length in the in-core perag structure and values depending on it.
         */
        error = xfs_update_last_ag_size(mp, orig_agcount);
        if (error)