xfs: tidy up xfs_iroot_realloc
authorDarrick J. Wong <djwong@kernel.org>
Fri, 30 Aug 2024 00:17:48 +0000 (17:17 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 9 Oct 2024 23:29:16 +0000 (16:29 -0700)
Tidy up this function a bit before we start refactoring the memory
handling and move the function to the bmbt code.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/xfs_inode_fork.c

index a71a5e98bf408bc6330793a8e6c74c33dc9769a4..8d7d943311e9a0a1b79d069a467f488b7e263eb4 100644 (file)
@@ -380,33 +380,32 @@ xfs_iformat_attr_fork(
  */
 void
 xfs_iroot_realloc(
-       xfs_inode_t             *ip,
+       struct xfs_inode        *ip,
        int                     rec_diff,
        int                     whichfork)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       int                     cur_max;
-       struct xfs_ifork        *ifp;
+       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        struct xfs_btree_block  *new_broot;
-       int                     new_max;
-       size_t                  new_size;
        char                    *np;
        char                    *op;
+       size_t                  new_size;
+       short                   old_size = ifp->if_broot_bytes;
+       int                     cur_max;
+       int                     new_max;
 
        /*
         * Handle the degenerate case quietly.
         */
-       if (rec_diff == 0) {
+       if (rec_diff == 0)
                return;
-       }
 
-       ifp = xfs_ifork_ptr(ip, whichfork);
        if (rec_diff > 0) {
                /*
                 * If there wasn't any memory allocated before, just
                 * allocate it now and get out.
                 */
-               if (ifp->if_broot_bytes == 0) {
+               if (old_size == 0) {
                        new_size = xfs_bmap_broot_space_calc(mp, rec_diff);
                        ifp->if_broot = kmalloc(new_size,
                                                GFP_KERNEL | __GFP_NOFAIL);
@@ -420,13 +419,13 @@ xfs_iroot_realloc(
                 * location.  The records don't change location because
                 * they are kept butted up against the btree block header.
                 */
-               cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, false);
+               cur_max = xfs_bmbt_maxrecs(mp, old_size, false);
                new_max = cur_max + rec_diff;
                new_size = xfs_bmap_broot_space_calc(mp, new_max);
                ifp->if_broot = krealloc(ifp->if_broot, new_size,
                                         GFP_KERNEL | __GFP_NOFAIL);
                op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1,
-                                                    ifp->if_broot_bytes);
+                                                    old_size);
                np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1,
                                                     (int)new_size);
                ifp->if_broot_bytes = (int)new_size;
@@ -441,52 +440,50 @@ xfs_iroot_realloc(
         * if_broot buffer.  It must already exist.  If we go to zero
         * records, just get rid of the root and clear the status bit.
         */
-       ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
-       cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, false);
+       ASSERT(ifp->if_broot != NULL && old_size > 0);
+       cur_max = xfs_bmbt_maxrecs(mp, old_size, false);
        new_max = cur_max + rec_diff;
        ASSERT(new_max >= 0);
        if (new_max > 0)
                new_size = xfs_bmap_broot_space_calc(mp, new_max);
        else
                new_size = 0;
-       if (new_size > 0) {
-               new_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL);
-               /*
-                * First copy over the btree block header.
-                */
-               memcpy(new_broot, ifp->if_broot,
-                       xfs_bmbt_block_len(ip->i_mount));
-       } else {
-               new_broot = NULL;
+       if (new_size == 0) {
+               ifp->if_broot = NULL;
+               ifp->if_broot_bytes = 0;
+               return;
        }
 
        /*
-        * Only copy the keys and pointers if there are any.
+        * Shrink the btree root by allocating a smaller object and copying the
+        * fields from the old object to the new object.  krealloc does nothing
+        * if we realloc downwards.
         */
-       if (new_max > 0) {
-               /*
-                * First copy the keys.
-                */
-               op = (char *)xfs_bmbt_key_addr(mp, ifp->if_broot, 1);
-               np = (char *)xfs_bmbt_key_addr(mp, new_broot, 1);
-               memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_key_t));
+       new_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL);
+       /*
+        * First copy over the btree block header.
+        */
+       memcpy(new_broot, ifp->if_broot, xfs_bmbt_block_len(ip->i_mount));
+
+       /*
+        * First copy the keys.
+        */
+       op = (char *)xfs_bmbt_key_addr(mp, ifp->if_broot, 1);
+       np = (char *)xfs_bmbt_key_addr(mp, new_broot, 1);
+       memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_key_t));
+
+       /*
+        * Then copy the pointers.
+        */
+       op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size);
+       np = (char *)xfs_bmap_broot_ptr_addr(mp, new_broot, 1, (int)new_size);
+       memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
 
-               /*
-                * Then copy the pointers.
-                */
-               op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1,
-                                                    ifp->if_broot_bytes);
-               np = (char *)xfs_bmap_broot_ptr_addr(mp, new_broot, 1,
-                                                    (int)new_size);
-               memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
-       }
        kfree(ifp->if_broot);
        ifp->if_broot = new_broot;
        ifp->if_broot_bytes = (int)new_size;
-       if (ifp->if_broot)
-               ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <=
-                       xfs_inode_fork_size(ip, whichfork));
-       return;
+       ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <=
+              xfs_inode_fork_size(ip, whichfork));
 }