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.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_log_format.h" 13 #include "xfs_trans.h" 14 #include "xfs_inode.h" 15 #include "xfs_icache.h" 16 #include "xfs_dir2.h" 17 #include "xfs_dir2_priv.h" 18 #include "scrub/scrub.h" 19 #include "scrub/common.h" 20 #include "scrub/dabtree.h" 21 #include "scrub/readdir.h" 22 23 /* Set us up to scrub directories. */ 24 int 25 xchk_setup_directory( 26 struct xfs_scrub *sc) 27 { 28 return xchk_setup_inode_contents(sc, 0); 29 } 30 31 /* Directories */ 32 33 /* Scrub a directory entry. */ 34 35 /* Check that an inode's mode matches a given XFS_DIR3_FT_* type. */ 36 STATIC void 37 xchk_dir_check_ftype( 38 struct xfs_scrub *sc, 39 xfs_fileoff_t offset, 40 struct xfs_inode *ip, 41 int ftype) 42 { 43 struct xfs_mount *mp = sc->mp; 44 45 if (!xfs_has_ftype(mp)) { 46 if (ftype != XFS_DIR3_FT_UNKNOWN && ftype != XFS_DIR3_FT_DIR) 47 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 48 return; 49 } 50 51 if (xfs_mode_to_ftype(VFS_I(ip)->i_mode) != ftype) 52 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 53 } 54 55 /* 56 * Scrub a single directory entry. 57 * 58 * Check the inode number to make sure it's sane, then we check that we can 59 * look up this filename. Finally, we check the ftype. 60 */ 61 STATIC int 62 xchk_dir_actor( 63 struct xfs_scrub *sc, 64 struct xfs_inode *dp, 65 xfs_dir2_dataptr_t dapos, 66 const struct xfs_name *name, 67 xfs_ino_t ino, 68 void *priv) 69 { 70 struct xfs_mount *mp = dp->i_mount; 71 struct xfs_inode *ip; 72 xfs_ino_t lookup_ino; 73 xfs_dablk_t offset; 74 int error = 0; 75 76 offset = xfs_dir2_db_to_da(mp->m_dir_geo, 77 xfs_dir2_dataptr_to_db(mp->m_dir_geo, dapos)); 78 79 if (xchk_should_terminate(sc, &error)) 80 return error; 81 82 /* Does this inode number make sense? */ 83 if (!xfs_verify_dir_ino(mp, ino)) { 84 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 85 return -ECANCELED; 86 } 87 88 /* Does this name make sense? */ 89 if (!xfs_dir2_namecheck(name->name, name->len)) { 90 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 91 return -ECANCELED; 92 } 93 94 if (!strncmp(".", name->name, name->len)) { 95 /* If this is "." then check that the inum matches the dir. */ 96 if (ino != dp->i_ino) 97 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 98 } else if (!strncmp("..", name->name, name->len)) { 99 /* 100 * If this is ".." in the root inode, check that the inum 101 * matches this dir. 102 */ 103 if (dp->i_ino == mp->m_sb.sb_rootino && ino != dp->i_ino) 104 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 105 } 106 107 /* Verify that we can look up this name by hash. */ 108 error = xchk_dir_lookup(sc, dp, name, &lookup_ino); 109 /* ENOENT means the hash lookup failed and the dir is corrupt */ 110 if (error == -ENOENT) 111 error = -EFSCORRUPTED; 112 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error)) 113 goto out; 114 if (lookup_ino != ino) { 115 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, offset); 116 return -ECANCELED; 117 } 118 119 /* 120 * Grab the inode pointed to by the dirent. We release the inode 121 * before we cancel the scrub transaction. 122 * 123 * If _iget returns -EINVAL or -ENOENT then the child inode number is 124 * garbage and the directory is corrupt. If the _iget returns 125 * -EFSCORRUPTED or -EFSBADCRC then the child is corrupt which is a 126 * cross referencing error. Any other error is an operational error. 127 */ 128 error = xchk_iget(sc, ino, &ip); 129 if (error == -EINVAL || error == -ENOENT) { 130 error = -EFSCORRUPTED; 131 xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error); 132 goto out; 133 } 134 if (!xchk_fblock_xref_process_error(sc, XFS_DATA_FORK, offset, &error)) 135 goto out; 136 137 xchk_dir_check_ftype(sc, offset, ip, name->type); 138 xchk_irele(sc, ip); 139 out: 140 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 141 return -ECANCELED; 142 return error; 143 } 144 145 /* Scrub a directory btree record. */ 146 STATIC int 147 xchk_dir_rec( 148 struct xchk_da_btree *ds, 149 int level) 150 { 151 struct xfs_name dname = { }; 152 struct xfs_da_state_blk *blk = &ds->state->path.blk[level]; 153 struct xfs_mount *mp = ds->state->mp; 154 struct xfs_inode *dp = ds->dargs.dp; 155 struct xfs_da_geometry *geo = mp->m_dir_geo; 156 struct xfs_dir2_data_entry *dent; 157 struct xfs_buf *bp; 158 struct xfs_dir2_leaf_entry *ent; 159 unsigned int end; 160 unsigned int iter_off; 161 xfs_ino_t ino; 162 xfs_dablk_t rec_bno; 163 xfs_dir2_db_t db; 164 xfs_dir2_data_aoff_t off; 165 xfs_dir2_dataptr_t ptr; 166 xfs_dahash_t calc_hash; 167 xfs_dahash_t hash; 168 struct xfs_dir3_icleaf_hdr hdr; 169 unsigned int tag; 170 int error; 171 172 ASSERT(blk->magic == XFS_DIR2_LEAF1_MAGIC || 173 blk->magic == XFS_DIR2_LEAFN_MAGIC); 174 175 xfs_dir2_leaf_hdr_from_disk(mp, &hdr, blk->bp->b_addr); 176 ent = hdr.ents + blk->index; 177 178 /* Check the hash of the entry. */ 179 error = xchk_da_btree_hash(ds, level, &ent->hashval); 180 if (error) 181 goto out; 182 183 /* Valid hash pointer? */ 184 ptr = be32_to_cpu(ent->address); 185 if (ptr == 0) 186 return 0; 187 188 /* Find the directory entry's location. */ 189 db = xfs_dir2_dataptr_to_db(geo, ptr); 190 off = xfs_dir2_dataptr_to_off(geo, ptr); 191 rec_bno = xfs_dir2_db_to_da(geo, db); 192 193 if (rec_bno >= geo->leafblk) { 194 xchk_da_set_corrupt(ds, level); 195 goto out; 196 } 197 error = xfs_dir3_data_read(ds->dargs.trans, dp, rec_bno, 198 XFS_DABUF_MAP_HOLE_OK, &bp); 199 if (!xchk_fblock_process_error(ds->sc, XFS_DATA_FORK, rec_bno, 200 &error)) 201 goto out; 202 if (!bp) { 203 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); 204 goto out; 205 } 206 xchk_buffer_recheck(ds->sc, bp); 207 208 if (ds->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 209 goto out_relse; 210 211 dent = bp->b_addr + off; 212 213 /* Make sure we got a real directory entry. */ 214 iter_off = geo->data_entry_offset; 215 end = xfs_dir3_data_end_offset(geo, bp->b_addr); 216 if (!end) { 217 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); 218 goto out_relse; 219 } 220 for (;;) { 221 struct xfs_dir2_data_entry *dep = bp->b_addr + iter_off; 222 struct xfs_dir2_data_unused *dup = bp->b_addr + iter_off; 223 224 if (iter_off >= end) { 225 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); 226 goto out_relse; 227 } 228 229 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { 230 iter_off += be16_to_cpu(dup->length); 231 continue; 232 } 233 if (dep == dent) 234 break; 235 iter_off += xfs_dir2_data_entsize(mp, dep->namelen); 236 } 237 238 /* Retrieve the entry, sanity check it, and compare hashes. */ 239 ino = be64_to_cpu(dent->inumber); 240 hash = be32_to_cpu(ent->hashval); 241 tag = be16_to_cpup(xfs_dir2_data_entry_tag_p(mp, dent)); 242 if (!xfs_verify_dir_ino(mp, ino) || tag != off) 243 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); 244 if (dent->namelen == 0) { 245 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); 246 goto out_relse; 247 } 248 249 /* Does the directory hash match? */ 250 dname.name = dent->name; 251 dname.len = dent->namelen; 252 calc_hash = xfs_dir2_hashname(mp, &dname); 253 if (calc_hash != hash) 254 xchk_fblock_set_corrupt(ds->sc, XFS_DATA_FORK, rec_bno); 255 256 out_relse: 257 xfs_trans_brelse(ds->dargs.trans, bp); 258 out: 259 return error; 260 } 261 262 /* 263 * Is this unused entry either in the bestfree or smaller than all of 264 * them? We've already checked that the bestfrees are sorted longest to 265 * shortest, and that there aren't any bogus entries. 266 */ 267 STATIC void 268 xchk_directory_check_free_entry( 269 struct xfs_scrub *sc, 270 xfs_dablk_t lblk, 271 struct xfs_dir2_data_free *bf, 272 struct xfs_dir2_data_unused *dup) 273 { 274 struct xfs_dir2_data_free *dfp; 275 unsigned int dup_length; 276 277 dup_length = be16_to_cpu(dup->length); 278 279 /* Unused entry is shorter than any of the bestfrees */ 280 if (dup_length < be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length)) 281 return; 282 283 for (dfp = &bf[XFS_DIR2_DATA_FD_COUNT - 1]; dfp >= bf; dfp--) 284 if (dup_length == be16_to_cpu(dfp->length)) 285 return; 286 287 /* Unused entry should be in the bestfrees but wasn't found. */ 288 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 289 } 290 291 /* Check free space info in a directory data block. */ 292 STATIC int 293 xchk_directory_data_bestfree( 294 struct xfs_scrub *sc, 295 xfs_dablk_t lblk, 296 bool is_block) 297 { 298 struct xfs_dir2_data_unused *dup; 299 struct xfs_dir2_data_free *dfp; 300 struct xfs_buf *bp; 301 struct xfs_dir2_data_free *bf; 302 struct xfs_mount *mp = sc->mp; 303 u16 tag; 304 unsigned int nr_bestfrees = 0; 305 unsigned int nr_frees = 0; 306 unsigned int smallest_bestfree; 307 int newlen; 308 unsigned int offset; 309 unsigned int end; 310 int error; 311 312 if (is_block) { 313 /* dir block format */ 314 if (lblk != XFS_B_TO_FSBT(mp, XFS_DIR2_DATA_OFFSET)) 315 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 316 error = xfs_dir3_block_read(sc->tp, sc->ip, &bp); 317 } else { 318 /* dir data format */ 319 error = xfs_dir3_data_read(sc->tp, sc->ip, lblk, 0, &bp); 320 } 321 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error)) 322 goto out; 323 xchk_buffer_recheck(sc, bp); 324 325 /* XXX: Check xfs_dir3_data_hdr.pad is zero once we start setting it. */ 326 327 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 328 goto out_buf; 329 330 /* Do the bestfrees correspond to actual free space? */ 331 bf = xfs_dir2_data_bestfree_p(mp, bp->b_addr); 332 smallest_bestfree = UINT_MAX; 333 for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) { 334 offset = be16_to_cpu(dfp->offset); 335 if (offset == 0) 336 continue; 337 if (offset >= mp->m_dir_geo->blksize) { 338 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 339 goto out_buf; 340 } 341 dup = bp->b_addr + offset; 342 tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)); 343 344 /* bestfree doesn't match the entry it points at? */ 345 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG) || 346 be16_to_cpu(dup->length) != be16_to_cpu(dfp->length) || 347 tag != offset) { 348 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 349 goto out_buf; 350 } 351 352 /* bestfree records should be ordered largest to smallest */ 353 if (smallest_bestfree < be16_to_cpu(dfp->length)) { 354 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 355 goto out_buf; 356 } 357 358 smallest_bestfree = be16_to_cpu(dfp->length); 359 nr_bestfrees++; 360 } 361 362 /* Make sure the bestfrees are actually the best free spaces. */ 363 offset = mp->m_dir_geo->data_entry_offset; 364 end = xfs_dir3_data_end_offset(mp->m_dir_geo, bp->b_addr); 365 366 /* Iterate the entries, stopping when we hit or go past the end. */ 367 while (offset < end) { 368 dup = bp->b_addr + offset; 369 370 /* Skip real entries */ 371 if (dup->freetag != cpu_to_be16(XFS_DIR2_DATA_FREE_TAG)) { 372 struct xfs_dir2_data_entry *dep = bp->b_addr + offset; 373 374 newlen = xfs_dir2_data_entsize(mp, dep->namelen); 375 if (newlen <= 0) { 376 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 377 lblk); 378 goto out_buf; 379 } 380 offset += newlen; 381 continue; 382 } 383 384 /* Spot check this free entry */ 385 tag = be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)); 386 if (tag != offset) { 387 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 388 goto out_buf; 389 } 390 391 /* 392 * Either this entry is a bestfree or it's smaller than 393 * any of the bestfrees. 394 */ 395 xchk_directory_check_free_entry(sc, lblk, bf, dup); 396 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 397 goto out_buf; 398 399 /* Move on. */ 400 newlen = be16_to_cpu(dup->length); 401 if (newlen <= 0) { 402 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 403 goto out_buf; 404 } 405 offset += newlen; 406 if (offset <= end) 407 nr_frees++; 408 } 409 410 /* We're required to fill all the space. */ 411 if (offset != end) 412 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 413 414 /* Did we see at least as many free slots as there are bestfrees? */ 415 if (nr_frees < nr_bestfrees) 416 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 417 out_buf: 418 xfs_trans_brelse(sc->tp, bp); 419 out: 420 return error; 421 } 422 423 /* 424 * Does the free space length in the free space index block ($len) match 425 * the longest length in the directory data block's bestfree array? 426 * Assume that we've already checked that the data block's bestfree 427 * array is in order. 428 */ 429 STATIC void 430 xchk_directory_check_freesp( 431 struct xfs_scrub *sc, 432 xfs_dablk_t lblk, 433 struct xfs_buf *dbp, 434 unsigned int len) 435 { 436 struct xfs_dir2_data_free *dfp; 437 438 dfp = xfs_dir2_data_bestfree_p(sc->mp, dbp->b_addr); 439 440 if (len != be16_to_cpu(dfp->length)) 441 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 442 443 if (len > 0 && be16_to_cpu(dfp->offset) == 0) 444 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 445 } 446 447 /* Check free space info in a directory leaf1 block. */ 448 STATIC int 449 xchk_directory_leaf1_bestfree( 450 struct xfs_scrub *sc, 451 struct xfs_da_args *args, 452 xfs_dir2_db_t last_data_db, 453 xfs_dablk_t lblk) 454 { 455 struct xfs_dir3_icleaf_hdr leafhdr; 456 struct xfs_dir2_leaf_tail *ltp; 457 struct xfs_dir2_leaf *leaf; 458 struct xfs_buf *dbp; 459 struct xfs_buf *bp; 460 struct xfs_da_geometry *geo = sc->mp->m_dir_geo; 461 __be16 *bestp; 462 __u16 best; 463 __u32 hash; 464 __u32 lasthash = 0; 465 __u32 bestcount; 466 unsigned int stale = 0; 467 int i; 468 int error; 469 470 /* Read the free space block. */ 471 error = xfs_dir3_leaf_read(sc->tp, sc->ip, lblk, &bp); 472 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error)) 473 return error; 474 xchk_buffer_recheck(sc, bp); 475 476 leaf = bp->b_addr; 477 xfs_dir2_leaf_hdr_from_disk(sc->ip->i_mount, &leafhdr, leaf); 478 ltp = xfs_dir2_leaf_tail_p(geo, leaf); 479 bestcount = be32_to_cpu(ltp->bestcount); 480 bestp = xfs_dir2_leaf_bests_p(ltp); 481 482 if (xfs_has_crc(sc->mp)) { 483 struct xfs_dir3_leaf_hdr *hdr3 = bp->b_addr; 484 485 if (hdr3->pad != cpu_to_be32(0)) 486 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 487 } 488 489 /* 490 * There must be enough bestfree slots to cover all the directory data 491 * blocks that we scanned. It is possible for there to be a hole 492 * between the last data block and i_disk_size. This seems like an 493 * oversight to the scrub author, but as we have been writing out 494 * directories like this (and xfs_repair doesn't mind them) for years, 495 * that's what we have to check. 496 */ 497 if (bestcount != last_data_db + 1) { 498 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 499 goto out; 500 } 501 502 /* Is the leaf count even remotely sane? */ 503 if (leafhdr.count > geo->leaf_max_ents) { 504 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 505 goto out; 506 } 507 508 /* Leaves and bests don't overlap in leaf format. */ 509 if ((char *)&leafhdr.ents[leafhdr.count] > (char *)bestp) { 510 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 511 goto out; 512 } 513 514 /* Check hash value order, count stale entries. */ 515 for (i = 0; i < leafhdr.count; i++) { 516 hash = be32_to_cpu(leafhdr.ents[i].hashval); 517 if (i > 0 && lasthash > hash) 518 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 519 lasthash = hash; 520 if (leafhdr.ents[i].address == 521 cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) 522 stale++; 523 } 524 if (leafhdr.stale != stale) 525 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 526 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 527 goto out; 528 529 /* Check all the bestfree entries. */ 530 for (i = 0; i < bestcount; i++, bestp++) { 531 best = be16_to_cpu(*bestp); 532 error = xfs_dir3_data_read(sc->tp, sc->ip, 533 xfs_dir2_db_to_da(args->geo, i), 534 XFS_DABUF_MAP_HOLE_OK, 535 &dbp); 536 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, 537 &error)) 538 break; 539 540 if (!dbp) { 541 if (best != NULLDATAOFF) { 542 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 543 lblk); 544 break; 545 } 546 continue; 547 } 548 549 if (best == NULLDATAOFF) 550 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 551 else 552 xchk_directory_check_freesp(sc, lblk, dbp, best); 553 xfs_trans_brelse(sc->tp, dbp); 554 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 555 break; 556 } 557 out: 558 xfs_trans_brelse(sc->tp, bp); 559 return error; 560 } 561 562 /* Check free space info in a directory freespace block. */ 563 STATIC int 564 xchk_directory_free_bestfree( 565 struct xfs_scrub *sc, 566 struct xfs_da_args *args, 567 xfs_dablk_t lblk) 568 { 569 struct xfs_dir3_icfree_hdr freehdr; 570 struct xfs_buf *dbp; 571 struct xfs_buf *bp; 572 __u16 best; 573 unsigned int stale = 0; 574 int i; 575 int error; 576 577 /* Read the free space block */ 578 error = xfs_dir2_free_read(sc->tp, sc->ip, lblk, &bp); 579 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error)) 580 return error; 581 xchk_buffer_recheck(sc, bp); 582 583 if (xfs_has_crc(sc->mp)) { 584 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; 585 586 if (hdr3->pad != cpu_to_be32(0)) 587 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 588 } 589 590 /* Check all the entries. */ 591 xfs_dir2_free_hdr_from_disk(sc->ip->i_mount, &freehdr, bp->b_addr); 592 for (i = 0; i < freehdr.nvalid; i++) { 593 best = be16_to_cpu(freehdr.bests[i]); 594 if (best == NULLDATAOFF) { 595 stale++; 596 continue; 597 } 598 error = xfs_dir3_data_read(sc->tp, sc->ip, 599 (freehdr.firstdb + i) * args->geo->fsbcount, 600 0, &dbp); 601 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, 602 &error)) 603 goto out; 604 xchk_directory_check_freesp(sc, lblk, dbp, best); 605 xfs_trans_brelse(sc->tp, dbp); 606 } 607 608 if (freehdr.nused + stale != freehdr.nvalid) 609 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 610 out: 611 xfs_trans_brelse(sc->tp, bp); 612 return error; 613 } 614 615 /* Check free space information in directories. */ 616 STATIC int 617 xchk_directory_blocks( 618 struct xfs_scrub *sc) 619 { 620 struct xfs_bmbt_irec got; 621 struct xfs_da_args args = { 622 .dp = sc ->ip, 623 .whichfork = XFS_DATA_FORK, 624 .geo = sc->mp->m_dir_geo, 625 .trans = sc->tp, 626 }; 627 struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK); 628 struct xfs_mount *mp = sc->mp; 629 xfs_fileoff_t leaf_lblk; 630 xfs_fileoff_t free_lblk; 631 xfs_fileoff_t lblk; 632 struct xfs_iext_cursor icur; 633 xfs_dablk_t dabno; 634 xfs_dir2_db_t last_data_db = 0; 635 bool found; 636 bool is_block = false; 637 int error; 638 639 /* Ignore local format directories. */ 640 if (ifp->if_format != XFS_DINODE_FMT_EXTENTS && 641 ifp->if_format != XFS_DINODE_FMT_BTREE) 642 return 0; 643 644 lblk = XFS_B_TO_FSB(mp, XFS_DIR2_DATA_OFFSET); 645 leaf_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_LEAF_OFFSET); 646 free_lblk = XFS_B_TO_FSB(mp, XFS_DIR2_FREE_OFFSET); 647 648 /* Is this a block dir? */ 649 error = xfs_dir2_isblock(&args, &is_block); 650 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, lblk, &error)) 651 goto out; 652 653 /* Iterate all the data extents in the directory... */ 654 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); 655 while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) { 656 /* No more data blocks... */ 657 if (got.br_startoff >= leaf_lblk) 658 break; 659 660 /* 661 * Check each data block's bestfree data. 662 * 663 * Iterate all the fsbcount-aligned block offsets in 664 * this directory. The directory block reading code is 665 * smart enough to do its own bmap lookups to handle 666 * discontiguous directory blocks. When we're done 667 * with the extent record, re-query the bmap at the 668 * next fsbcount-aligned offset to avoid redundant 669 * block checks. 670 */ 671 for (lblk = roundup((xfs_dablk_t)got.br_startoff, 672 args.geo->fsbcount); 673 lblk < got.br_startoff + got.br_blockcount; 674 lblk += args.geo->fsbcount) { 675 last_data_db = xfs_dir2_da_to_db(args.geo, lblk); 676 error = xchk_directory_data_bestfree(sc, lblk, 677 is_block); 678 if (error) 679 goto out; 680 } 681 dabno = got.br_startoff + got.br_blockcount; 682 lblk = roundup(dabno, args.geo->fsbcount); 683 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); 684 } 685 686 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 687 goto out; 688 689 /* Look for a leaf1 block, which has free info. */ 690 if (xfs_iext_lookup_extent(sc->ip, ifp, leaf_lblk, &icur, &got) && 691 got.br_startoff == leaf_lblk && 692 got.br_blockcount == args.geo->fsbcount && 693 !xfs_iext_next_extent(ifp, &icur, &got)) { 694 if (is_block) { 695 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 696 goto out; 697 } 698 error = xchk_directory_leaf1_bestfree(sc, &args, last_data_db, 699 leaf_lblk); 700 if (error) 701 goto out; 702 } 703 704 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 705 goto out; 706 707 /* Scan for free blocks */ 708 lblk = free_lblk; 709 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); 710 while (found && !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) { 711 /* 712 * Dirs can't have blocks mapped above 2^32. 713 * Single-block dirs shouldn't even be here. 714 */ 715 lblk = got.br_startoff; 716 if (lblk & ~0xFFFFFFFFULL) { 717 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 718 goto out; 719 } 720 if (is_block) { 721 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, lblk); 722 goto out; 723 } 724 725 /* 726 * Check each dir free block's bestfree data. 727 * 728 * Iterate all the fsbcount-aligned block offsets in 729 * this directory. The directory block reading code is 730 * smart enough to do its own bmap lookups to handle 731 * discontiguous directory blocks. When we're done 732 * with the extent record, re-query the bmap at the 733 * next fsbcount-aligned offset to avoid redundant 734 * block checks. 735 */ 736 for (lblk = roundup((xfs_dablk_t)got.br_startoff, 737 args.geo->fsbcount); 738 lblk < got.br_startoff + got.br_blockcount; 739 lblk += args.geo->fsbcount) { 740 error = xchk_directory_free_bestfree(sc, &args, 741 lblk); 742 if (error) 743 goto out; 744 } 745 dabno = got.br_startoff + got.br_blockcount; 746 lblk = roundup(dabno, args.geo->fsbcount); 747 found = xfs_iext_lookup_extent(sc->ip, ifp, lblk, &icur, &got); 748 } 749 out: 750 return error; 751 } 752 753 /* Scrub a whole directory. */ 754 int 755 xchk_directory( 756 struct xfs_scrub *sc) 757 { 758 int error; 759 760 if (!S_ISDIR(VFS_I(sc->ip)->i_mode)) 761 return -ENOENT; 762 763 /* Plausible size? */ 764 if (sc->ip->i_disk_size < xfs_dir2_sf_hdr_size(0)) { 765 xchk_ino_set_corrupt(sc, sc->ip->i_ino); 766 return 0; 767 } 768 769 /* Check directory tree structure */ 770 error = xchk_da_btree(sc, XFS_DATA_FORK, xchk_dir_rec, NULL); 771 if (error) 772 return error; 773 774 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 775 return 0; 776 777 /* Check the freespace. */ 778 error = xchk_directory_blocks(sc); 779 if (error) 780 return error; 781 782 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT) 783 return 0; 784 785 /* Look up every name in this directory by hash. */ 786 error = xchk_dir_walk(sc, sc->ip, xchk_dir_actor, NULL); 787 if (error == -ECANCELED) 788 error = 0; 789 return error; 790 } 791