]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: tidy up xfs_iroot_realloc
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:20:12 +0000 (16:20 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 23 Dec 2024 21:06:01 +0000 (13:06 -0800)
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>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_inode_fork.c

index 1158ca48626b718a29793063f6d634061e47ed84..7f865479c4159fd0d042217fa3556601006de386 100644 (file)
@@ -382,33 +382,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);
@@ -422,13 +421,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;
@@ -443,52 +442,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));
 }