]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: make xfs_iroot_realloc take the new numrecs instead of deltas
authorDarrick J. Wong <djwong@kernel.org>
Mon, 23 Sep 2024 20:41:45 +0000 (13:41 -0700)
committerChristoph Hellwig <hch@lst.de>
Wed, 9 Oct 2024 13:55:44 +0000 (15:55 +0200)
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>
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
fs/xfs/xfs_inode.h

index f2efab1e8a42afb686c4073a6941553f44430487..433810491175374b856b64df81e7318bb439e320 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, ifp, 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, 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.
@@ -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, ifp, 0);
        ifp->if_format = XFS_DINODE_FMT_EXTENTS;
        ASSERT(ifp->if_broot == NULL);
        xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
index 37f2c91e3191029ca4538bfe558b6ffb6695eb01..4cc63e499474889d3457015b734132095d2c2fdf 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, xfs_btree_ifork_ptr(cur), 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, xfs_btree_ifork_ptr(cur),
+                                       numrecs + 1);
                        *stat = 1;
                } else {
                        /* A root block that needs replacing */
@@ -3688,9 +3687,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;
@@ -3699,7 +3696,6 @@ xfs_btree_kill_iroot(
        union xfs_btree_ptr     *cpp;
        struct xfs_buf          *cbp;
        int                     level;
-       int                     index;
        int                     numrecs;
        int                     error;
 #ifdef DEBUG
@@ -3745,14 +3741,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);
@@ -3932,10 +3924,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 3c5fd5296d418c01ef077805fff09ed3d4a550fa..5eacd7a77f2c1351578f55255cb2285fb66a4f20 100644 (file)
@@ -409,12 +409,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
@@ -423,40 +421,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
@@ -464,38 +470,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
@@ -505,11 +496,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);
index 11c866d3c959a7fb256ef58d0961a098cb3bc91b..251a3f0dc0db91b09d736636886358a8ce2c1a78 100644 (file)
@@ -126,6 +126,24 @@ xfs_ifork_ptr(
        }
 }
 
+static inline int
+xfs_ifork_which(
+       struct xfs_inode        *ip,
+       struct xfs_ifork        *ifp)
+{
+       ASSERT(ifp != NULL);
+
+       if (ifp == &ip->i_df)
+               return XFS_DATA_FORK;
+       if (ifp == &ip->i_af)
+               return XFS_ATTR_FORK;
+       if (ifp == ip->i_cowfp)
+               return XFS_COW_FORK;
+
+       ASSERT(0);
+       return -2; /* unknown */
+}
+
 static inline unsigned int xfs_inode_fork_boff(struct xfs_inode *ip)
 {
        return ip->i_forkoff << 3;