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