]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: compute rtrmap btree max levels when reflink enabled
authorDarrick J. Wong <djwong@kernel.org>
Mon, 24 Feb 2025 18:21:54 +0000 (10:21 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 25 Feb 2025 17:15:59 +0000 (09:15 -0800)
Source kernel commit: c2694ff678c9b667ab4cb7c0b45d45309c4dd64b

Compute the maximum possible height of the realtime rmap btree when
reflink is enabled.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/xfs_rtrmap_btree.c

index 10055110b8cf42e09ff7fc0b6c205c48359e4682..d897d140efa75344374d6ba73ee8a82176b97d82 100644 (file)
@@ -717,6 +717,7 @@ xfs_rtrmapbt_maxrecs(
 unsigned int
 xfs_rtrmapbt_maxlevels_ondisk(void)
 {
+       unsigned long long      max_dblocks;
        unsigned int            minrecs[2];
        unsigned int            blocklen;
 
@@ -725,8 +726,20 @@ xfs_rtrmapbt_maxlevels_ondisk(void)
        minrecs[0] = xfs_rtrmapbt_block_maxrecs(blocklen, true) / 2;
        minrecs[1] = xfs_rtrmapbt_block_maxrecs(blocklen, false) / 2;
 
-       /* We need at most one record for every block in an rt group. */
-       return xfs_btree_compute_maxlevels(minrecs, XFS_MAX_RGBLOCKS);
+       /*
+        * Compute the asymptotic maxlevels for an rtrmapbt on any rtreflink fs.
+        *
+        * On a reflink filesystem, each block in an rtgroup can have up to
+        * 2^32 (per the refcount record format) owners, which means that
+        * theoretically we could face up to 2^64 rmap records.  However, we're
+        * likely to run out of blocks in the data device long before that
+        * happens, which means that we must compute the max height based on
+        * what the btree will look like if it consumes almost all the blocks
+        * in the data device due to maximal sharing factor.
+        */
+       max_dblocks = -1U; /* max ag count */
+       max_dblocks *= XFS_MAX_CRC_AG_BLOCKS;
+       return xfs_btree_space_to_height(minrecs, max_dblocks);
 }
 
 int __init
@@ -765,9 +778,20 @@ xfs_rtrmapbt_compute_maxlevels(
         * maximum height is constrained by the size of the data device and
         * the height required to store one rmap record for each block in an
         * rt group.
+        *
+        * On a reflink filesystem, each rt block can have up to 2^32 (per the
+        * refcount record format) owners, which means that theoretically we
+        * could face up to 2^64 rmap records.  This makes the computation of
+        * maxlevels based on record count meaningless, so we only consider the
+        * size of the data device.
         */
        d_maxlevels = xfs_btree_space_to_height(mp->m_rtrmap_mnr,
                                mp->m_sb.sb_dblocks);
+       if (xfs_has_rtreflink(mp)) {
+               mp->m_rtrmap_maxlevels = d_maxlevels + 1;
+               return;
+       }
+
        r_maxlevels = xfs_btree_compute_maxlevels(mp->m_rtrmap_mnr,
                                mp->m_groups[XG_TYPE_RTG].blocks);