Skip to content

Commit c99f99f

Browse files
author
Darrick J. Wong
committed
xfs: check btree keys reflect the child block
When scrub is checking a non-root btree block, it should make sure that the keys in the parent btree block accurately capture the keyspace that the child block stores. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com>
1 parent 3838456 commit c99f99f

1 file changed

Lines changed: 48 additions & 1 deletion

File tree

fs/xfs/scrub/btree.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,48 @@ xchk_btree_check_minrecs(
529529
xchk_btree_set_corrupt(bs->sc, cur, level);
530530
}
531531

532+
/*
533+
* If this btree block has a parent, make sure that the parent's keys capture
534+
* the keyspace contained in this block.
535+
*/
536+
STATIC void
537+
xchk_btree_block_check_keys(
538+
struct xchk_btree *bs,
539+
int level,
540+
struct xfs_btree_block *block)
541+
{
542+
union xfs_btree_key block_key;
543+
union xfs_btree_key *block_high_key;
544+
union xfs_btree_key *parent_low_key, *parent_high_key;
545+
struct xfs_btree_cur *cur = bs->cur;
546+
struct xfs_btree_block *parent_block;
547+
struct xfs_buf *bp;
548+
549+
if (level == cur->bc_nlevels - 1)
550+
return;
551+
552+
xfs_btree_get_keys(cur, block, &block_key);
553+
554+
/* Make sure the low key of this block matches the parent. */
555+
parent_block = xfs_btree_get_block(cur, level + 1, &bp);
556+
parent_low_key = xfs_btree_key_addr(cur, cur->bc_levels[level + 1].ptr,
557+
parent_block);
558+
if (cur->bc_ops->diff_two_keys(cur, &block_key, parent_low_key)) {
559+
xchk_btree_set_corrupt(bs->sc, bs->cur, level);
560+
return;
561+
}
562+
563+
if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING))
564+
return;
565+
566+
/* Make sure the high key of this block matches the parent. */
567+
parent_high_key = xfs_btree_high_key_addr(cur,
568+
cur->bc_levels[level + 1].ptr, parent_block);
569+
block_high_key = xfs_btree_high_key_from_key(cur, &block_key);
570+
if (cur->bc_ops->diff_two_keys(cur, block_high_key, parent_high_key))
571+
xchk_btree_set_corrupt(bs->sc, bs->cur, level);
572+
}
573+
532574
/*
533575
* Grab and scrub a btree block given a btree pointer. Returns block
534576
* and buffer pointers (if applicable) if they're ok to use.
@@ -580,7 +622,12 @@ xchk_btree_get_block(
580622
* Check the block's siblings; this function absorbs error codes
581623
* for us.
582624
*/
583-
return xchk_btree_block_check_siblings(bs, *pblock);
625+
error = xchk_btree_block_check_siblings(bs, *pblock);
626+
if (error)
627+
return error;
628+
629+
xchk_btree_block_check_keys(bs, level, *pblock);
630+
return 0;
584631
}
585632

586633
/*

0 commit comments

Comments
 (0)