]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: hoist the node iroot update code out of xfs_btree_kill_iroot
authorDarrick J. Wong <djwong@kernel.org>
Wed, 3 Jul 2024 21:22:14 +0000 (14:22 -0700)
committerChristoph Hellwig <hch@lst.de>
Sun, 11 Aug 2024 06:35:54 +0000 (08:35 +0200)
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>
libxfs/xfs_btree.c

index 76262d6b45c6bf763c30ea09bf429884dc6cde65..5917e6e63942140131030d1d62fbc239b45e7844 100644 (file)
@@ -3730,6 +3730,63 @@ 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;
+       int                     diff;
+
+       /*
+        * 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.
+        */
+       diff = numrecs - cur->bc_ops->get_maxrecs(cur, level);
+       xfs_btree_iroot_realloc(cur, diff);
+       block = xfs_btree_get_iroot(cur);
+
+       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.
  *
@@ -3742,24 +3799,16 @@ STATIC int
 xfs_btree_kill_iroot(
        struct xfs_btree_cur    *cur)
 {
-       int                     whichfork = cur->bc_ino.whichfork;
        struct xfs_inode        *ip = cur->bc_ino.ip;
-       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        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                     index;
        int                     numrecs;
        int                     error;
 #ifdef DEBUG
        union xfs_btree_ptr     ptr;
 #endif
-       int                     i;
 
        ASSERT(cur->bc_ops->type == XFS_BTREE_TYPE_INODE);
        ASSERT(cur->bc_nlevels > 1);
@@ -3799,39 +3848,16 @@ xfs_btree_kill_iroot(
        ASSERT(xfs_btree_ptr_is_null(cur, &ptr));
 #endif
 
-       index = numrecs - cur->bc_ops->get_maxrecs(cur, level);
-       if (index) {
-               xfs_btree_iroot_realloc(cur, index);
-               block = ifp->if_broot;
-       }
-
-       be16_add_cpu(&block->bb_numrecs, index);
-       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;
 }