1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2017 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <darrick.wong@oracle.com> 5 */ 6 #include "xfs.h" 7 #include "xfs_fs.h" 8 #include "xfs_shared.h" 9 #include "xfs_format.h" 10 #include "xfs_trans_resv.h" 11 #include "xfs_mount.h" 12 #include "xfs_inode.h" 13 #include "xfs_btree.h" 14 #include "scrub/scrub.h" 15 #include "scrub/common.h" 16 #include "scrub/btree.h" 17 #include "scrub/trace.h" 18 19 /* btree scrubbing */ 20 21 /* 22 * Check for btree operation errors. See the section about handling 23 * operational errors in common.c. 24 */ 25 static bool 26 __xchk_btree_process_error( 27 struct xfs_scrub *sc, 28 struct xfs_btree_cur *cur, 29 int level, 30 int *error, 31 __u32 errflag, 32 void *ret_ip) 33 { 34 if (*error == 0) 35 return true; 36 37 switch (*error) { 38 case -EDEADLOCK: 39 /* Used to restart an op with deadlock avoidance. */ 40 trace_xchk_deadlock_retry(sc->ip, sc->sm, *error); 41 break; 42 case -EFSBADCRC: 43 case -EFSCORRUPTED: 44 /* Note the badness but don't abort. */ 45 sc->sm->sm_flags |= errflag; 46 *error = 0; 47 fallthrough; 48 default: 49 if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) 50 trace_xchk_ifork_btree_op_error(sc, cur, level, 51 *error, ret_ip); 52 else 53 trace_xchk_btree_op_error(sc, cur, level, 54 *error, ret_ip); 55 break; 56 } 57 return false; 58 } 59 60 bool 61 xchk_btree_process_error( 62 struct xfs_scrub *sc, 63 struct xfs_btree_cur *cur, 64 int level, 65 int *error) 66 { 67 return __xchk_btree_process_error(sc, cur, level, error, 68 XFS_SCRUB_OFLAG_CORRUPT, __return_address); 69 } 70 71 bool 72 xchk_btree_xref_process_error( 73 struct xfs_scrub *sc, 74 struct xfs_btree_cur *cur, 75 int level, 76 int *error) 77 { 78 return __xchk_btree_process_error(sc, cur, level, error, 79 XFS_SCRUB_OFLAG_XFAIL, __return_address); 80 } 81 82 /* Record btree block corruption. */ 83 static void 84 __xchk_btree_set_corrupt( 85 struct xfs_scrub *sc, 86 struct xfs_btree_cur *cur, 87 int level, 88 __u32 errflag, 89 void *ret_ip) 90 { 91 sc->sm->sm_flags |= errflag; 92 93 if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) 94 trace_xchk_ifork_btree_error(sc, cur, level, 95 ret_ip); 96 else 97 trace_xchk_btree_error(sc, cur, level, 98 ret_ip); 99 } 100 101 void 102 xchk_btree_set_corrupt( 103 struct xfs_scrub *sc, 104 struct xfs_btree_cur *cur, 105 int level) 106 { 107 __xchk_btree_set_corrupt(sc, cur, level, XFS_SCRUB_OFLAG_CORRUPT, 108 __return_address); 109 } 110 111 void 112 xchk_btree_xref_set_corrupt( 113 struct xfs_scrub *sc, 114 struct xfs_btree_cur *cur, 115 int level) 116 { 117 __xchk_btree_set_corrupt(sc, cur, level, XFS_SCRUB_OFLAG_XCORRUPT, 118 __return_address); 119 } 120 121 /* 122 * Make sure this record is in order and doesn't stray outside of the parent 123 * keys. 124 */ 125 STATIC void 126 xchk_btree_rec( 127 struct xchk_btree *bs) 128 { 129 struct xfs_btree_cur *cur = bs->cur; 130 union xfs_btree_rec *rec; 131 union xfs_btree_key key; 132 union xfs_btree_key hkey; 133 union xfs_btree_key *keyp; 134 struct xfs_btree_block *block; 135 struct xfs_btree_block *keyblock; 136 struct xfs_buf *bp; 137 138 block = xfs_btree_get_block(cur, 0, &bp); 139 rec = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); 140 141 trace_xchk_btree_rec(bs->sc, cur, 0); 142 143 /* If this isn't the first record, are they in order? */ 144 if (cur->bc_ptrs[0] > 1 && 145 !cur->bc_ops->recs_inorder(cur, &bs->lastrec, rec)) 146 xchk_btree_set_corrupt(bs->sc, cur, 0); 147 memcpy(&bs->lastrec, rec, cur->bc_ops->rec_len); 148 149 if (cur->bc_nlevels == 1) 150 return; 151 152 /* Is this at least as large as the parent low key? */ 153 cur->bc_ops->init_key_from_rec(&key, rec); 154 keyblock = xfs_btree_get_block(cur, 1, &bp); 155 keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[1], keyblock); 156 if (cur->bc_ops->diff_two_keys(cur, &key, keyp) < 0) 157 xchk_btree_set_corrupt(bs->sc, cur, 1); 158 159 if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING)) 160 return; 161 162 /* Is this no larger than the parent high key? */ 163 cur->bc_ops->init_high_key_from_rec(&hkey, rec); 164 keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[1], keyblock); 165 if (cur->bc_ops->diff_two_keys(cur, keyp, &hkey) < 0) 166 xchk_btree_set_corrupt(bs->sc, cur, 1); 167 } 168 169 /* 170 * Make sure this key is in order and doesn't stray outside of the parent 171 * keys. 172 */ 173 STATIC void 174 xchk_btree_key( 175 struct xchk_btree *bs, 176 int level) 177 { 178 struct xfs_btree_cur *cur = bs->cur; 179 union xfs_btree_key *key; 180 union xfs_btree_key *keyp; 181 struct xfs_btree_block *block; 182 struct xfs_btree_block *keyblock; 183 struct xfs_buf *bp; 184 185 block = xfs_btree_get_block(cur, level, &bp); 186 key = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); 187 188 trace_xchk_btree_key(bs->sc, cur, level); 189 190 /* If this isn't the first key, are they in order? */ 191 if (cur->bc_ptrs[level] > 1 && 192 !cur->bc_ops->keys_inorder(cur, &bs->lastkey[level - 1], key)) 193 xchk_btree_set_corrupt(bs->sc, cur, level); 194 memcpy(&bs->lastkey[level - 1], key, cur->bc_ops->key_len); 195 196 if (level + 1 >= cur->bc_nlevels) 197 return; 198 199 /* Is this at least as large as the parent low key? */ 200 keyblock = xfs_btree_get_block(cur, level + 1, &bp); 201 keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[level + 1], keyblock); 202 if (cur->bc_ops->diff_two_keys(cur, key, keyp) < 0) 203 xchk_btree_set_corrupt(bs->sc, cur, level); 204 205 if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING)) 206 return; 207 208 /* Is this no larger than the parent high key? */ 209 key = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); 210 keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level + 1], keyblock); 211 if (cur->bc_ops->diff_two_keys(cur, keyp, key) < 0) 212 xchk_btree_set_corrupt(bs->sc, cur, level); 213 } 214 215 /* 216 * Check a btree pointer. Returns true if it's ok to use this pointer. 217 * Callers do not need to set the corrupt flag. 218 */ 219 static bool 220 xchk_btree_ptr_ok( 221 struct xchk_btree *bs, 222 int level, 223 union xfs_btree_ptr *ptr) 224 { 225 bool res; 226 227 /* A btree rooted in an inode has no block pointer to the root. */ 228 if ((bs->cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && 229 level == bs->cur->bc_nlevels) 230 return true; 231 232 /* Otherwise, check the pointers. */ 233 if (bs->cur->bc_flags & XFS_BTREE_LONG_PTRS) 234 res = xfs_btree_check_lptr(bs->cur, be64_to_cpu(ptr->l), level); 235 else 236 res = xfs_btree_check_sptr(bs->cur, be32_to_cpu(ptr->s), level); 237 if (!res) 238 xchk_btree_set_corrupt(bs->sc, bs->cur, level); 239 240 return res; 241 } 242 243 /* Check that a btree block's sibling matches what we expect it. */ 244 STATIC int 245 xchk_btree_block_check_sibling( 246 struct xchk_btree *bs, 247 int level, 248 int direction, 249 union xfs_btree_ptr *sibling) 250 { 251 struct xfs_btree_cur *cur = bs->cur; 252 struct xfs_btree_block *pblock; 253 struct xfs_buf *pbp; 254 struct xfs_btree_cur *ncur = NULL; 255 union xfs_btree_ptr *pp; 256 int success; 257 int error; 258 259 error = xfs_btree_dup_cursor(cur, &ncur); 260 if (!xchk_btree_process_error(bs->sc, cur, level + 1, &error) || 261 !ncur) 262 return error; 263 264 /* 265 * If the pointer is null, we shouldn't be able to move the upper 266 * level pointer anywhere. 267 */ 268 if (xfs_btree_ptr_is_null(cur, sibling)) { 269 if (direction > 0) 270 error = xfs_btree_increment(ncur, level + 1, &success); 271 else 272 error = xfs_btree_decrement(ncur, level + 1, &success); 273 if (error == 0 && success) 274 xchk_btree_set_corrupt(bs->sc, cur, level); 275 error = 0; 276 goto out; 277 } 278 279 /* Increment upper level pointer. */ 280 if (direction > 0) 281 error = xfs_btree_increment(ncur, level + 1, &success); 282 else 283 error = xfs_btree_decrement(ncur, level + 1, &success); 284 if (!xchk_btree_process_error(bs->sc, cur, level + 1, &error)) 285 goto out; 286 if (!success) { 287 xchk_btree_set_corrupt(bs->sc, cur, level + 1); 288 goto out; 289 } 290 291 /* Compare upper level pointer to sibling pointer. */ 292 pblock = xfs_btree_get_block(ncur, level + 1, &pbp); 293 pp = xfs_btree_ptr_addr(ncur, ncur->bc_ptrs[level + 1], pblock); 294 if (!xchk_btree_ptr_ok(bs, level + 1, pp)) 295 goto out; 296 if (pbp) 297 xchk_buffer_recheck(bs->sc, pbp); 298 299 if (xfs_btree_diff_two_ptrs(cur, pp, sibling)) 300 xchk_btree_set_corrupt(bs->sc, cur, level); 301 out: 302 xfs_btree_del_cursor(ncur, XFS_BTREE_ERROR); 303 return error; 304 } 305 306 /* Check the siblings of a btree block. */ 307 STATIC int 308 xchk_btree_block_check_siblings( 309 struct xchk_btree *bs, 310 struct xfs_btree_block *block) 311 { 312 struct xfs_btree_cur *cur = bs->cur; 313 union xfs_btree_ptr leftsib; 314 union xfs_btree_ptr rightsib; 315 int level; 316 int error = 0; 317 318 xfs_btree_get_sibling(cur, block, &leftsib, XFS_BB_LEFTSIB); 319 xfs_btree_get_sibling(cur, block, &rightsib, XFS_BB_RIGHTSIB); 320 level = xfs_btree_get_level(block); 321 322 /* Root block should never have siblings. */ 323 if (level == cur->bc_nlevels - 1) { 324 if (!xfs_btree_ptr_is_null(cur, &leftsib) || 325 !xfs_btree_ptr_is_null(cur, &rightsib)) 326 xchk_btree_set_corrupt(bs->sc, cur, level); 327 goto out; 328 } 329 330 /* 331 * Does the left & right sibling pointers match the adjacent 332 * parent level pointers? 333 * (These function absorbs error codes for us.) 334 */ 335 error = xchk_btree_block_check_sibling(bs, level, -1, &leftsib); 336 if (error) 337 return error; 338 error = xchk_btree_block_check_sibling(bs, level, 1, &rightsib); 339 if (error) 340 return error; 341 out: 342 return error; 343 } 344 345 struct check_owner { 346 struct list_head list; 347 xfs_daddr_t daddr; 348 int level; 349 }; 350 351 /* 352 * Make sure this btree block isn't in the free list and that there's 353 * an rmap record for it. 354 */ 355 STATIC int 356 xchk_btree_check_block_owner( 357 struct xchk_btree *bs, 358 int level, 359 xfs_daddr_t daddr) 360 { 361 xfs_agnumber_t agno; 362 xfs_agblock_t agbno; 363 xfs_btnum_t btnum; 364 bool init_sa; 365 int error = 0; 366 367 if (!bs->cur) 368 return 0; 369 370 btnum = bs->cur->bc_btnum; 371 agno = xfs_daddr_to_agno(bs->cur->bc_mp, daddr); 372 agbno = xfs_daddr_to_agbno(bs->cur->bc_mp, daddr); 373 374 init_sa = bs->cur->bc_flags & XFS_BTREE_LONG_PTRS; 375 if (init_sa) { 376 error = xchk_ag_init_existing(bs->sc, agno, &bs->sc->sa); 377 if (!xchk_btree_xref_process_error(bs->sc, bs->cur, 378 level, &error)) 379 goto out_free; 380 } 381 382 xchk_xref_is_used_space(bs->sc, agbno, 1); 383 /* 384 * The bnobt scrubber aliases bs->cur to bs->sc->sa.bno_cur, so we 385 * have to nullify it (to shut down further block owner checks) if 386 * self-xref encounters problems. 387 */ 388 if (!bs->sc->sa.bno_cur && btnum == XFS_BTNUM_BNO) 389 bs->cur = NULL; 390 391 xchk_xref_is_owned_by(bs->sc, agbno, 1, bs->oinfo); 392 if (!bs->sc->sa.rmap_cur && btnum == XFS_BTNUM_RMAP) 393 bs->cur = NULL; 394 395 out_free: 396 if (init_sa) 397 xchk_ag_free(bs->sc, &bs->sc->sa); 398 399 return error; 400 } 401 402 /* Check the owner of a btree block. */ 403 STATIC int 404 xchk_btree_check_owner( 405 struct xchk_btree *bs, 406 int level, 407 struct xfs_buf *bp) 408 { 409 struct xfs_btree_cur *cur = bs->cur; 410 struct check_owner *co; 411 412 /* 413 * In theory, xfs_btree_get_block should only give us a null buffer 414 * pointer for the root of a root-in-inode btree type, but we need 415 * to check defensively here in case the cursor state is also screwed 416 * up. 417 */ 418 if (bp == NULL) { 419 if (!(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)) 420 xchk_btree_set_corrupt(bs->sc, bs->cur, level); 421 return 0; 422 } 423 424 /* 425 * We want to cross-reference each btree block with the bnobt 426 * and the rmapbt. We cannot cross-reference the bnobt or 427 * rmapbt while scanning the bnobt or rmapbt, respectively, 428 * because we cannot alter the cursor and we'd prefer not to 429 * duplicate cursors. Therefore, save the buffer daddr for 430 * later scanning. 431 */ 432 if (cur->bc_btnum == XFS_BTNUM_BNO || cur->bc_btnum == XFS_BTNUM_RMAP) { 433 co = kmem_alloc(sizeof(struct check_owner), 434 KM_MAYFAIL); 435 if (!co) 436 return -ENOMEM; 437 co->level = level; 438 co->daddr = xfs_buf_daddr(bp); 439 list_add_tail(&co->list, &bs->to_check); 440 return 0; 441 } 442 443 return xchk_btree_check_block_owner(bs, level, xfs_buf_daddr(bp)); 444 } 445 446 /* Decide if we want to check minrecs of a btree block in the inode root. */ 447 static inline bool 448 xchk_btree_check_iroot_minrecs( 449 struct xchk_btree *bs) 450 { 451 /* 452 * xfs_bmap_add_attrfork_btree had an implementation bug wherein it 453 * would miscalculate the space required for the data fork bmbt root 454 * when adding an attr fork, and promote the iroot contents to an 455 * external block unnecessarily. This went unnoticed for many years 456 * until scrub found filesystems in this state. Inode rooted btrees are 457 * not supposed to have immediate child blocks that are small enough 458 * that the contents could fit in the inode root, but we can't fail 459 * existing filesystems, so instead we disable the check for data fork 460 * bmap btrees when there's an attr fork. 461 */ 462 if (bs->cur->bc_btnum == XFS_BTNUM_BMAP && 463 bs->cur->bc_ino.whichfork == XFS_DATA_FORK && 464 XFS_IFORK_Q(bs->sc->ip)) 465 return false; 466 467 return true; 468 } 469 470 /* 471 * Check that this btree block has at least minrecs records or is one of the 472 * special blocks that don't require that. 473 */ 474 STATIC void 475 xchk_btree_check_minrecs( 476 struct xchk_btree *bs, 477 int level, 478 struct xfs_btree_block *block) 479 { 480 struct xfs_btree_cur *cur = bs->cur; 481 unsigned int root_level = cur->bc_nlevels - 1; 482 unsigned int numrecs = be16_to_cpu(block->bb_numrecs); 483 484 /* More records than minrecs means the block is ok. */ 485 if (numrecs >= cur->bc_ops->get_minrecs(cur, level)) 486 return; 487 488 /* 489 * For btrees rooted in the inode, it's possible that the root block 490 * contents spilled into a regular ondisk block because there wasn't 491 * enough space in the inode root. The number of records in that 492 * child block might be less than the standard minrecs, but that's ok 493 * provided that there's only one direct child of the root. 494 */ 495 if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && 496 level == cur->bc_nlevels - 2) { 497 struct xfs_btree_block *root_block; 498 struct xfs_buf *root_bp; 499 int root_maxrecs; 500 501 root_block = xfs_btree_get_block(cur, root_level, &root_bp); 502 root_maxrecs = cur->bc_ops->get_dmaxrecs(cur, root_level); 503 if (xchk_btree_check_iroot_minrecs(bs) && 504 (be16_to_cpu(root_block->bb_numrecs) != 1 || 505 numrecs <= root_maxrecs)) 506 xchk_btree_set_corrupt(bs->sc, cur, level); 507 return; 508 } 509 510 /* 511 * Otherwise, only the root level is allowed to have fewer than minrecs 512 * records or keyptrs. 513 */ 514 if (level < root_level) 515 xchk_btree_set_corrupt(bs->sc, cur, level); 516 } 517 518 /* 519 * Grab and scrub a btree block given a btree pointer. Returns block 520 * and buffer pointers (if applicable) if they're ok to use. 521 */ 522 STATIC int 523 xchk_btree_get_block( 524 struct xchk_btree *bs, 525 int level, 526 union xfs_btree_ptr *pp, 527 struct xfs_btree_block **pblock, 528 struct xfs_buf **pbp) 529 { 530 xfs_failaddr_t failed_at; 531 int error; 532 533 *pblock = NULL; 534 *pbp = NULL; 535 536 error = xfs_btree_lookup_get_block(bs->cur, level, pp, pblock); 537 if (!xchk_btree_process_error(bs->sc, bs->cur, level, &error) || 538 !*pblock) 539 return error; 540 541 xfs_btree_get_block(bs->cur, level, pbp); 542 if (bs->cur->bc_flags & XFS_BTREE_LONG_PTRS) 543 failed_at = __xfs_btree_check_lblock(bs->cur, *pblock, 544 level, *pbp); 545 else 546 failed_at = __xfs_btree_check_sblock(bs->cur, *pblock, 547 level, *pbp); 548 if (failed_at) { 549 xchk_btree_set_corrupt(bs->sc, bs->cur, level); 550 return 0; 551 } 552 if (*pbp) 553 xchk_buffer_recheck(bs->sc, *pbp); 554 555 xchk_btree_check_minrecs(bs, level, *pblock); 556 557 /* 558 * Check the block's owner; this function absorbs error codes 559 * for us. 560 */ 561 error = xchk_btree_check_owner(bs, level, *pbp); 562 if (error) 563 return error; 564 565 /* 566 * Check the block's siblings; this function absorbs error codes 567 * for us. 568 */ 569 return xchk_btree_block_check_siblings(bs, *pblock); 570 } 571 572 /* 573 * Check that the low and high keys of this block match the keys stored 574 * in the parent block. 575 */ 576 STATIC void 577 xchk_btree_block_keys( 578 struct xchk_btree *bs, 579 int level, 580 struct xfs_btree_block *block) 581 { 582 union xfs_btree_key block_keys; 583 struct xfs_btree_cur *cur = bs->cur; 584 union xfs_btree_key *high_bk; 585 union xfs_btree_key *parent_keys; 586 union xfs_btree_key *high_pk; 587 struct xfs_btree_block *parent_block; 588 struct xfs_buf *bp; 589 590 if (level >= cur->bc_nlevels - 1) 591 return; 592 593 /* Calculate the keys for this block. */ 594 xfs_btree_get_keys(cur, block, &block_keys); 595 596 /* Obtain the parent's copy of the keys for this block. */ 597 parent_block = xfs_btree_get_block(cur, level + 1, &bp); 598 parent_keys = xfs_btree_key_addr(cur, cur->bc_ptrs[level + 1], 599 parent_block); 600 601 if (cur->bc_ops->diff_two_keys(cur, &block_keys, parent_keys) != 0) 602 xchk_btree_set_corrupt(bs->sc, cur, 1); 603 604 if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING)) 605 return; 606 607 /* Get high keys */ 608 high_bk = xfs_btree_high_key_from_key(cur, &block_keys); 609 high_pk = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level + 1], 610 parent_block); 611 612 if (cur->bc_ops->diff_two_keys(cur, high_bk, high_pk) != 0) 613 xchk_btree_set_corrupt(bs->sc, cur, 1); 614 } 615 616 /* 617 * Visit all nodes and leaves of a btree. Check that all pointers and 618 * records are in order, that the keys reflect the records, and use a callback 619 * so that the caller can verify individual records. 620 */ 621 int 622 xchk_btree( 623 struct xfs_scrub *sc, 624 struct xfs_btree_cur *cur, 625 xchk_btree_rec_fn scrub_fn, 626 const struct xfs_owner_info *oinfo, 627 void *private) 628 { 629 union xfs_btree_ptr ptr; 630 struct xchk_btree *bs; 631 union xfs_btree_ptr *pp; 632 union xfs_btree_rec *recp; 633 struct xfs_btree_block *block; 634 struct xfs_buf *bp; 635 struct check_owner *co; 636 struct check_owner *n; 637 size_t cur_sz; 638 int level; 639 int error = 0; 640 641 /* 642 * Allocate the btree scrub context from the heap, because this 643 * structure can get rather large. Don't let a caller feed us a 644 * totally absurd size. 645 */ 646 cur_sz = xchk_btree_sizeof(cur->bc_nlevels); 647 if (cur_sz > PAGE_SIZE) { 648 xchk_btree_set_corrupt(sc, cur, 0); 649 return 0; 650 } 651 bs = kmem_zalloc(cur_sz, KM_NOFS | KM_MAYFAIL); 652 if (!bs) 653 return -ENOMEM; 654 bs->cur = cur; 655 bs->scrub_rec = scrub_fn; 656 bs->oinfo = oinfo; 657 bs->private = private; 658 bs->sc = sc; 659 660 /* Initialize scrub state */ 661 INIT_LIST_HEAD(&bs->to_check); 662 663 /* 664 * Load the root of the btree. The helper function absorbs 665 * error codes for us. 666 */ 667 level = cur->bc_nlevels - 1; 668 cur->bc_ops->init_ptr_from_cur(cur, &ptr); 669 if (!xchk_btree_ptr_ok(bs, cur->bc_nlevels, &ptr)) 670 goto out; 671 error = xchk_btree_get_block(bs, level, &ptr, &block, &bp); 672 if (error || !block) 673 goto out; 674 675 cur->bc_ptrs[level] = 1; 676 677 while (level < cur->bc_nlevels) { 678 block = xfs_btree_get_block(cur, level, &bp); 679 680 if (level == 0) { 681 /* End of leaf, pop back towards the root. */ 682 if (cur->bc_ptrs[level] > 683 be16_to_cpu(block->bb_numrecs)) { 684 xchk_btree_block_keys(bs, level, block); 685 if (level < cur->bc_nlevels - 1) 686 cur->bc_ptrs[level + 1]++; 687 level++; 688 continue; 689 } 690 691 /* Records in order for scrub? */ 692 xchk_btree_rec(bs); 693 694 /* Call out to the record checker. */ 695 recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); 696 error = bs->scrub_rec(bs, recp); 697 if (error) 698 break; 699 if (xchk_should_terminate(sc, &error) || 700 (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 701 break; 702 703 cur->bc_ptrs[level]++; 704 continue; 705 } 706 707 /* End of node, pop back towards the root. */ 708 if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { 709 xchk_btree_block_keys(bs, level, block); 710 if (level < cur->bc_nlevels - 1) 711 cur->bc_ptrs[level + 1]++; 712 level++; 713 continue; 714 } 715 716 /* Keys in order for scrub? */ 717 xchk_btree_key(bs, level); 718 719 /* Drill another level deeper. */ 720 pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); 721 if (!xchk_btree_ptr_ok(bs, level, pp)) { 722 cur->bc_ptrs[level]++; 723 continue; 724 } 725 level--; 726 error = xchk_btree_get_block(bs, level, pp, &block, &bp); 727 if (error || !block) 728 goto out; 729 730 cur->bc_ptrs[level] = 1; 731 } 732 733 out: 734 /* Process deferred owner checks on btree blocks. */ 735 list_for_each_entry_safe(co, n, &bs->to_check, list) { 736 if (!error && bs->cur) 737 error = xchk_btree_check_block_owner(bs, co->level, 738 co->daddr); 739 list_del(&co->list); 740 kmem_free(co); 741 } 742 kmem_free(bs); 743 744 return error; 745 } 746