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_btree.h" 13 #include "xfs_bit.h" 14 #include "xfs_log_format.h" 15 #include "xfs_trans.h" 16 #include "xfs_inode.h" 17 #include "xfs_alloc.h" 18 #include "xfs_bmap.h" 19 #include "xfs_bmap_btree.h" 20 #include "xfs_rmap.h" 21 #include "xfs_rmap_btree.h" 22 #include "scrub/scrub.h" 23 #include "scrub/common.h" 24 #include "scrub/btree.h" 25 #include "xfs_ag.h" 26 27 /* Set us up with an inode's bmap. */ 28 int 29 xchk_setup_inode_bmap( 30 struct xfs_scrub *sc) 31 { 32 int error; 33 34 error = xchk_get_inode(sc); 35 if (error) 36 goto out; 37 38 sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL; 39 xfs_ilock(sc->ip, sc->ilock_flags); 40 41 /* 42 * We don't want any ephemeral data fork updates sitting around 43 * while we inspect block mappings, so wait for directio to finish 44 * and flush dirty data if we have delalloc reservations. 45 */ 46 if (S_ISREG(VFS_I(sc->ip)->i_mode) && 47 sc->sm->sm_type == XFS_SCRUB_TYPE_BMBTD) { 48 struct address_space *mapping = VFS_I(sc->ip)->i_mapping; 49 50 inode_dio_wait(VFS_I(sc->ip)); 51 52 /* 53 * Try to flush all incore state to disk before we examine the 54 * space mappings for the data fork. Leave accumulated errors 55 * in the mapping for the writer threads to consume. 56 * 57 * On ENOSPC or EIO writeback errors, we continue into the 58 * extent mapping checks because write failures do not 59 * necessarily imply anything about the correctness of the file 60 * metadata. The metadata and the file data could be on 61 * completely separate devices; a media failure might only 62 * affect a subset of the disk, etc. We can handle delalloc 63 * extents in the scrubber, so leaving them in memory is fine. 64 */ 65 error = filemap_fdatawrite(mapping); 66 if (!error) 67 error = filemap_fdatawait_keep_errors(mapping); 68 if (error && (error != -ENOSPC && error != -EIO)) 69 goto out; 70 } 71 72 /* Got the inode, lock it and we're ready to go. */ 73 error = xchk_trans_alloc(sc, 0); 74 if (error) 75 goto out; 76 sc->ilock_flags |= XFS_ILOCK_EXCL; 77 xfs_ilock(sc->ip, XFS_ILOCK_EXCL); 78 79 out: 80 /* scrub teardown will unlock and release the inode */ 81 return error; 82 } 83 84 /* 85 * Inode fork block mapping (BMBT) scrubber. 86 * More complex than the others because we have to scrub 87 * all the extents regardless of whether or not the fork 88 * is in btree format. 89 */ 90 91 struct xchk_bmap_info { 92 struct xfs_scrub *sc; 93 struct xfs_iext_cursor icur; 94 xfs_fileoff_t lastoff; 95 bool is_rt; 96 bool is_shared; 97 bool was_loaded; 98 int whichfork; 99 }; 100 101 /* Look for a corresponding rmap for this irec. */ 102 static inline bool 103 xchk_bmap_get_rmap( 104 struct xchk_bmap_info *info, 105 struct xfs_bmbt_irec *irec, 106 xfs_agblock_t agbno, 107 uint64_t owner, 108 struct xfs_rmap_irec *rmap) 109 { 110 xfs_fileoff_t offset; 111 unsigned int rflags = 0; 112 int has_rmap; 113 int error; 114 115 if (info->whichfork == XFS_ATTR_FORK) 116 rflags |= XFS_RMAP_ATTR_FORK; 117 if (irec->br_state == XFS_EXT_UNWRITTEN) 118 rflags |= XFS_RMAP_UNWRITTEN; 119 120 /* 121 * CoW staging extents are owned (on disk) by the refcountbt, so 122 * their rmaps do not have offsets. 123 */ 124 if (info->whichfork == XFS_COW_FORK) 125 offset = 0; 126 else 127 offset = irec->br_startoff; 128 129 /* 130 * If the caller thinks this could be a shared bmbt extent (IOWs, 131 * any data fork extent of a reflink inode) then we have to use the 132 * range rmap lookup to make sure we get the correct owner/offset. 133 */ 134 if (info->is_shared) { 135 error = xfs_rmap_lookup_le_range(info->sc->sa.rmap_cur, agbno, 136 owner, offset, rflags, rmap, &has_rmap); 137 } else { 138 error = xfs_rmap_lookup_le(info->sc->sa.rmap_cur, agbno, 139 owner, offset, rflags, rmap, &has_rmap); 140 } 141 if (!xchk_should_check_xref(info->sc, &error, &info->sc->sa.rmap_cur)) 142 return false; 143 144 if (!has_rmap) 145 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 146 irec->br_startoff); 147 return has_rmap; 148 } 149 150 static inline bool 151 xchk_bmap_has_prev( 152 struct xchk_bmap_info *info, 153 struct xfs_bmbt_irec *irec) 154 { 155 struct xfs_bmbt_irec got; 156 struct xfs_ifork *ifp; 157 158 ifp = xfs_ifork_ptr(info->sc->ip, info->whichfork); 159 160 if (!xfs_iext_peek_prev_extent(ifp, &info->icur, &got)) 161 return false; 162 if (got.br_startoff + got.br_blockcount != irec->br_startoff) 163 return false; 164 if (got.br_startblock + got.br_blockcount != irec->br_startblock) 165 return false; 166 if (got.br_state != irec->br_state) 167 return false; 168 return true; 169 } 170 171 static inline bool 172 xchk_bmap_has_next( 173 struct xchk_bmap_info *info, 174 struct xfs_bmbt_irec *irec) 175 { 176 struct xfs_bmbt_irec got; 177 struct xfs_ifork *ifp; 178 179 ifp = xfs_ifork_ptr(info->sc->ip, info->whichfork); 180 181 if (!xfs_iext_peek_next_extent(ifp, &info->icur, &got)) 182 return false; 183 if (irec->br_startoff + irec->br_blockcount != got.br_startoff) 184 return false; 185 if (irec->br_startblock + irec->br_blockcount != got.br_startblock) 186 return false; 187 if (got.br_state != irec->br_state) 188 return false; 189 return true; 190 } 191 192 /* Make sure that we have rmapbt records for this extent. */ 193 STATIC void 194 xchk_bmap_xref_rmap( 195 struct xchk_bmap_info *info, 196 struct xfs_bmbt_irec *irec, 197 xfs_agblock_t agbno) 198 { 199 struct xfs_rmap_irec rmap; 200 unsigned long long rmap_end; 201 uint64_t owner; 202 203 if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm)) 204 return; 205 206 if (info->whichfork == XFS_COW_FORK) 207 owner = XFS_RMAP_OWN_COW; 208 else 209 owner = info->sc->ip->i_ino; 210 211 /* Find the rmap record for this irec. */ 212 if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap)) 213 return; 214 215 /* Check the rmap. */ 216 rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount; 217 if (rmap.rm_startblock > agbno || 218 agbno + irec->br_blockcount > rmap_end) 219 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 220 irec->br_startoff); 221 222 /* 223 * Check the logical offsets if applicable. CoW staging extents 224 * don't track logical offsets since the mappings only exist in 225 * memory. 226 */ 227 if (info->whichfork != XFS_COW_FORK) { 228 rmap_end = (unsigned long long)rmap.rm_offset + 229 rmap.rm_blockcount; 230 if (rmap.rm_offset > irec->br_startoff || 231 irec->br_startoff + irec->br_blockcount > rmap_end) 232 xchk_fblock_xref_set_corrupt(info->sc, 233 info->whichfork, irec->br_startoff); 234 } 235 236 if (rmap.rm_owner != owner) 237 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 238 irec->br_startoff); 239 240 /* 241 * Check for discrepancies between the unwritten flag in the irec and 242 * the rmap. Note that the (in-memory) CoW fork distinguishes between 243 * unwritten and written extents, but we don't track that in the rmap 244 * records because the blocks are owned (on-disk) by the refcountbt, 245 * which doesn't track unwritten state. 246 */ 247 if (owner != XFS_RMAP_OWN_COW && 248 !!(irec->br_state == XFS_EXT_UNWRITTEN) != 249 !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN)) 250 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 251 irec->br_startoff); 252 253 if (!!(info->whichfork == XFS_ATTR_FORK) != 254 !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK)) 255 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 256 irec->br_startoff); 257 if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK) 258 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 259 irec->br_startoff); 260 261 /* 262 * If the rmap starts before this bmbt record, make sure there's a bmbt 263 * record for the previous offset that is contiguous with this mapping. 264 * Skip this for CoW fork extents because the refcount btree (and not 265 * the inode) is the ondisk owner for those extents. 266 */ 267 if (info->whichfork != XFS_COW_FORK && rmap.rm_startblock < agbno && 268 !xchk_bmap_has_prev(info, irec)) { 269 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 270 irec->br_startoff); 271 return; 272 } 273 274 /* 275 * If the rmap ends after this bmbt record, make sure there's a bmbt 276 * record for the next offset that is contiguous with this mapping. 277 * Skip this for CoW fork extents because the refcount btree (and not 278 * the inode) is the ondisk owner for those extents. 279 */ 280 rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount; 281 if (info->whichfork != XFS_COW_FORK && 282 rmap_end > agbno + irec->br_blockcount && 283 !xchk_bmap_has_next(info, irec)) { 284 xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, 285 irec->br_startoff); 286 return; 287 } 288 } 289 290 /* Cross-reference a single rtdev extent record. */ 291 STATIC void 292 xchk_bmap_rt_iextent_xref( 293 struct xfs_inode *ip, 294 struct xchk_bmap_info *info, 295 struct xfs_bmbt_irec *irec) 296 { 297 xchk_xref_is_used_rt_space(info->sc, irec->br_startblock, 298 irec->br_blockcount); 299 } 300 301 /* Cross-reference a single datadev extent record. */ 302 STATIC void 303 xchk_bmap_iextent_xref( 304 struct xfs_inode *ip, 305 struct xchk_bmap_info *info, 306 struct xfs_bmbt_irec *irec) 307 { 308 struct xfs_mount *mp = info->sc->mp; 309 xfs_agnumber_t agno; 310 xfs_agblock_t agbno; 311 xfs_extlen_t len; 312 int error; 313 314 agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock); 315 agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); 316 len = irec->br_blockcount; 317 318 error = xchk_ag_init_existing(info->sc, agno, &info->sc->sa); 319 if (!xchk_fblock_process_error(info->sc, info->whichfork, 320 irec->br_startoff, &error)) 321 goto out_free; 322 323 xchk_xref_is_used_space(info->sc, agbno, len); 324 xchk_xref_is_not_inode_chunk(info->sc, agbno, len); 325 xchk_bmap_xref_rmap(info, irec, agbno); 326 switch (info->whichfork) { 327 case XFS_DATA_FORK: 328 if (xfs_is_reflink_inode(info->sc->ip)) 329 break; 330 fallthrough; 331 case XFS_ATTR_FORK: 332 xchk_xref_is_not_shared(info->sc, agbno, 333 irec->br_blockcount); 334 break; 335 case XFS_COW_FORK: 336 xchk_xref_is_cow_staging(info->sc, agbno, 337 irec->br_blockcount); 338 xchk_xref_is_not_shared(info->sc, agbno, 339 irec->br_blockcount); 340 break; 341 } 342 343 out_free: 344 xchk_ag_free(info->sc, &info->sc->sa); 345 } 346 347 /* 348 * Directories and attr forks should never have blocks that can't be addressed 349 * by a xfs_dablk_t. 350 */ 351 STATIC void 352 xchk_bmap_dirattr_extent( 353 struct xfs_inode *ip, 354 struct xchk_bmap_info *info, 355 struct xfs_bmbt_irec *irec) 356 { 357 struct xfs_mount *mp = ip->i_mount; 358 xfs_fileoff_t off; 359 360 if (!S_ISDIR(VFS_I(ip)->i_mode) && info->whichfork != XFS_ATTR_FORK) 361 return; 362 363 if (!xfs_verify_dablk(mp, irec->br_startoff)) 364 xchk_fblock_set_corrupt(info->sc, info->whichfork, 365 irec->br_startoff); 366 367 off = irec->br_startoff + irec->br_blockcount - 1; 368 if (!xfs_verify_dablk(mp, off)) 369 xchk_fblock_set_corrupt(info->sc, info->whichfork, off); 370 } 371 372 /* Scrub a single extent record. */ 373 STATIC void 374 xchk_bmap_iextent( 375 struct xfs_inode *ip, 376 struct xchk_bmap_info *info, 377 struct xfs_bmbt_irec *irec) 378 { 379 struct xfs_mount *mp = info->sc->mp; 380 381 /* 382 * Check for out-of-order extents. This record could have come 383 * from the incore list, for which there is no ordering check. 384 */ 385 if (irec->br_startoff < info->lastoff) 386 xchk_fblock_set_corrupt(info->sc, info->whichfork, 387 irec->br_startoff); 388 389 if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount)) 390 xchk_fblock_set_corrupt(info->sc, info->whichfork, 391 irec->br_startoff); 392 393 xchk_bmap_dirattr_extent(ip, info, irec); 394 395 /* There should never be a "hole" extent in either extent list. */ 396 if (irec->br_startblock == HOLESTARTBLOCK) 397 xchk_fblock_set_corrupt(info->sc, info->whichfork, 398 irec->br_startoff); 399 400 /* Make sure the extent points to a valid place. */ 401 if (irec->br_blockcount > XFS_MAX_BMBT_EXTLEN) 402 xchk_fblock_set_corrupt(info->sc, info->whichfork, 403 irec->br_startoff); 404 if (info->is_rt && 405 !xfs_verify_rtext(mp, irec->br_startblock, irec->br_blockcount)) 406 xchk_fblock_set_corrupt(info->sc, info->whichfork, 407 irec->br_startoff); 408 if (!info->is_rt && 409 !xfs_verify_fsbext(mp, irec->br_startblock, irec->br_blockcount)) 410 xchk_fblock_set_corrupt(info->sc, info->whichfork, 411 irec->br_startoff); 412 413 /* We don't allow unwritten extents on attr forks. */ 414 if (irec->br_state == XFS_EXT_UNWRITTEN && 415 info->whichfork == XFS_ATTR_FORK) 416 xchk_fblock_set_corrupt(info->sc, info->whichfork, 417 irec->br_startoff); 418 419 if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 420 return; 421 422 if (info->is_rt) 423 xchk_bmap_rt_iextent_xref(ip, info, irec); 424 else 425 xchk_bmap_iextent_xref(ip, info, irec); 426 } 427 428 /* Scrub a bmbt record. */ 429 STATIC int 430 xchk_bmapbt_rec( 431 struct xchk_btree *bs, 432 const union xfs_btree_rec *rec) 433 { 434 struct xfs_bmbt_irec irec; 435 struct xfs_bmbt_irec iext_irec; 436 struct xfs_iext_cursor icur; 437 struct xchk_bmap_info *info = bs->private; 438 struct xfs_inode *ip = bs->cur->bc_ino.ip; 439 struct xfs_buf *bp = NULL; 440 struct xfs_btree_block *block; 441 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, info->whichfork); 442 uint64_t owner; 443 int i; 444 445 /* 446 * Check the owners of the btree blocks up to the level below 447 * the root since the verifiers don't do that. 448 */ 449 if (xfs_has_crc(bs->cur->bc_mp) && 450 bs->cur->bc_levels[0].ptr == 1) { 451 for (i = 0; i < bs->cur->bc_nlevels - 1; i++) { 452 block = xfs_btree_get_block(bs->cur, i, &bp); 453 owner = be64_to_cpu(block->bb_u.l.bb_owner); 454 if (owner != ip->i_ino) 455 xchk_fblock_set_corrupt(bs->sc, 456 info->whichfork, 0); 457 } 458 } 459 460 /* 461 * Check that the incore extent tree contains an extent that matches 462 * this one exactly. We validate those cached bmaps later, so we don't 463 * need to check them here. If the incore extent tree was just loaded 464 * from disk by the scrubber, we assume that its contents match what's 465 * on disk (we still hold the ILOCK) and skip the equivalence check. 466 */ 467 if (!info->was_loaded) 468 return 0; 469 470 xfs_bmbt_disk_get_all(&rec->bmbt, &irec); 471 if (!xfs_iext_lookup_extent(ip, ifp, irec.br_startoff, &icur, 472 &iext_irec) || 473 irec.br_startoff != iext_irec.br_startoff || 474 irec.br_startblock != iext_irec.br_startblock || 475 irec.br_blockcount != iext_irec.br_blockcount || 476 irec.br_state != iext_irec.br_state) 477 xchk_fblock_set_corrupt(bs->sc, info->whichfork, 478 irec.br_startoff); 479 return 0; 480 } 481 482 /* Scan the btree records. */ 483 STATIC int 484 xchk_bmap_btree( 485 struct xfs_scrub *sc, 486 int whichfork, 487 struct xchk_bmap_info *info) 488 { 489 struct xfs_owner_info oinfo; 490 struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, whichfork); 491 struct xfs_mount *mp = sc->mp; 492 struct xfs_inode *ip = sc->ip; 493 struct xfs_btree_cur *cur; 494 int error; 495 496 /* Load the incore bmap cache if it's not loaded. */ 497 info->was_loaded = !xfs_need_iread_extents(ifp); 498 499 error = xfs_iread_extents(sc->tp, ip, whichfork); 500 if (!xchk_fblock_process_error(sc, whichfork, 0, &error)) 501 goto out; 502 503 /* Check the btree structure. */ 504 cur = xfs_bmbt_init_cursor(mp, sc->tp, ip, whichfork); 505 xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork); 506 error = xchk_btree(sc, cur, xchk_bmapbt_rec, &oinfo, info); 507 xfs_btree_del_cursor(cur, error); 508 out: 509 return error; 510 } 511 512 struct xchk_bmap_check_rmap_info { 513 struct xfs_scrub *sc; 514 int whichfork; 515 struct xfs_iext_cursor icur; 516 }; 517 518 /* Can we find bmaps that fit this rmap? */ 519 STATIC int 520 xchk_bmap_check_rmap( 521 struct xfs_btree_cur *cur, 522 const struct xfs_rmap_irec *rec, 523 void *priv) 524 { 525 struct xfs_bmbt_irec irec; 526 struct xfs_rmap_irec check_rec; 527 struct xchk_bmap_check_rmap_info *sbcri = priv; 528 struct xfs_ifork *ifp; 529 struct xfs_scrub *sc = sbcri->sc; 530 bool have_map; 531 532 /* Is this even the right fork? */ 533 if (rec->rm_owner != sc->ip->i_ino) 534 return 0; 535 if ((sbcri->whichfork == XFS_ATTR_FORK) ^ 536 !!(rec->rm_flags & XFS_RMAP_ATTR_FORK)) 537 return 0; 538 if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK) 539 return 0; 540 541 /* Now look up the bmbt record. */ 542 ifp = xfs_ifork_ptr(sc->ip, sbcri->whichfork); 543 if (!ifp) { 544 xchk_fblock_set_corrupt(sc, sbcri->whichfork, 545 rec->rm_offset); 546 goto out; 547 } 548 have_map = xfs_iext_lookup_extent(sc->ip, ifp, rec->rm_offset, 549 &sbcri->icur, &irec); 550 if (!have_map) 551 xchk_fblock_set_corrupt(sc, sbcri->whichfork, 552 rec->rm_offset); 553 /* 554 * bmap extent record lengths are constrained to 2^21 blocks in length 555 * because of space constraints in the on-disk metadata structure. 556 * However, rmap extent record lengths are constrained only by AG 557 * length, so we have to loop through the bmbt to make sure that the 558 * entire rmap is covered by bmbt records. 559 */ 560 check_rec = *rec; 561 while (have_map) { 562 if (irec.br_startoff != check_rec.rm_offset) 563 xchk_fblock_set_corrupt(sc, sbcri->whichfork, 564 check_rec.rm_offset); 565 if (irec.br_startblock != XFS_AGB_TO_FSB(sc->mp, 566 cur->bc_ag.pag->pag_agno, 567 check_rec.rm_startblock)) 568 xchk_fblock_set_corrupt(sc, sbcri->whichfork, 569 check_rec.rm_offset); 570 if (irec.br_blockcount > check_rec.rm_blockcount) 571 xchk_fblock_set_corrupt(sc, sbcri->whichfork, 572 check_rec.rm_offset); 573 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 574 break; 575 check_rec.rm_startblock += irec.br_blockcount; 576 check_rec.rm_offset += irec.br_blockcount; 577 check_rec.rm_blockcount -= irec.br_blockcount; 578 if (check_rec.rm_blockcount == 0) 579 break; 580 have_map = xfs_iext_next_extent(ifp, &sbcri->icur, &irec); 581 if (!have_map) 582 xchk_fblock_set_corrupt(sc, sbcri->whichfork, 583 check_rec.rm_offset); 584 } 585 586 out: 587 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 588 return -ECANCELED; 589 return 0; 590 } 591 592 /* Make sure each rmap has a corresponding bmbt entry. */ 593 STATIC int 594 xchk_bmap_check_ag_rmaps( 595 struct xfs_scrub *sc, 596 int whichfork, 597 struct xfs_perag *pag) 598 { 599 struct xchk_bmap_check_rmap_info sbcri; 600 struct xfs_btree_cur *cur; 601 struct xfs_buf *agf; 602 int error; 603 604 error = xfs_alloc_read_agf(pag, sc->tp, 0, &agf); 605 if (error) 606 return error; 607 608 cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, agf, pag); 609 610 sbcri.sc = sc; 611 sbcri.whichfork = whichfork; 612 error = xfs_rmap_query_all(cur, xchk_bmap_check_rmap, &sbcri); 613 if (error == -ECANCELED) 614 error = 0; 615 616 xfs_btree_del_cursor(cur, error); 617 xfs_trans_brelse(sc->tp, agf); 618 return error; 619 } 620 621 /* Make sure each rmap has a corresponding bmbt entry. */ 622 STATIC int 623 xchk_bmap_check_rmaps( 624 struct xfs_scrub *sc, 625 int whichfork) 626 { 627 struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, whichfork); 628 struct xfs_perag *pag; 629 xfs_agnumber_t agno; 630 bool zero_size; 631 int error; 632 633 if (!xfs_has_rmapbt(sc->mp) || 634 whichfork == XFS_COW_FORK || 635 (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 636 return 0; 637 638 /* Don't support realtime rmap checks yet. */ 639 if (XFS_IS_REALTIME_INODE(sc->ip) && whichfork == XFS_DATA_FORK) 640 return 0; 641 642 ASSERT(xfs_ifork_ptr(sc->ip, whichfork) != NULL); 643 644 /* 645 * Only do this for complex maps that are in btree format, or for 646 * situations where we would seem to have a size but zero extents. 647 * The inode repair code can zap broken iforks, which means we have 648 * to flag this bmap as corrupt if there are rmaps that need to be 649 * reattached. 650 */ 651 652 if (whichfork == XFS_DATA_FORK) 653 zero_size = i_size_read(VFS_I(sc->ip)) == 0; 654 else 655 zero_size = false; 656 657 if (ifp->if_format != XFS_DINODE_FMT_BTREE && 658 (zero_size || ifp->if_nextents > 0)) 659 return 0; 660 661 for_each_perag(sc->mp, agno, pag) { 662 error = xchk_bmap_check_ag_rmaps(sc, whichfork, pag); 663 if (error || 664 (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) { 665 xfs_perag_rele(pag); 666 return error; 667 } 668 } 669 670 return 0; 671 } 672 673 /* Scrub a delalloc reservation from the incore extent map tree. */ 674 STATIC void 675 xchk_bmap_iextent_delalloc( 676 struct xfs_inode *ip, 677 struct xchk_bmap_info *info, 678 struct xfs_bmbt_irec *irec) 679 { 680 struct xfs_mount *mp = info->sc->mp; 681 682 /* 683 * Check for out-of-order extents. This record could have come 684 * from the incore list, for which there is no ordering check. 685 */ 686 if (irec->br_startoff < info->lastoff) 687 xchk_fblock_set_corrupt(info->sc, info->whichfork, 688 irec->br_startoff); 689 690 if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount)) 691 xchk_fblock_set_corrupt(info->sc, info->whichfork, 692 irec->br_startoff); 693 694 /* Make sure the extent points to a valid place. */ 695 if (irec->br_blockcount > XFS_MAX_BMBT_EXTLEN) 696 xchk_fblock_set_corrupt(info->sc, info->whichfork, 697 irec->br_startoff); 698 } 699 700 /* 701 * Scrub an inode fork's block mappings. 702 * 703 * First we scan every record in every btree block, if applicable. 704 * Then we unconditionally scan the incore extent cache. 705 */ 706 STATIC int 707 xchk_bmap( 708 struct xfs_scrub *sc, 709 int whichfork) 710 { 711 struct xfs_bmbt_irec irec; 712 struct xchk_bmap_info info = { NULL }; 713 struct xfs_mount *mp = sc->mp; 714 struct xfs_inode *ip = sc->ip; 715 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); 716 xfs_fileoff_t endoff; 717 int error = 0; 718 719 /* Non-existent forks can be ignored. */ 720 if (!ifp) 721 goto out; 722 723 info.is_rt = whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip); 724 info.whichfork = whichfork; 725 info.is_shared = whichfork == XFS_DATA_FORK && xfs_is_reflink_inode(ip); 726 info.sc = sc; 727 728 switch (whichfork) { 729 case XFS_COW_FORK: 730 /* No CoW forks on non-reflink inodes/filesystems. */ 731 if (!xfs_is_reflink_inode(ip)) { 732 xchk_ino_set_corrupt(sc, sc->ip->i_ino); 733 goto out; 734 } 735 break; 736 case XFS_ATTR_FORK: 737 if (!xfs_has_attr(mp) && !xfs_has_attr2(mp)) 738 xchk_ino_set_corrupt(sc, sc->ip->i_ino); 739 break; 740 default: 741 ASSERT(whichfork == XFS_DATA_FORK); 742 break; 743 } 744 745 /* Check the fork values */ 746 switch (ifp->if_format) { 747 case XFS_DINODE_FMT_UUID: 748 case XFS_DINODE_FMT_DEV: 749 case XFS_DINODE_FMT_LOCAL: 750 /* No mappings to check. */ 751 if (whichfork == XFS_COW_FORK) 752 xchk_fblock_set_corrupt(sc, whichfork, 0); 753 goto out; 754 case XFS_DINODE_FMT_EXTENTS: 755 break; 756 case XFS_DINODE_FMT_BTREE: 757 if (whichfork == XFS_COW_FORK) { 758 xchk_fblock_set_corrupt(sc, whichfork, 0); 759 goto out; 760 } 761 762 error = xchk_bmap_btree(sc, whichfork, &info); 763 if (error) 764 goto out; 765 break; 766 default: 767 xchk_fblock_set_corrupt(sc, whichfork, 0); 768 goto out; 769 } 770 771 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 772 goto out; 773 774 /* Find the offset of the last extent in the mapping. */ 775 error = xfs_bmap_last_offset(ip, &endoff, whichfork); 776 if (!xchk_fblock_process_error(sc, whichfork, 0, &error)) 777 goto out; 778 779 /* Scrub extent records. */ 780 info.lastoff = 0; 781 ifp = xfs_ifork_ptr(ip, whichfork); 782 for_each_xfs_iext(ifp, &info.icur, &irec) { 783 if (xchk_should_terminate(sc, &error) || 784 (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) 785 goto out; 786 787 if (irec.br_startoff >= endoff) { 788 xchk_fblock_set_corrupt(sc, whichfork, 789 irec.br_startoff); 790 goto out; 791 } 792 793 if (isnullstartblock(irec.br_startblock)) 794 xchk_bmap_iextent_delalloc(ip, &info, &irec); 795 else 796 xchk_bmap_iextent(ip, &info, &irec); 797 info.lastoff = irec.br_startoff + irec.br_blockcount; 798 } 799 800 error = xchk_bmap_check_rmaps(sc, whichfork); 801 if (!xchk_fblock_xref_process_error(sc, whichfork, 0, &error)) 802 goto out; 803 out: 804 return error; 805 } 806 807 /* Scrub an inode's data fork. */ 808 int 809 xchk_bmap_data( 810 struct xfs_scrub *sc) 811 { 812 return xchk_bmap(sc, XFS_DATA_FORK); 813 } 814 815 /* Scrub an inode's attr fork. */ 816 int 817 xchk_bmap_attr( 818 struct xfs_scrub *sc) 819 { 820 return xchk_bmap(sc, XFS_ATTR_FORK); 821 } 822 823 /* Scrub an inode's CoW fork. */ 824 int 825 xchk_bmap_cow( 826 struct xfs_scrub *sc) 827 { 828 if (!xfs_is_reflink_inode(sc->ip)) 829 return -ENOENT; 830 831 return xchk_bmap(sc, XFS_COW_FORK); 832 } 833