]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: make xfs_iroot_realloc take the new numrecs instead of deltas
authorDarrick J. Wong <djwong@kernel.org>
Tue, 15 Oct 2024 19:44:29 +0000 (12:44 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 1 Nov 2024 20:44:55 +0000 (13:44 -0700)
Change the calling signature of xfs_iroot_realloc to take the ifork and
the new number of records in the btree block, not a diff against the
current number.  This will make the callsites easier to understand.

Note that this function is misnamed because it is very specific to the
single type of inode-rooted btree supported.  This will be addressed in
a subsequent patch.

Return the new btree root to reduce the amount of code clutter.

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

index 552d292bf354122c4f7e4f56f213838215384b08..d8b1bfb4f408b97e813bda56a6e9ffcdcfc99cc2 100644 (file)
@@ -609,7 +609,7 @@ xfs_bmap_btree_to_extents(
        xfs_trans_binval(tp, cbp);
        if (cur->bc_levels[0].bp == cbp)
                cur->bc_levels[0].bp = NULL;
-       xfs_iroot_realloc(ip, -1, whichfork);
+       xfs_iroot_realloc(ip, ifp, 0);
        ASSERT(ifp->if_broot == NULL);
        ifp->if_format = XFS_DINODE_FMT_EXTENTS;
        *logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
@@ -653,12 +653,11 @@ xfs_bmap_extents_to_btree(
         * Make space in the inode incore. This needs to be undone if we fail
         * to expand the root.
         */
-       xfs_iroot_realloc(ip, 1, whichfork);
+       block = xfs_iroot_realloc(ip, ifp, 1);
 
        /*
         * Fill in the root.
         */
-       block = ifp->if_broot;
        xfs_bmbt_init_block(ip, block, NULL, 1, 1);
        /*
         * Need a cursor.  Can't allocate until bb_level is filled in.
@@ -740,7 +739,7 @@ xfs_bmap_extents_to_btree(
 out_unreserve_dquot:
        xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L);
 out_root_realloc:
-       xfs_iroot_realloc(ip, -1, whichfork);
+       xfs_iroot_realloc(ip, ifp, 0);
        ifp->if_format = XFS_DINODE_FMT_EXTENTS;
        ASSERT(ifp->if_broot == NULL);
        xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
index 3d870f3f4a5165701f521c79eeaf861dc70e7253..513b921ada95e643cef35193c77246db7def1fb8 100644 (file)
@@ -3159,9 +3159,7 @@ xfs_btree_new_iroot(
 
        xfs_btree_copy_ptrs(cur, pp, &nptr, 1);
 
-       xfs_iroot_realloc(cur->bc_ino.ip,
-                         1 - xfs_btree_get_numrecs(cblock),
-                         cur->bc_ino.whichfork);
+       xfs_iroot_realloc(cur->bc_ino.ip, xfs_btree_ifork_ptr(cur), 1);
 
        xfs_btree_setbuf(cur, level, cbp);
 
@@ -3345,7 +3343,8 @@ xfs_btree_make_block_unfull(
 
                if (numrecs < cur->bc_ops->get_dmaxrecs(cur, level)) {
                        /* A root block that can be made bigger. */
-                       xfs_iroot_realloc(ip, 1, cur->bc_ino.whichfork);
+                       xfs_iroot_realloc(ip, xfs_btree_ifork_ptr(cur),
+                                       numrecs + 1);
                        *stat = 1;
                } else {
                        /* A root block that needs replacing */
@@ -3686,9 +3685,7 @@ 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;
@@ -3697,7 +3694,6 @@ xfs_btree_kill_iroot(
        union xfs_btree_ptr     *cpp;
        struct xfs_buf          *cbp;
        int                     level;
-       int                     index;
        int                     numrecs;
        int                     error;
 #ifdef DEBUG
@@ -3743,14 +3739,10 @@ 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_iroot_realloc(cur->bc_ino.ip, index,
-                                 cur->bc_ino.whichfork);
-               block = ifp->if_broot;
-       }
+       block = xfs_iroot_realloc(cur->bc_ino.ip, xfs_btree_ifork_ptr(cur),
+                       numrecs);
 
-       be16_add_cpu(&block->bb_numrecs, index);
+       block->bb_numrecs = be16_to_cpu(numrecs);
        ASSERT(block->bb_numrecs == cblock->bb_numrecs);
 
        kp = xfs_btree_key_addr(cur, 1, block);
@@ -3930,10 +3922,11 @@ xfs_btree_delrec(
        /*
         * We're at the root level.  First, shrink the root block in-memory.
         * Try to get rid of the next level down.  If we can't then there's
-        * nothing left to do.
+        * nothing left to do.  numrecs was decremented above.
         */
        if (xfs_btree_at_iroot(cur, level)) {
-               xfs_iroot_realloc(cur->bc_ino.ip, -1, cur->bc_ino.whichfork);
+               xfs_iroot_realloc(cur->bc_ino.ip, xfs_btree_ifork_ptr(cur),
+                               numrecs);
 
                error = xfs_btree_kill_iroot(cur);
                if (error)
index d72b7f66acb93ff966cc95531dfb604efdf86753..ef6ee29ab8cb59eb8e20559f8084f0141e4c7c83 100644 (file)
@@ -407,12 +407,10 @@ __xfs_broot_realloc(
 }
 
 /*
- * Reallocate the space for if_broot based on the number of records
- * being added or deleted as indicated in rec_diff.  Move the records
- * and pointers in if_broot to fit the new size.  When shrinking this
- * will eliminate holes between the records and pointers created by
- * the caller.  When growing this will create holes to be filled in
- * by the caller.
+ * Reallocate the space for if_broot based on the number of records.  Move the
+ * records and pointers in if_broot to fit the new size.  When shrinking this
+ * will eliminate holes between the records and pointers created by the caller.
+ * When growing this will create holes to be filled in by the caller.
  *
  * The caller must not request to add more records than would fit in
  * the on-disk inode root.  If the if_broot is currently NULL, then
@@ -421,40 +419,48 @@ __xfs_broot_realloc(
  * it can go to zero.
  *
  * ip -- the inode whose if_broot area is changing
- * ext_diff -- the change in the number of records, positive or negative,
- *      requested for the if_broot array.
+ * ifp -- which inode fork to change
+ * new_numrecs -- the new number of records requested for the if_broot array
+ *
+ * Returns the incore btree root block.
  */
-void
+struct xfs_btree_block *
 xfs_iroot_realloc(
        struct xfs_inode        *ip,
-       int                     rec_diff,
-       int                     whichfork)
+       struct xfs_ifork        *ifp,
+       unsigned int            new_numrecs)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
        char                    *np;
        char                    *op;
-       size_t                  new_size;
-       short                   old_size = ifp->if_broot_bytes;
-       int                     cur_max;
-       int                     new_max;
+       unsigned int            new_size;
+       unsigned int            old_size = ifp->if_broot_bytes;
 
        /*
-        * Handle the degenerate case quietly.
+        * Block mapping btrees do not support storing zero records; if this
+        * happens, the fork is being changed to FMT_EXTENTS.  Free the broot
+        * and get out.
         */
-       if (rec_diff == 0)
-               return;
+       if (new_numrecs == 0) {
+               xfs_broot_free(ifp);
+               return NULL;
+       }
+
+       new_size = xfs_bmap_broot_space_calc(mp, new_numrecs);
+
+       /* Handle the nop case quietly. */
+       if (new_size == old_size)
+               return ifp->if_broot;
+
+       if (new_size > old_size) {
+               unsigned int    old_numrecs;
 
-       if (rec_diff > 0) {
                /*
                 * If there wasn't any memory allocated before, just
                 * allocate it now and get out.
                 */
-               if (old_size == 0) {
-                       new_size = xfs_bmap_broot_space_calc(mp, rec_diff);
-                       xfs_broot_realloc(ifp, new_size);
-                       return;
-               }
+               if (old_size == 0)
+                       return xfs_broot_realloc(ifp, new_size);
 
                /*
                 * If there is already an existing if_broot, then we need
@@ -462,38 +468,23 @@ 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, old_size, false);
-               new_max = cur_max + rec_diff;
-               new_size = xfs_bmap_broot_space_calc(mp, new_max);
-
+               old_numrecs = xfs_bmbt_maxrecs(mp, old_size, false);
                xfs_broot_realloc(ifp, new_size);
                op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1,
                                                     old_size);
                np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1,
                                                     (int)new_size);
                ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <=
-                       xfs_inode_fork_size(ip, whichfork));
-               memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t));
-               return;
+                       xfs_inode_fork_size(ip, xfs_ifork_which(ip, ifp)));
+               memmove(np, op, old_numrecs * (uint)sizeof(xfs_fsblock_t));
+               return ifp->if_broot;
        }
 
        /*
-        * rec_diff is less than 0.  In this case, we are shrinking the
-        * if_broot buffer.  It must already exist.  If we go to zero
-        * records, just get rid of the root and clear the status bit.
+        * We're reducing, but not totally eliminating, numrecs.  In this case,
+        * we are shrinking the if_broot buffer, so it must already exist.
         */
-       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) {
-               xfs_broot_free(ifp);
-               return;
-       }
+       ASSERT(ifp->if_broot != NULL && old_size > 0 && new_size > 0);
 
        /*
         * Shrink the btree root by moving the bmbt pointers, since they are
@@ -503,11 +494,12 @@ xfs_iroot_realloc(
        op = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1, old_size);
        np = (char *)xfs_bmap_broot_ptr_addr(mp, ifp->if_broot, 1,
                                             (int)new_size);
-       memmove(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
+       memmove(np, op, new_numrecs * (uint)sizeof(xfs_fsblock_t));
 
        xfs_broot_realloc(ifp, new_size);
        ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <=
-              xfs_inode_fork_size(ip, whichfork));
+              xfs_inode_fork_size(ip, xfs_ifork_which(ip, ifp)));
+       return ifp->if_broot;
 }
 
 
index fc5efdeb0d7b6a02ee1406fdf21adcc9fd3124dc..5fb33773de8fc2c2867b166ff295798482b357e8 100644 (file)
@@ -185,7 +185,9 @@ xfs_broot_free(struct xfs_ifork *ifp)
        __xfs_broot_realloc(ifp, 0, 0);
 }
 
-void           xfs_iroot_realloc(struct xfs_inode *, int, int);
+struct xfs_btree_block *xfs_iroot_realloc(struct xfs_inode *ip,
+                               struct xfs_ifork *ifp,
+                               unsigned int new_numrecs);
 int            xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int);
 int            xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *,
                                  int);