xfs: dynamically allocate cursors based on maxlevels
authorDarrick J. Wong <djwong@kernel.org>
Thu, 16 Sep 2021 19:27:24 +0000 (12:27 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 19 Oct 2021 18:45:15 +0000 (11:45 -0700)
To support future btree code, we need to be able to size btree cursors
dynamically for very large btrees.  Switch the maxlevels computation to
use the precomputed values in the superblock, and create cursors that
can handle a certain height.  For now, we retain the btree cursor cache
that can handle up to 9-level btrees, though a subsequent patch
introduces separate caches for each btree type, where each cache's
objects will be exactly tall enough to handle the specific btree type.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
fs/xfs/libxfs/xfs_alloc_btree.c
fs/xfs/libxfs/xfs_bmap_btree.c
fs/xfs/libxfs/xfs_btree.h
fs/xfs/libxfs/xfs_ialloc_btree.c
fs/xfs/libxfs/xfs_refcount_btree.c
fs/xfs/libxfs/xfs_rmap_btree.c
fs/xfs/xfs_super.c

index c644b11132f6c0b2c6f95d35e76d031f910b43a8..f14bad21503fe329cbcbf487afc9945772d06c44 100644 (file)
@@ -477,7 +477,7 @@ xfs_allocbt_init_common(
 
        ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT);
 
-       cur = xfs_btree_alloc_cursor(mp, tp, btnum);
+       cur = xfs_btree_alloc_cursor(mp, tp, btnum, mp->m_ag_maxlevels);
        cur->bc_ag.abt.active = false;
 
        if (btnum == XFS_BTNUM_CNT) {
index a06987e36db5ad353b5dfa1287158e0f4c675a81..b90122de0df0a1d1582ba44026b376bb543c36f1 100644 (file)
@@ -552,7 +552,8 @@ xfs_bmbt_init_cursor(
        struct xfs_btree_cur    *cur;
        ASSERT(whichfork != XFS_COW_FORK);
 
-       cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP);
+       cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_BMAP,
+                       mp->m_bm_maxlevels[whichfork]);
        cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
        cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_bmbt_2);
 
index ed0b7d5ab3a3d0c7071203358767619143142069..b46cd98309fa2aaa0be8f936ee2ae96a0fedc4e6 100644 (file)
@@ -94,6 +94,12 @@ uint32_t xfs_btree_magic(int crc, xfs_btnum_t btnum);
 
 #define        XFS_BTREE_MAXLEVELS     9       /* max of all btrees */
 
+/*
+ * The btree cursor zone hands out cursors that can handle up to this many
+ * levels.  This is the known maximum for all btree types.
+ */
+#define XFS_BTREE_CUR_CACHE_MAXLEVELS  (9)
+
 struct xfs_btree_ops {
        /* size of the key and record structures */
        size_t  key_len;
@@ -583,15 +589,18 @@ static inline struct xfs_btree_cur *
 xfs_btree_alloc_cursor(
        struct xfs_mount        *mp,
        struct xfs_trans        *tp,
-       xfs_btnum_t             btnum)
+       xfs_btnum_t             btnum,
+       uint8_t                 maxlevels)
 {
        struct xfs_btree_cur    *cur;
 
+       ASSERT(maxlevels <= XFS_BTREE_CUR_CACHE_MAXLEVELS);
+
        cur = kmem_cache_zalloc(xfs_btree_cur_zone, GFP_NOFS | __GFP_NOFAIL);
        cur->bc_tp = tp;
        cur->bc_mp = mp;
        cur->bc_btnum = btnum;
-       cur->bc_maxlevels = XFS_BTREE_MAXLEVELS;
+       cur->bc_maxlevels = maxlevels;
 
        return cur;
 }
index c8fea6a464d5a3f39927130ffd5b41a40510bebf..3a5a24648b87320ef03b024274430a25302bce58 100644 (file)
@@ -432,7 +432,8 @@ xfs_inobt_init_common(
 {
        struct xfs_btree_cur    *cur;
 
-       cur = xfs_btree_alloc_cursor(mp, tp, btnum);
+       cur = xfs_btree_alloc_cursor(mp, tp, btnum,
+                       M_IGEO(mp)->inobt_maxlevels);
        if (btnum == XFS_BTNUM_INO) {
                cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_ibt_2);
                cur->bc_ops = &xfs_inobt_ops;
index 48c45e31d89703334653ca9803ac596f9978a155..995b0d86ddc05785c097b4a146ef1115bc0a6e78 100644 (file)
@@ -322,7 +322,8 @@ xfs_refcountbt_init_common(
 
        ASSERT(pag->pag_agno < mp->m_sb.sb_agcount);
 
-       cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_REFC);
+       cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_REFC,
+                       mp->m_refc_maxlevels);
        cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2);
 
        cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;
index f3c4d0965cc9ce7b694354d63841013cf2ce0b75..1b48b7b3ee303b94707a3aef86b7d577960ef1b0 100644 (file)
@@ -452,7 +452,8 @@ xfs_rmapbt_init_common(
        struct xfs_btree_cur    *cur;
 
        /* Overlapping btree; 2 keys per pointer. */
-       cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_RMAP);
+       cur = xfs_btree_alloc_cursor(mp, tp, XFS_BTNUM_RMAP,
+                       mp->m_rmap_maxlevels);
        cur->bc_flags = XFS_BTREE_CRC_BLOCKS | XFS_BTREE_OVERLAPPING;
        cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_rmap_2);
        cur->bc_ops = &xfs_rmapbt_ops;
index 30bae0657343e5d03b4f78ac30688d7a13780e1c..2a535a8bc3c0835a6dc2a1328320e742a6418fe8 100644 (file)
@@ -1966,8 +1966,8 @@ xfs_init_zones(void)
                goto out_destroy_log_ticket_zone;
 
        xfs_btree_cur_zone = kmem_cache_create("xfs_btree_cur",
-                               xfs_btree_cur_sizeof(XFS_BTREE_MAXLEVELS),
-                                              0, 0, NULL);
+                       xfs_btree_cur_sizeof(XFS_BTREE_CUR_CACHE_MAXLEVELS),
+                       0, 0, NULL);
        if (!xfs_btree_cur_zone)
                goto out_destroy_bmap_free_item_zone;