Skip to content

Commit 08a3a69

Browse files
committed
xfs: btree scrub should check minrecs
Strengthen the btree block header checks to detect the number of records being less than the btree type's minimum record count. Certain blocks are allowed to violate this constraint -- specifically any btree block at the top of the tree can have fewer than minrecs records. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com>
1 parent 631fc95 commit 08a3a69

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

fs/xfs/scrub/btree.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,44 @@ xfs_scrub_btree_check_owner(
454454
return xfs_scrub_btree_check_block_owner(bs, level, XFS_BUF_ADDR(bp));
455455
}
456456

457+
/*
458+
* Check that this btree block has at least minrecs records or is one of the
459+
* special blocks that don't require that.
460+
*/
461+
STATIC void
462+
xfs_scrub_btree_check_minrecs(
463+
struct xfs_scrub_btree *bs,
464+
int level,
465+
struct xfs_btree_block *block)
466+
{
467+
unsigned int numrecs;
468+
int ok_level;
469+
470+
numrecs = be16_to_cpu(block->bb_numrecs);
471+
472+
/* More records than minrecs means the block is ok. */
473+
if (numrecs >= bs->cur->bc_ops->get_minrecs(bs->cur, level))
474+
return;
475+
476+
/*
477+
* Certain btree blocks /can/ have fewer than minrecs records. Any
478+
* level greater than or equal to the level of the highest dedicated
479+
* btree block are allowed to violate this constraint.
480+
*
481+
* For a btree rooted in a block, the btree root can have fewer than
482+
* minrecs records. If the btree is rooted in an inode and does not
483+
* store records in the root, the direct children of the root and the
484+
* root itself can have fewer than minrecs records.
485+
*/
486+
ok_level = bs->cur->bc_nlevels - 1;
487+
if (bs->cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
488+
ok_level--;
489+
if (level >= ok_level)
490+
return;
491+
492+
xfs_scrub_btree_set_corrupt(bs->sc, bs->cur, level);
493+
}
494+
457495
/*
458496
* Grab and scrub a btree block given a btree pointer. Returns block
459497
* and buffer pointers (if applicable) if they're ok to use.
@@ -491,6 +529,8 @@ xfs_scrub_btree_get_block(
491529
if (*pbp)
492530
xfs_scrub_buffer_recheck(bs->sc, *pbp);
493531

532+
xfs_scrub_btree_check_minrecs(bs, level, *pblock);
533+
494534
/*
495535
* Check the block's owner; this function absorbs error codes
496536
* for us.

0 commit comments

Comments
 (0)