xfs: fix the minrecs logic when dealing with inode root child blocks
The comment and logic in xchk_btree_check_minrecs for dealing with
inode-rooted btrees isn't quite correct. While the direct children of
the inode root are allowed to have fewer records than what would
normally be allowed for a regular ondisk btree block, this is only true
if there is only one child block and the number of records don't fit in
the inode root.
Fixes: 08a3a692ef
("xfs: btree scrub should check minrecs")
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
2bd3fa793a
commit
e95b6c3ef1
@ -452,32 +452,41 @@ xchk_btree_check_minrecs(
|
|||||||
int level,
|
int level,
|
||||||
struct xfs_btree_block *block)
|
struct xfs_btree_block *block)
|
||||||
{
|
{
|
||||||
unsigned int numrecs;
|
struct xfs_btree_cur *cur = bs->cur;
|
||||||
int ok_level;
|
unsigned int root_level = cur->bc_nlevels - 1;
|
||||||
|
unsigned int numrecs = be16_to_cpu(block->bb_numrecs);
|
||||||
numrecs = be16_to_cpu(block->bb_numrecs);
|
|
||||||
|
|
||||||
/* More records than minrecs means the block is ok. */
|
/* More records than minrecs means the block is ok. */
|
||||||
if (numrecs >= bs->cur->bc_ops->get_minrecs(bs->cur, level))
|
if (numrecs >= cur->bc_ops->get_minrecs(cur, level))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Certain btree blocks /can/ have fewer than minrecs records. Any
|
* For btrees rooted in the inode, it's possible that the root block
|
||||||
* level greater than or equal to the level of the highest dedicated
|
* contents spilled into a regular ondisk block because there wasn't
|
||||||
* btree block are allowed to violate this constraint.
|
* enough space in the inode root. The number of records in that
|
||||||
*
|
* child block might be less than the standard minrecs, but that's ok
|
||||||
* For a btree rooted in a block, the btree root can have fewer than
|
* provided that there's only one direct child of the root.
|
||||||
* minrecs records. If the btree is rooted in an inode and does not
|
|
||||||
* store records in the root, the direct children of the root and the
|
|
||||||
* root itself can have fewer than minrecs records.
|
|
||||||
*/
|
*/
|
||||||
ok_level = bs->cur->bc_nlevels - 1;
|
if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
|
||||||
if (bs->cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
|
level == cur->bc_nlevels - 2) {
|
||||||
ok_level--;
|
struct xfs_btree_block *root_block;
|
||||||
if (level >= ok_level)
|
struct xfs_buf *root_bp;
|
||||||
return;
|
int root_maxrecs;
|
||||||
|
|
||||||
xchk_btree_set_corrupt(bs->sc, bs->cur, level);
|
root_block = xfs_btree_get_block(cur, root_level, &root_bp);
|
||||||
|
root_maxrecs = cur->bc_ops->get_dmaxrecs(cur, root_level);
|
||||||
|
if (be16_to_cpu(root_block->bb_numrecs) != 1 ||
|
||||||
|
numrecs <= root_maxrecs)
|
||||||
|
xchk_btree_set_corrupt(bs->sc, cur, level);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Otherwise, only the root level is allowed to have fewer than minrecs
|
||||||
|
* records or keyptrs.
|
||||||
|
*/
|
||||||
|
if (level < root_level)
|
||||||
|
xchk_btree_set_corrupt(bs->sc, cur, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user