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_btree.h" 13 #include "xfs_log_format.h" 14 #include "xfs_trans.h" 15 #include "xfs_inode.h" 16 #include "xfs_ialloc.h" 17 #include "xfs_ialloc_btree.h" 18 #include "xfs_icache.h" 19 #include "xfs_rmap.h" 20 #include "scrub/scrub.h" 21 #include "scrub/common.h" 22 #include "scrub/btree.h" 23 #include "scrub/trace.h" 24 #include "xfs_ag.h" 25 26 /* 27 * Set us up to scrub inode btrees. 28 * If we detect a discrepancy between the inobt and the inode, 29 * try again after forcing logged inode cores out to disk. 30 */ 31 int 32 xchk_setup_ag_iallocbt( 33 struct xfs_scrub *sc) 34 { 35 if (xchk_need_intent_drain(sc)) 36 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN); 37 return xchk_setup_ag_btree(sc, sc->flags & XCHK_TRY_HARDER); 38 } 39 40 /* Inode btree scrubber. */ 41 42 struct xchk_iallocbt { 43 /* Number of inodes we see while scanning inobt. */ 44 unsigned long long inodes; 45 46 /* Expected next startino, for big block filesystems. */ 47 xfs_agino_t next_startino; 48 49 /* Expected end of the current inode cluster. */ 50 xfs_agino_t next_cluster_ino; 51 }; 52 53 /* 54 * Does the finobt have a record for this inode with the same hole/free state? 55 * This is a bit complicated because of the following: 56 * 57 * - The finobt need not have a record if all inodes in the inobt record are 58 * allocated. 59 * - The finobt need not have a record if all inodes in the inobt record are 60 * free. 61 * - The finobt need not have a record if the inobt record says this is a hole. 62 * This likely doesn't happen in practice. 63 */ 64 STATIC int 65 xchk_inobt_xref_finobt( 66 struct xfs_scrub *sc, 67 struct xfs_inobt_rec_incore *irec, 68 xfs_agino_t agino, 69 bool free, 70 bool hole) 71 { 72 struct xfs_inobt_rec_incore frec; 73 struct xfs_btree_cur *cur = sc->sa.fino_cur; 74 bool ffree, fhole; 75 unsigned int frec_idx, fhole_idx; 76 int has_record; 77 int error; 78 79 ASSERT(xfs_btree_is_fino(cur->bc_ops)); 80 81 error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &has_record); 82 if (error) 83 return error; 84 if (!has_record) 85 goto no_record; 86 87 error = xfs_inobt_get_rec(cur, &frec, &has_record); 88 if (error) 89 return error; 90 if (!has_record) 91 return -EFSCORRUPTED; 92 93 if (frec.ir_startino + XFS_INODES_PER_CHUNK <= agino) 94 goto no_record; 95 96 /* There's a finobt record; free and hole status must match. */ 97 frec_idx = agino - frec.ir_startino; 98 ffree = frec.ir_free & (1ULL << frec_idx); 99 fhole_idx = frec_idx / XFS_INODES_PER_HOLEMASK_BIT; 100 fhole = frec.ir_holemask & (1U << fhole_idx); 101 102 if (ffree != free) 103 xchk_btree_xref_set_corrupt(sc, cur, 0); 104 if (fhole != hole) 105 xchk_btree_xref_set_corrupt(sc, cur, 0); 106 return 0; 107 108 no_record: 109 /* inobt record is fully allocated */ 110 if (irec->ir_free == 0) 111 return 0; 112 113 /* inobt record is totally unallocated */ 114 if (irec->ir_free == XFS_INOBT_ALL_FREE) 115 return 0; 116 117 /* inobt record says this is a hole */ 118 if (hole) 119 return 0; 120 121 /* finobt doesn't care about allocated inodes */ 122 if (!free) 123 return 0; 124 125 xchk_btree_xref_set_corrupt(sc, cur, 0); 126 return 0; 127 } 128 129 /* 130 * Make sure that each inode of this part of an inobt record has the same 131 * sparse and free status as the finobt. 132 */ 133 STATIC void 134 xchk_inobt_chunk_xref_finobt( 135 struct xfs_scrub *sc, 136 struct xfs_inobt_rec_incore *irec, 137 xfs_agino_t agino, 138 unsigned int nr_inodes) 139 { 140 xfs_agino_t i; 141 unsigned int rec_idx; 142 int error; 143 144 ASSERT(sc->sm->sm_type == XFS_SCRUB_TYPE_INOBT); 145 146 if (!sc->sa.fino_cur || xchk_skip_xref(sc->sm)) 147 return; 148 149 for (i = agino, rec_idx = agino - irec->ir_startino; 150 i < agino + nr_inodes; 151 i++, rec_idx++) { 152 bool free, hole; 153 unsigned int hole_idx; 154 155 free = irec->ir_free & (1ULL << rec_idx); 156 hole_idx = rec_idx / XFS_INODES_PER_HOLEMASK_BIT; 157 hole = irec->ir_holemask & (1U << hole_idx); 158 159 error = xchk_inobt_xref_finobt(sc, irec, i, free, hole); 160 if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur)) 161 return; 162 } 163 } 164 165 /* 166 * Does the inobt have a record for this inode with the same hole/free state? 167 * The inobt must always have a record if there's a finobt record. 168 */ 169 STATIC int 170 xchk_finobt_xref_inobt( 171 struct xfs_scrub *sc, 172 struct xfs_inobt_rec_incore *frec, 173 xfs_agino_t agino, 174 bool ffree, 175 bool fhole) 176 { 177 struct xfs_inobt_rec_incore irec; 178 struct xfs_btree_cur *cur = sc->sa.ino_cur; 179 bool free, hole; 180 unsigned int rec_idx, hole_idx; 181 int has_record; 182 int error; 183 184 ASSERT(xfs_btree_is_ino(cur->bc_ops)); 185 186 error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &has_record); 187 if (error) 188 return error; 189 if (!has_record) 190 goto no_record; 191 192 error = xfs_inobt_get_rec(cur, &irec, &has_record); 193 if (error) 194 return error; 195 if (!has_record) 196 return -EFSCORRUPTED; 197 198 if (irec.ir_startino + XFS_INODES_PER_CHUNK <= agino) 199 goto no_record; 200 201 /* There's an inobt record; free and hole status must match. */ 202 rec_idx = agino - irec.ir_startino; 203 free = irec.ir_free & (1ULL << rec_idx); 204 hole_idx = rec_idx / XFS_INODES_PER_HOLEMASK_BIT; 205 hole = irec.ir_holemask & (1U << hole_idx); 206 207 if (ffree != free) 208 xchk_btree_xref_set_corrupt(sc, cur, 0); 209 if (fhole != hole) 210 xchk_btree_xref_set_corrupt(sc, cur, 0); 211 return 0; 212 213 no_record: 214 /* finobt should never have a record for which the inobt does not */ 215 xchk_btree_xref_set_corrupt(sc, cur, 0); 216 return 0; 217 } 218 219 /* 220 * Make sure that each inode of this part of an finobt record has the same 221 * sparse and free status as the inobt. 222 */ 223 STATIC void 224 xchk_finobt_chunk_xref_inobt( 225 struct xfs_scrub *sc, 226 struct xfs_inobt_rec_incore *frec, 227 xfs_agino_t agino, 228 unsigned int nr_inodes) 229 { 230 xfs_agino_t i; 231 unsigned int rec_idx; 232 int error; 233 234 ASSERT(sc->sm->sm_type == XFS_SCRUB_TYPE_FINOBT); 235 236 if (!sc->sa.ino_cur || xchk_skip_xref(sc->sm)) 237 return; 238 239 for (i = agino, rec_idx = agino - frec->ir_startino; 240 i < agino + nr_inodes; 241 i++, rec_idx++) { 242 bool ffree, fhole; 243 unsigned int hole_idx; 244 245 ffree = frec->ir_free & (1ULL << rec_idx); 246 hole_idx = rec_idx / XFS_INODES_PER_HOLEMASK_BIT; 247 fhole = frec->ir_holemask & (1U << hole_idx); 248 249 error = xchk_finobt_xref_inobt(sc, frec, i, ffree, fhole); 250 if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur)) 251 return; 252 } 253 } 254 255 /* Is this chunk worth checking and cross-referencing? */ 256 STATIC bool 257 xchk_iallocbt_chunk( 258 struct xchk_btree *bs, 259 struct xfs_inobt_rec_incore *irec, 260 xfs_agino_t agino, 261 unsigned int nr_inodes) 262 { 263 struct xfs_scrub *sc = bs->sc; 264 struct xfs_mount *mp = bs->cur->bc_mp; 265 struct xfs_perag *pag = to_perag(bs->cur->bc_group); 266 xfs_agblock_t agbno; 267 xfs_extlen_t len; 268 269 agbno = XFS_AGINO_TO_AGBNO(mp, agino); 270 len = XFS_B_TO_FSB(mp, nr_inodes * mp->m_sb.sb_inodesize); 271 272 if (!xfs_verify_agbext(pag, agbno, len)) 273 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 274 275 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 276 return false; 277 278 xchk_xref_is_used_space(sc, agbno, len); 279 if (sc->sm->sm_type == XFS_SCRUB_TYPE_INOBT) 280 xchk_inobt_chunk_xref_finobt(sc, irec, agino, nr_inodes); 281 else 282 xchk_finobt_chunk_xref_inobt(sc, irec, agino, nr_inodes); 283 xchk_xref_is_only_owned_by(sc, agbno, len, &XFS_RMAP_OINFO_INODES); 284 xchk_xref_is_not_shared(sc, agbno, len); 285 xchk_xref_is_not_cow_staging(sc, agbno, len); 286 return true; 287 } 288 289 /* 290 * Check that an inode's allocation status matches ir_free in the inobt 291 * record. First we try querying the in-core inode state, and if the inode 292 * isn't loaded we examine the on-disk inode directly. 293 * 294 * Since there can be 1:M and M:1 mappings between inobt records and inode 295 * clusters, we pass in the inode location information as an inobt record; 296 * the index of an inode cluster within the inobt record (as well as the 297 * cluster buffer itself); and the index of the inode within the cluster. 298 * 299 * @irec is the inobt record. 300 * @irec_ino is the inode offset from the start of the record. 301 * @dip is the on-disk inode. 302 */ 303 STATIC int 304 xchk_iallocbt_check_cluster_ifree( 305 struct xchk_btree *bs, 306 struct xfs_inobt_rec_incore *irec, 307 unsigned int irec_ino, 308 struct xfs_dinode *dip) 309 { 310 xfs_ino_t fsino; 311 xfs_agino_t agino; 312 bool irec_free; 313 bool ino_inuse; 314 bool freemask_ok; 315 int error = 0; 316 317 if (xchk_should_terminate(bs->sc, &error)) 318 return error; 319 320 /* 321 * Given an inobt record and the offset of an inode from the start of 322 * the record, compute which fs inode we're talking about. 323 */ 324 agino = irec->ir_startino + irec_ino; 325 fsino = xfs_agino_to_ino(to_perag(bs->cur->bc_group), agino); 326 irec_free = (irec->ir_free & XFS_INOBT_MASK(irec_ino)); 327 328 if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC || 329 (dip->di_version >= 3 && be64_to_cpu(dip->di_ino) != fsino)) { 330 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 331 goto out; 332 } 333 334 error = xchk_inode_is_allocated(bs->sc, agino, &ino_inuse); 335 if (error == -ENODATA) { 336 /* Not cached, just read the disk buffer */ 337 freemask_ok = irec_free ^ !!(dip->di_mode); 338 if (!(bs->sc->flags & XCHK_TRY_HARDER) && !freemask_ok) 339 return -EDEADLOCK; 340 } else if (error < 0) { 341 /* 342 * Inode is only half assembled, or there was an IO error, 343 * or the verifier failed, so don't bother trying to check. 344 * The inode scrubber can deal with this. 345 */ 346 goto out; 347 } else { 348 /* Inode is all there. */ 349 freemask_ok = irec_free ^ ino_inuse; 350 } 351 if (!freemask_ok) 352 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 353 out: 354 return 0; 355 } 356 357 /* 358 * Check that the holemask and freemask of a hypothetical inode cluster match 359 * what's actually on disk. If sparse inodes are enabled, the cluster does 360 * not actually have to map to inodes if the corresponding holemask bit is set. 361 * 362 * @cluster_base is the first inode in the cluster within the @irec. 363 */ 364 STATIC int 365 xchk_iallocbt_check_cluster( 366 struct xchk_btree *bs, 367 struct xfs_inobt_rec_incore *irec, 368 unsigned int cluster_base) 369 { 370 struct xfs_perag *pag = to_perag(bs->cur->bc_group); 371 struct xfs_imap imap; 372 struct xfs_mount *mp = bs->cur->bc_mp; 373 struct xfs_buf *cluster_bp; 374 unsigned int nr_inodes; 375 xfs_agblock_t agbno; 376 unsigned int cluster_index; 377 uint16_t cluster_mask = 0; 378 uint16_t ir_holemask; 379 int error = 0; 380 381 nr_inodes = min_t(unsigned int, XFS_INODES_PER_CHUNK, 382 M_IGEO(mp)->inodes_per_cluster); 383 384 /* Map this inode cluster */ 385 agbno = XFS_AGINO_TO_AGBNO(mp, irec->ir_startino + cluster_base); 386 387 /* Compute a bitmask for this cluster that can be used for holemask. */ 388 for (cluster_index = 0; 389 cluster_index < nr_inodes; 390 cluster_index += XFS_INODES_PER_HOLEMASK_BIT) 391 cluster_mask |= XFS_INOBT_MASK((cluster_base + cluster_index) / 392 XFS_INODES_PER_HOLEMASK_BIT); 393 394 /* 395 * Map the first inode of this cluster to a buffer and offset. 396 * Be careful about inobt records that don't align with the start of 397 * the inode buffer when block sizes are large enough to hold multiple 398 * inode chunks. When this happens, cluster_base will be zero but 399 * ir_startino can be large enough to make im_boffset nonzero. 400 */ 401 ir_holemask = (irec->ir_holemask & cluster_mask); 402 imap.im_agbno = agbno; 403 imap.im_boffset = XFS_INO_TO_OFFSET(mp, irec->ir_startino) << 404 mp->m_sb.sb_inodelog; 405 406 if (imap.im_boffset != 0 && cluster_base != 0) { 407 ASSERT(imap.im_boffset == 0 || cluster_base == 0); 408 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 409 return 0; 410 } 411 412 trace_xchk_iallocbt_check_cluster(pag, irec->ir_startino, imap.im_agbno, 413 XFS_FSB_TO_BB(mp, M_IGEO(mp)->blocks_per_cluster), 414 cluster_base, nr_inodes, cluster_mask, ir_holemask, 415 XFS_INO_TO_OFFSET(mp, irec->ir_startino + 416 cluster_base)); 417 418 /* The whole cluster must be a hole or not a hole. */ 419 if (ir_holemask != cluster_mask && ir_holemask != 0) { 420 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 421 return 0; 422 } 423 424 /* If any part of this is a hole, skip it. */ 425 if (ir_holemask) { 426 xchk_xref_is_not_owned_by(bs->sc, agbno, 427 M_IGEO(mp)->blocks_per_cluster, 428 &XFS_RMAP_OINFO_INODES); 429 return 0; 430 } 431 432 xchk_xref_is_only_owned_by(bs->sc, agbno, M_IGEO(mp)->blocks_per_cluster, 433 &XFS_RMAP_OINFO_INODES); 434 435 /* Grab the inode cluster buffer. */ 436 error = xfs_read_icluster(pag, bs->cur->bc_tp, imap.im_agbno, 437 &cluster_bp); 438 if (!xchk_btree_xref_process_error(bs->sc, bs->cur, 0, &error)) 439 return error; 440 441 /* Check free status of each inode within this cluster. */ 442 for (cluster_index = 0; cluster_index < nr_inodes; cluster_index++) { 443 struct xfs_dinode *dip; 444 445 if (imap.im_boffset >= BBTOB(cluster_bp->b_length)) { 446 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 447 break; 448 } 449 450 dip = xfs_buf_offset(cluster_bp, imap.im_boffset); 451 error = xchk_iallocbt_check_cluster_ifree(bs, irec, 452 cluster_base + cluster_index, dip); 453 if (error) 454 break; 455 imap.im_boffset += mp->m_sb.sb_inodesize; 456 } 457 458 xfs_trans_brelse(bs->cur->bc_tp, cluster_bp); 459 return error; 460 } 461 462 /* 463 * For all the inode clusters that could map to this inobt record, make sure 464 * that the holemask makes sense and that the allocation status of each inode 465 * matches the freemask. 466 */ 467 STATIC int 468 xchk_iallocbt_check_clusters( 469 struct xchk_btree *bs, 470 struct xfs_inobt_rec_incore *irec) 471 { 472 unsigned int cluster_base; 473 int error = 0; 474 475 /* 476 * For the common case where this inobt record maps to multiple inode 477 * clusters this will call _check_cluster for each cluster. 478 * 479 * For the case that multiple inobt records map to a single cluster, 480 * this will call _check_cluster once. 481 */ 482 for (cluster_base = 0; 483 cluster_base < XFS_INODES_PER_CHUNK; 484 cluster_base += M_IGEO(bs->sc->mp)->inodes_per_cluster) { 485 error = xchk_iallocbt_check_cluster(bs, irec, cluster_base); 486 if (error) 487 break; 488 } 489 490 return error; 491 } 492 493 /* 494 * Make sure this inode btree record is aligned properly. Because a fs block 495 * contains multiple inodes, we check that the inobt record is aligned to the 496 * correct inode, not just the correct block on disk. This results in a finer 497 * grained corruption check. 498 */ 499 STATIC void 500 xchk_iallocbt_rec_alignment( 501 struct xchk_btree *bs, 502 struct xfs_inobt_rec_incore *irec) 503 { 504 struct xfs_mount *mp = bs->sc->mp; 505 struct xchk_iallocbt *iabt = bs->private; 506 struct xfs_ino_geometry *igeo = M_IGEO(mp); 507 508 /* 509 * finobt records have different positioning requirements than inobt 510 * records: each finobt record must have a corresponding inobt record. 511 * That is checked in the xref function, so for now we only catch the 512 * obvious case where the record isn't at all aligned properly. 513 * 514 * Note that if a fs block contains more than a single chunk of inodes, 515 * we will have finobt records only for those chunks containing free 516 * inodes, and therefore expect chunk alignment of finobt records. 517 * Otherwise, we expect that the finobt record is aligned to the 518 * cluster alignment as told by the superblock. 519 */ 520 if (xfs_btree_is_fino(bs->cur->bc_ops)) { 521 unsigned int imask; 522 523 imask = min_t(unsigned int, XFS_INODES_PER_CHUNK, 524 igeo->cluster_align_inodes) - 1; 525 if (irec->ir_startino & imask) 526 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 527 return; 528 } 529 530 if (iabt->next_startino != NULLAGINO) { 531 /* 532 * We're midway through a cluster of inodes that is mapped by 533 * multiple inobt records. Did we get the record for the next 534 * irec in the sequence? 535 */ 536 if (irec->ir_startino != iabt->next_startino) { 537 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 538 return; 539 } 540 541 iabt->next_startino += XFS_INODES_PER_CHUNK; 542 543 /* Are we done with the cluster? */ 544 if (iabt->next_startino >= iabt->next_cluster_ino) { 545 iabt->next_startino = NULLAGINO; 546 iabt->next_cluster_ino = NULLAGINO; 547 } 548 return; 549 } 550 551 /* inobt records must be aligned to cluster and inoalignmnt size. */ 552 if (irec->ir_startino & (igeo->cluster_align_inodes - 1)) { 553 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 554 return; 555 } 556 557 if (irec->ir_startino & (igeo->inodes_per_cluster - 1)) { 558 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 559 return; 560 } 561 562 if (igeo->inodes_per_cluster <= XFS_INODES_PER_CHUNK) 563 return; 564 565 /* 566 * If this is the start of an inode cluster that can be mapped by 567 * multiple inobt records, the next inobt record must follow exactly 568 * after this one. 569 */ 570 iabt->next_startino = irec->ir_startino + XFS_INODES_PER_CHUNK; 571 iabt->next_cluster_ino = irec->ir_startino + igeo->inodes_per_cluster; 572 } 573 574 /* Scrub an inobt/finobt record. */ 575 STATIC int 576 xchk_iallocbt_rec( 577 struct xchk_btree *bs, 578 const union xfs_btree_rec *rec) 579 { 580 struct xfs_mount *mp = bs->cur->bc_mp; 581 struct xchk_iallocbt *iabt = bs->private; 582 struct xfs_inobt_rec_incore irec; 583 uint64_t holes; 584 xfs_agino_t agino; 585 int holecount; 586 int i; 587 int error = 0; 588 uint16_t holemask; 589 590 xfs_inobt_btrec_to_irec(mp, rec, &irec); 591 if (xfs_inobt_check_irec(to_perag(bs->cur->bc_group), &irec) != NULL) { 592 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 593 return 0; 594 } 595 596 agino = irec.ir_startino; 597 598 xchk_iallocbt_rec_alignment(bs, &irec); 599 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 600 goto out; 601 602 iabt->inodes += irec.ir_count; 603 604 /* Handle non-sparse inodes */ 605 if (!xfs_inobt_issparse(irec.ir_holemask)) { 606 if (irec.ir_count != XFS_INODES_PER_CHUNK) 607 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 608 609 if (!xchk_iallocbt_chunk(bs, &irec, agino, 610 XFS_INODES_PER_CHUNK)) 611 goto out; 612 goto check_clusters; 613 } 614 615 /* Check each chunk of a sparse inode cluster. */ 616 holemask = irec.ir_holemask; 617 holecount = 0; 618 holes = ~xfs_inobt_irec_to_allocmask(&irec); 619 if ((holes & irec.ir_free) != holes || 620 irec.ir_freecount > irec.ir_count) 621 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 622 623 for (i = 0; i < XFS_INOBT_HOLEMASK_BITS; i++) { 624 if (holemask & 1) 625 holecount += XFS_INODES_PER_HOLEMASK_BIT; 626 else if (!xchk_iallocbt_chunk(bs, &irec, agino, 627 XFS_INODES_PER_HOLEMASK_BIT)) 628 goto out; 629 holemask >>= 1; 630 agino += XFS_INODES_PER_HOLEMASK_BIT; 631 } 632 633 if (holecount > XFS_INODES_PER_CHUNK || 634 holecount + irec.ir_count != XFS_INODES_PER_CHUNK) 635 xchk_btree_set_corrupt(bs->sc, bs->cur, 0); 636 637 check_clusters: 638 if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 639 goto out; 640 641 error = xchk_iallocbt_check_clusters(bs, &irec); 642 if (error) 643 goto out; 644 645 out: 646 return error; 647 } 648 649 /* 650 * Make sure the inode btrees are as large as the rmap thinks they are. 651 * Don't bother if we're missing btree cursors, as we're already corrupt. 652 */ 653 STATIC void 654 xchk_iallocbt_xref_rmap_btreeblks( 655 struct xfs_scrub *sc) 656 { 657 xfs_filblks_t blocks; 658 xfs_filblks_t inobt_blocks = 0; 659 xfs_filblks_t finobt_blocks = 0; 660 int error; 661 662 if (!sc->sa.ino_cur || !sc->sa.rmap_cur || 663 (xfs_has_finobt(sc->mp) && !sc->sa.fino_cur) || 664 xchk_skip_xref(sc->sm)) 665 return; 666 667 /* Check that we saw as many inobt blocks as the rmap says. */ 668 error = xfs_btree_count_blocks(sc->sa.ino_cur, &inobt_blocks); 669 if (!xchk_process_error(sc, 0, 0, &error)) 670 return; 671 672 if (sc->sa.fino_cur) { 673 error = xfs_btree_count_blocks(sc->sa.fino_cur, &finobt_blocks); 674 if (!xchk_process_error(sc, 0, 0, &error)) 675 return; 676 } 677 678 error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, 679 &XFS_RMAP_OINFO_INOBT, &blocks); 680 if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) 681 return; 682 if (blocks != inobt_blocks + finobt_blocks) 683 xchk_btree_set_corrupt(sc, sc->sa.ino_cur, 0); 684 } 685 686 /* 687 * Make sure that the inobt records point to the same number of blocks as 688 * the rmap says are owned by inodes. 689 */ 690 STATIC void 691 xchk_iallocbt_xref_rmap_inodes( 692 struct xfs_scrub *sc, 693 unsigned long long inodes) 694 { 695 xfs_filblks_t blocks; 696 xfs_filblks_t inode_blocks; 697 int error; 698 699 if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm)) 700 return; 701 702 /* Check that we saw as many inode blocks as the rmap knows about. */ 703 error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur, 704 &XFS_RMAP_OINFO_INODES, &blocks); 705 if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur)) 706 return; 707 inode_blocks = XFS_B_TO_FSB(sc->mp, inodes * sc->mp->m_sb.sb_inodesize); 708 if (blocks != inode_blocks) 709 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0); 710 } 711 712 /* Scrub one of the inode btrees for some AG. */ 713 int 714 xchk_iallocbt( 715 struct xfs_scrub *sc) 716 { 717 struct xfs_btree_cur *cur; 718 struct xchk_iallocbt iabt = { 719 .inodes = 0, 720 .next_startino = NULLAGINO, 721 .next_cluster_ino = NULLAGINO, 722 }; 723 int error; 724 725 switch (sc->sm->sm_type) { 726 case XFS_SCRUB_TYPE_INOBT: 727 cur = sc->sa.ino_cur; 728 break; 729 case XFS_SCRUB_TYPE_FINOBT: 730 cur = sc->sa.fino_cur; 731 break; 732 default: 733 ASSERT(0); 734 return -EIO; 735 } 736 737 error = xchk_btree(sc, cur, xchk_iallocbt_rec, &XFS_RMAP_OINFO_INOBT, 738 &iabt); 739 if (error) 740 return error; 741 742 xchk_iallocbt_xref_rmap_btreeblks(sc); 743 744 /* 745 * If we're scrubbing the inode btree, inode_blocks is the number of 746 * blocks pointed to by all the inode chunk records. Therefore, we 747 * should compare to the number of inode chunk blocks that the rmap 748 * knows about. We can't do this for the finobt since it only points 749 * to inode chunks with free inodes. 750 */ 751 if (sc->sm->sm_type == XFS_SCRUB_TYPE_INOBT) 752 xchk_iallocbt_xref_rmap_inodes(sc, iabt.inodes); 753 return error; 754 } 755 756 /* See if an inode btree has (or doesn't have) an inode chunk record. */ 757 static inline void 758 xchk_xref_inode_check( 759 struct xfs_scrub *sc, 760 xfs_agblock_t agbno, 761 xfs_extlen_t len, 762 struct xfs_btree_cur **icur, 763 enum xbtree_recpacking expected) 764 { 765 enum xbtree_recpacking outcome; 766 int error; 767 768 if (!(*icur) || xchk_skip_xref(sc->sm)) 769 return; 770 771 error = xfs_ialloc_has_inodes_at_extent(*icur, agbno, len, &outcome); 772 if (!xchk_should_check_xref(sc, &error, icur)) 773 return; 774 if (outcome != expected) 775 xchk_btree_xref_set_corrupt(sc, *icur, 0); 776 } 777 778 /* xref check that the extent is not covered by inodes */ 779 void 780 xchk_xref_is_not_inode_chunk( 781 struct xfs_scrub *sc, 782 xfs_agblock_t agbno, 783 xfs_extlen_t len) 784 { 785 xchk_xref_inode_check(sc, agbno, len, &sc->sa.ino_cur, 786 XBTREE_RECPACKING_EMPTY); 787 xchk_xref_inode_check(sc, agbno, len, &sc->sa.fino_cur, 788 XBTREE_RECPACKING_EMPTY); 789 } 790 791 /* xref check that the extent is covered by inodes */ 792 void 793 xchk_xref_is_inode_chunk( 794 struct xfs_scrub *sc, 795 xfs_agblock_t agbno, 796 xfs_extlen_t len) 797 { 798 xchk_xref_inode_check(sc, agbno, len, &sc->sa.ino_cur, 799 XBTREE_RECPACKING_FULL); 800 } 801