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