summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2022-07-14 11:16:02 -0700
committerDarrick J. Wong <djwong@kernel.org>2022-10-14 14:17:22 -0700
commita25bdfb66391e0536a76bc4bf0a2d4f89fd676a5 (patch)
treeae305c0c6b917c1afe34f88a698639b47bcc0ec2
parentefea324d8ed3564d4c7b38c9f603a02ef660a252 (diff)
xfs: compute rtrmap btree max levels when reflink enabled
Compute the maximum possible height of the realtime rmap btree when reflink is enabled. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/libxfs/xfs_rtrmap_btree.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/fs/xfs/libxfs/xfs_rtrmap_btree.c b/fs/xfs/libxfs/xfs_rtrmap_btree.c
index c13a528940ab..53368dfb8c8a 100644
--- a/fs/xfs/libxfs/xfs_rtrmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rtrmap_btree.c
@@ -785,6 +785,7 @@ xfs_rtrmapbt_maxrecs(
unsigned int
xfs_rtrmapbt_maxlevels_ondisk(void)
{
+ unsigned long long max_dblocks;
unsigned int minrecs[2];
unsigned int blocklen;
@@ -793,8 +794,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
@@ -833,9 +846,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_sb.sb_rgblocks);