]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: hoist the node iroot update code out of xfs_btree_kill_iroot
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:20:17 +0000 (16:20 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 23 Dec 2024 21:06:02 +0000 (13:06 -0800)
In preparation for allowing records in an inode btree root, hoist the
code that copies keyptrs from an existing node child into the root block
to a separate function.  Remove some unnecessary conditionals and clean
up a few function calls in the new function.  Note that this change
reorders the ->free_block call with respect to the change in bc_nlevels
to make it easier to support inode root leaf blocks in the next patch.

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

index ed09eeee916160fed0d889639cdc98b177b6f6ee..e83a8de5fb8746f264192de01c67c0fb31fea3a2 100644 (file)
@@ -3726,6 +3726,60 @@ error0:
        return error;
 }
 
+/*
+ * Move the keyptrs from a child node block to the root block.
+ *
+ * Since the keyptr size does not change, all we have to do is increase the
+ * tree height, copy the keyptrs to the new internal node (cblock), shrink
+ * the root, and copy the pointers there.
+ */
+STATIC int
+xfs_btree_demote_node_child(
+       struct xfs_btree_cur    *cur,
+       struct xfs_btree_block  *cblock,
+       int                     level,
+       int                     numrecs)
+{
+       struct xfs_btree_block  *block;
+       union xfs_btree_key     *ckp;
+       union xfs_btree_key     *kp;
+       union xfs_btree_ptr     *cpp;
+       union xfs_btree_ptr     *pp;
+       int                     i;
+       int                     error;
+
+       /*
+        * Adjust the root btree node size and the record count to match the
+        * doomed child so that we can copy the keyptrs ahead of changing the
+        * tree shape.
+        */
+       block = cur->bc_ops->broot_realloc(cur, numrecs);
+
+       xfs_btree_set_numrecs(block, numrecs);
+       ASSERT(block->bb_numrecs == cblock->bb_numrecs);
+
+       /* Copy keys from the doomed block. */
+       kp = xfs_btree_key_addr(cur, 1, block);
+       ckp = xfs_btree_key_addr(cur, 1, cblock);
+       xfs_btree_copy_keys(cur, kp, ckp, numrecs);
+
+       /* Copy pointers from the doomed block. */
+       pp = xfs_btree_ptr_addr(cur, 1, block);
+       cpp = xfs_btree_ptr_addr(cur, 1, cblock);
+       for (i = 0; i < numrecs; i++) {
+               error = xfs_btree_debug_check_ptr(cur, cpp, i, level - 1);
+               if (error)
+                       return error;
+       }
+       xfs_btree_copy_ptrs(cur, pp, cpp, numrecs);
+
+       /* Decrease tree height, adjusting the root block level to match. */
+       cur->bc_levels[level - 1].bp = NULL;
+       be16_add_cpu(&block->bb_level, -1);
+       cur->bc_nlevels--;
+       return 0;
+}
+
 /*
  * Try to merge a non-leaf block back into the inode root.
  *
@@ -3741,10 +3795,6 @@ xfs_btree_kill_iroot(
        struct xfs_inode        *ip = cur->bc_ino.ip;
        struct xfs_btree_block  *block;
        struct xfs_btree_block  *cblock;
-       union xfs_btree_key     *kp;
-       union xfs_btree_key     *ckp;
-       union xfs_btree_ptr     *pp;
-       union xfs_btree_ptr     *cpp;
        struct xfs_buf          *cbp;
        int                     level;
        int                     numrecs;
@@ -3752,7 +3802,6 @@ xfs_btree_kill_iroot(
 #ifdef DEBUG
        union xfs_btree_ptr     ptr;
 #endif
-       int                     i;
 
        ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE);
        ASSERT(cur->bc_nlevels > 1);
@@ -3792,35 +3841,16 @@ xfs_btree_kill_iroot(
        ASSERT(xfs_btree_ptr_is_null(cur, &ptr));
 #endif
 
-       block = cur->bc_ops->broot_realloc(cur, numrecs);
-
-       block->bb_numrecs = be16_to_cpu(numrecs);
-       ASSERT(block->bb_numrecs == cblock->bb_numrecs);
-
-       kp = xfs_btree_key_addr(cur, 1, block);
-       ckp = xfs_btree_key_addr(cur, 1, cblock);
-       xfs_btree_copy_keys(cur, kp, ckp, numrecs);
-
-       pp = xfs_btree_ptr_addr(cur, 1, block);
-       cpp = xfs_btree_ptr_addr(cur, 1, cblock);
-
-       for (i = 0; i < numrecs; i++) {
-               error = xfs_btree_debug_check_ptr(cur, cpp, i, level - 1);
-               if (error)
-                       return error;
-       }
-
-       xfs_btree_copy_ptrs(cur, pp, cpp, numrecs);
+       error = xfs_btree_demote_node_child(cur, cblock, level, numrecs);
+       if (error)
+               return error;
 
        error = xfs_btree_free_block(cur, cbp);
        if (error)
                return error;
 
-       cur->bc_levels[level - 1].bp = NULL;
-       be16_add_cpu(&block->bb_level, -1);
        xfs_trans_log_inode(cur->bc_tp, ip,
                XFS_ILOG_CORE | xfs_ilog_fbroot(cur->bc_ino.whichfork));
-       cur->bc_nlevels--;
 out0:
        return 0;
 }