]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: make xfs_iroot_realloc take the new numrecs instead of deltas
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:20:14 +0000 (16:20 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 23 Dec 2024 21:06:02 +0000 (13:06 -0800)
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>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_btree.c
fs/xfs/libxfs/xfs_inode_fork.c
fs/xfs/libxfs/xfs_inode_fork.h

index 5255f93bae31f39371b09ac5bf66ad859b313b93..8ab38f07cb78dde7e50641bdd19e82a2e5ea2c60 100644 (file)
@@ -615,7 +615,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, whichfork, 0);
        ASSERT(ifp->if_broot == NULL);
        ifp->if_format = XFS_DINODE_FMT_EXTENTS;
        *logflagsp |= XFS_ILOG_CORE | xfs_ilog_fext(whichfork);
@@ -659,12 +659,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, whichfork, 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.
@@ -746,7 +745,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, whichfork, 0);
        ifp->if_format = XFS_DINODE_FMT_EXTENTS;
        ASSERT(ifp->if_broot == NULL);
        xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
index 68ee1c299c25fd69dbd35d86174f737330792732..5714bec26c2084280afdd2f1e5c75152d0158457 100644 (file)
@@ -3161,9 +3161,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, cur->bc_ino.whichfork, 1);
 
        xfs_btree_setbuf(cur, level, cbp);
 
@@ -3347,7 +3345,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, cur->bc_ino.whichfork,
+                                       numrecs + 1);
                        *stat = 1;
                } else {
                        /* A root block that needs replacing */
@@ -3705,9 +3704,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;
@@ -3716,7 +3713,6 @@ xfs_btree_kill_iroot(
        union xfs_btree_ptr     *cpp;
        struct xfs_buf          *cbp;
        int                     level;
-       int                     index;
        int                     numrecs;
        int                     error;
 #ifdef DEBUG
@@ -3762,14 +3758,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, cur->bc_ino.whichfork,
+                       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);
@@ -3949,10 +3941,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, cur->bc_ino.whichfork,
+                               numrecs);
 
                error = xfs_btree_kill_iroot(cur);
                if (error)
index 294c3c5556836ef0582cafaed5f6bc405bd73cd8..53bfdf422ad82067b43f61f82c086c2f5cb54ee7 100644 (file)
@@ -423,12 +423,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
@@ -437,40 +435,47 @@ 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.
+ * whichfork -- 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)
+       int                     whichfork,
+       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)
+               return xfs_broot_realloc(ifp, 0);
+
+       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
@@ -478,10 +483,7 @@ 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);
@@ -489,27 +491,15 @@ xfs_iroot_realloc(
                                                     (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;
+               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_realloc(ifp, 0);
-               return;
-       }
+       ASSERT(ifp->if_broot != NULL && old_size > 0 && new_size > 0);
 
        /*
         * Shrink the btree root by moving the bmbt pointers, since they are
@@ -519,11 +509,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));
+       return ifp->if_broot;
 }
 
 
index e3c5c9121044fdc7b623382859555b0af8835e62..d05eb0bad864e13b6032ee3ca4efd66d7001ebb3 100644 (file)
@@ -175,7 +175,8 @@ struct xfs_btree_block *xfs_broot_alloc(struct xfs_ifork *ifp,
 struct xfs_btree_block *xfs_broot_realloc(struct xfs_ifork *ifp,
                                size_t new_size);
 
-void           xfs_iroot_realloc(struct xfs_inode *, int, int);
+struct xfs_btree_block *xfs_iroot_realloc(struct xfs_inode *ip, int whichfork,
+                               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);