@@ -151,11 +151,12 @@ xchk_btree_rec(
151151
152152 trace_xchk_btree_rec (bs -> sc , cur , 0 );
153153
154- /* If this isn't the first record, are they in order? */
155- if (cur -> bc_levels [ 0 ]. ptr > 1 &&
154+ /* Are all records across all record blocks in order? */
155+ if (bs -> lastrec_valid &&
156156 !cur -> bc_ops -> recs_inorder (cur , & bs -> lastrec , rec ))
157157 xchk_btree_set_corrupt (bs -> sc , cur , 0 );
158158 memcpy (& bs -> lastrec , rec , cur -> bc_ops -> rec_len );
159+ bs -> lastrec_valid = true;
159160
160161 if (cur -> bc_nlevels == 1 )
161162 return ;
@@ -198,11 +199,12 @@ xchk_btree_key(
198199
199200 trace_xchk_btree_key (bs -> sc , cur , level );
200201
201- /* If this isn't the first key, are they in order? */
202- if (cur -> bc_levels [level ]. ptr > 1 &&
203- !cur -> bc_ops -> keys_inorder (cur , & bs -> lastkey [level - 1 ], key ))
202+ /* Are all low keys across all node blocks in order? */
203+ if (bs -> lastkey [level - 1 ]. valid &&
204+ !cur -> bc_ops -> keys_inorder (cur , & bs -> lastkey [level - 1 ]. key , key ))
204205 xchk_btree_set_corrupt (bs -> sc , cur , level );
205- memcpy (& bs -> lastkey [level - 1 ], key , cur -> bc_ops -> key_len );
206+ memcpy (& bs -> lastkey [level - 1 ].key , key , cur -> bc_ops -> key_len );
207+ bs -> lastkey [level - 1 ].valid = true;
206208
207209 if (level + 1 >= cur -> bc_nlevels )
208210 return ;
@@ -529,6 +531,48 @@ xchk_btree_check_minrecs(
529531 xchk_btree_set_corrupt (bs -> sc , cur , level );
530532}
531533
534+ /*
535+ * If this btree block has a parent, make sure that the parent's keys capture
536+ * the keyspace contained in this block.
537+ */
538+ STATIC void
539+ xchk_btree_block_check_keys (
540+ struct xchk_btree * bs ,
541+ int level ,
542+ struct xfs_btree_block * block )
543+ {
544+ union xfs_btree_key block_key ;
545+ union xfs_btree_key * block_high_key ;
546+ union xfs_btree_key * parent_low_key , * parent_high_key ;
547+ struct xfs_btree_cur * cur = bs -> cur ;
548+ struct xfs_btree_block * parent_block ;
549+ struct xfs_buf * bp ;
550+
551+ if (level == cur -> bc_nlevels - 1 )
552+ return ;
553+
554+ xfs_btree_get_keys (cur , block , & block_key );
555+
556+ /* Make sure the low key of this block matches the parent. */
557+ parent_block = xfs_btree_get_block (cur , level + 1 , & bp );
558+ parent_low_key = xfs_btree_key_addr (cur , cur -> bc_levels [level + 1 ].ptr ,
559+ parent_block );
560+ if (cur -> bc_ops -> diff_two_keys (cur , & block_key , parent_low_key )) {
561+ xchk_btree_set_corrupt (bs -> sc , bs -> cur , level );
562+ return ;
563+ }
564+
565+ if (!(cur -> bc_flags & XFS_BTREE_OVERLAPPING ))
566+ return ;
567+
568+ /* Make sure the high key of this block matches the parent. */
569+ parent_high_key = xfs_btree_high_key_addr (cur ,
570+ cur -> bc_levels [level + 1 ].ptr , parent_block );
571+ block_high_key = xfs_btree_high_key_from_key (cur , & block_key );
572+ if (cur -> bc_ops -> diff_two_keys (cur , block_high_key , parent_high_key ))
573+ xchk_btree_set_corrupt (bs -> sc , bs -> cur , level );
574+ }
575+
532576/*
533577 * Grab and scrub a btree block given a btree pointer. Returns block
534578 * and buffer pointers (if applicable) if they're ok to use.
@@ -580,7 +624,12 @@ xchk_btree_get_block(
580624 * Check the block's siblings; this function absorbs error codes
581625 * for us.
582626 */
583- return xchk_btree_block_check_siblings (bs , * pblock );
627+ error = xchk_btree_block_check_siblings (bs , * pblock );
628+ if (error )
629+ return error ;
630+
631+ xchk_btree_block_check_keys (bs , level , * pblock );
632+ return 0 ;
584633}
585634
586635/*
0 commit comments