1
0
Fork 0
mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-01-23 08:35:19 -05:00
linux/fs/xfs/libxfs
Darrick J. Wong c0f399ff51 xfs: fix off-by-one error in xfs_btree_space_to_height
Lately I've been stress-testing extreme-sized rmap btrees by using the
(new) xfs_db bmap_inflate command to clone bmbt mappings billions of
times and then using xfs_repair to build new rmap and refcount btrees.
This of course is /much/ faster than actually FICLONEing a file billions
of times.

Unfortunately, xfs_repair fails in xfs_btree_bload_compute_geometry with
EOVERFLOW, which indicates that xfs_mount.m_rmap_maxlevels is not
sufficiently large for the test scenario.  For a 1TB filesystem (~67
million AG blocks, 4 AGs) the btheight command reports:

$ xfs_db -c 'btheight -n 4400801200 -w min rmapbt' /dev/sda
rmapbt: worst case per 4096-byte block: 84 records (leaf) / 45 keyptrs (node)
level 0: 4400801200 records, 52390491 blocks
level 1: 52390491 records, 1164234 blocks
level 2: 1164234 records, 25872 blocks
level 3: 25872 records, 575 blocks
level 4: 575 records, 13 blocks
level 5: 13 records, 1 block
6 levels, 53581186 blocks total

The AG is sufficiently large to build this rmap btree.  Unfortunately,
m_rmap_maxlevels is 5.  Augmenting the loop in the space->height
function to report height, node blocks, and blocks remaining produces
this:

ht 1 node_blocks 45 blockleft 67108863
ht 2 node_blocks 2025 blockleft 67108818
ht 3 node_blocks 91125 blockleft 67106793
ht 4 node_blocks 4100625 blockleft 67015668
final height: 5

The goal of this function is to compute the maximum height btree that
can be stored in the given number of ondisk fsblocks.  Starting with the
top level of the tree, each iteration through the loop adds the fanout
factor of the next level down until we run out of blocks.  IOWs, maximum
height is achieved by using the smallest fanout factor that can apply
to that level.

However, the loop setup is not correct.  Top level btree blocks are
allowed to contain fewer than minrecs items, so the computation is
incorrect because the first time through the loop it should be using a
fanout factor of 2.  With this corrected, the above becomes:

ht 1 node_blocks 2 blockleft 67108863
ht 2 node_blocks 90 blockleft 67108861
ht 3 node_blocks 4050 blockleft 67108771
ht 4 node_blocks 182250 blockleft 67104721
ht 5 node_blocks 8201250 blockleft 66922471
final height: 6

Fixes: 9ec691205e ("xfs: compute the maximum height of the rmap btree when reflink enabled")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
2023-01-03 10:23:07 -08:00
..
xfs_ag.c
xfs_ag.h xfs: create a predicate to verify per-AG extents 2022-10-31 08:58:20 -07:00
xfs_ag_resv.c
xfs_ag_resv.h
xfs_alloc.c treewide: use get_random_u32_below() instead of deprecated function 2022-11-18 02:15:15 +01:00
xfs_alloc.h
xfs_alloc_btree.c
xfs_alloc_btree.h
xfs_attr.c
xfs_attr.h
xfs_attr_leaf.c xfs: don't leak memory when attr fork loading fails 2022-07-20 16:40:39 -07:00
xfs_attr_leaf.h
xfs_attr_remote.c
xfs_attr_remote.h
xfs_attr_sf.h
xfs_bit.c
xfs_bit.h
xfs_bmap.c xfs: invalidate xfs_bufs when allocating cow extents 2022-12-01 09:36:16 -08:00
xfs_bmap.h
xfs_bmap_btree.c
xfs_bmap_btree.h
xfs_btree.c xfs: fix off-by-one error in xfs_btree_space_to_height 2023-01-03 10:23:07 -08:00
xfs_btree.h xfs: get rid of assert from xfs_btree_islastblock 2022-12-01 09:36:16 -08:00
xfs_btree_staging.c
xfs_btree_staging.h
xfs_cksum.h
xfs_da_btree.c xfs: trim the mapp array accordingly in xfs_da_grow_inode_int 2022-10-04 16:39:42 +11:00
xfs_da_btree.h
xfs_da_format.h
xfs_defer.c
xfs_defer.h
xfs_dir2.c xfs: rearrange the logic and remove the broken comment for xfs_dir2_isxx 2022-10-04 16:39:58 +11:00
xfs_dir2.h xfs: rearrange the logic and remove the broken comment for xfs_dir2_isxx 2022-10-04 16:39:58 +11:00
xfs_dir2_block.c
xfs_dir2_data.c
xfs_dir2_leaf.c xfs: fix exception caused by unexpected illegal bestcount in leaf dir 2022-10-20 09:42:56 -07:00
xfs_dir2_node.c
xfs_dir2_priv.h
xfs_dir2_sf.c xfs: Remove the unneeded result variable 2022-09-19 06:52:14 +10:00
xfs_dquot_buf.c
xfs_errortag.h xfs: add debug knob to slow down write for fun 2022-11-28 17:54:49 -08:00
xfs_format.h xfs: rename XFS_REFC_COW_START to _COWFLAG 2022-10-31 08:58:22 -07:00
xfs_fs.h
xfs_health.h
xfs_ialloc.c treewide: use get_random_u32_below() instead of deprecated function 2022-11-18 02:15:15 +01:00
xfs_ialloc.h
xfs_ialloc_btree.c
xfs_ialloc_btree.h
xfs_iext_tree.c
xfs_inode_buf.c xfs: make attr forks permanent 2022-07-14 09:46:37 -07:00
xfs_inode_buf.h
xfs_inode_fork.c xfs: clean up "%Ld/%Lu" which doesn't meet C standard 2022-09-19 06:47:14 +10:00
xfs_inode_fork.h
xfs_log_format.h xfs: refactor all the EFI/EFD log item sizeof logic 2022-10-31 08:58:20 -07:00
xfs_log_recover.h
xfs_log_rlimit.c
xfs_quota_defs.h
xfs_refcount.c xfs: estimate post-merge refcounts correctly 2022-12-01 09:32:04 -08:00
xfs_refcount.h xfs: rename XFS_REFC_COW_START to _COWFLAG 2022-10-31 08:58:22 -07:00
xfs_refcount_btree.c xfs: track cow/shared record domains explicitly in xfs_refcount_irec 2022-10-31 08:58:21 -07:00
xfs_refcount_btree.h
xfs_rmap.c xfs: create a predicate to verify per-AG extents 2022-10-31 08:58:20 -07:00
xfs_rmap.h
xfs_rmap_btree.c
xfs_rmap_btree.h
xfs_rtbitmap.c
xfs_sb.c xfs: fix sb write verify for lazysbcount 2022-11-16 19:20:20 -08:00
xfs_sb.h
xfs_shared.h
xfs_symlink_remote.c
xfs_trans_inode.c
xfs_trans_resv.c xfs: increase rename inode reservation 2022-10-26 13:02:24 -07:00
xfs_trans_resv.h
xfs_trans_space.h
xfs_types.c
xfs_types.h xfs: report refcount domain in tracepoints 2022-10-31 08:58:21 -07:00