1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2023-2024 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_trans_space.h" 12 #include "xfs_mount.h" 13 #include "xfs_log_format.h" 14 #include "xfs_trans.h" 15 #include "xfs_inode.h" 16 #include "xfs_icache.h" 17 #include "xfs_dir2.h" 18 #include "xfs_dir2_priv.h" 19 #include "xfs_attr.h" 20 #include "xfs_parent.h" 21 #include "scrub/scrub.h" 22 #include "scrub/common.h" 23 #include "scrub/bitmap.h" 24 #include "scrub/ino_bitmap.h" 25 #include "scrub/xfile.h" 26 #include "scrub/xfarray.h" 27 #include "scrub/xfblob.h" 28 #include "scrub/listxattr.h" 29 #include "scrub/trace.h" 30 #include "scrub/repair.h" 31 #include "scrub/orphanage.h" 32 #include "scrub/dirtree.h" 33 #include "scrub/readdir.h" 34 35 /* 36 * Directory Tree Structure Repairs 37 * ================================ 38 * 39 * If we decide that the directory being scanned is participating in a 40 * directory loop, the only change we can make is to remove directory entries 41 * pointing down to @sc->ip. If that leaves it with no parents, the directory 42 * should be adopted by the orphanage. 43 */ 44 45 /* Set up to repair directory loops. */ 46 int 47 xrep_setup_dirtree( 48 struct xfs_scrub *sc) 49 { 50 return xrep_orphanage_try_create(sc); 51 } 52 53 /* Change the outcome of this path. */ 54 static inline void 55 xrep_dirpath_set_outcome( 56 struct xchk_dirtree *dl, 57 struct xchk_dirpath *path, 58 enum xchk_dirpath_outcome outcome) 59 { 60 trace_xrep_dirpath_set_outcome(dl->sc, path->path_nr, path->nr_steps, 61 outcome); 62 63 path->outcome = outcome; 64 } 65 66 /* Delete all paths. */ 67 STATIC void 68 xrep_dirtree_delete_all_paths( 69 struct xchk_dirtree *dl, 70 struct xchk_dirtree_outcomes *oc) 71 { 72 struct xchk_dirpath *path; 73 74 xchk_dirtree_for_each_path(dl, path) { 75 switch (path->outcome) { 76 case XCHK_DIRPATH_CORRUPT: 77 case XCHK_DIRPATH_LOOP: 78 oc->suspect--; 79 oc->bad++; 80 xrep_dirpath_set_outcome(dl, path, XCHK_DIRPATH_DELETE); 81 break; 82 case XCHK_DIRPATH_OK: 83 oc->good--; 84 oc->bad++; 85 xrep_dirpath_set_outcome(dl, path, XCHK_DIRPATH_DELETE); 86 break; 87 default: 88 break; 89 } 90 } 91 92 ASSERT(oc->suspect == 0); 93 ASSERT(oc->good == 0); 94 } 95 96 /* Since this is the surviving path, set the dotdot entry to this value. */ 97 STATIC void 98 xrep_dirpath_retain_parent( 99 struct xchk_dirtree *dl, 100 struct xchk_dirpath *path) 101 { 102 struct xchk_dirpath_step step; 103 int error; 104 105 error = xfarray_load(dl->path_steps, path->first_step, &step); 106 if (error) 107 return; 108 109 dl->parent_ino = be64_to_cpu(step.pptr_rec.p_ino); 110 } 111 112 /* Find the one surviving path so we know how to set dotdot. */ 113 STATIC void 114 xrep_dirtree_find_surviving_path( 115 struct xchk_dirtree *dl, 116 struct xchk_dirtree_outcomes *oc) 117 { 118 struct xchk_dirpath *path; 119 bool foundit = false; 120 121 xchk_dirtree_for_each_path(dl, path) { 122 switch (path->outcome) { 123 case XCHK_DIRPATH_CORRUPT: 124 case XCHK_DIRPATH_LOOP: 125 case XCHK_DIRPATH_OK: 126 if (!foundit) { 127 xrep_dirpath_retain_parent(dl, path); 128 foundit = true; 129 continue; 130 } 131 ASSERT(foundit == false); 132 break; 133 default: 134 break; 135 } 136 } 137 138 ASSERT(oc->suspect + oc->good == 1); 139 } 140 141 /* Delete all paths except for the one good one. */ 142 STATIC void 143 xrep_dirtree_keep_one_good_path( 144 struct xchk_dirtree *dl, 145 struct xchk_dirtree_outcomes *oc) 146 { 147 struct xchk_dirpath *path; 148 bool foundit = false; 149 150 xchk_dirtree_for_each_path(dl, path) { 151 switch (path->outcome) { 152 case XCHK_DIRPATH_CORRUPT: 153 case XCHK_DIRPATH_LOOP: 154 oc->suspect--; 155 oc->bad++; 156 xrep_dirpath_set_outcome(dl, path, XCHK_DIRPATH_DELETE); 157 break; 158 case XCHK_DIRPATH_OK: 159 if (!foundit) { 160 xrep_dirpath_retain_parent(dl, path); 161 foundit = true; 162 continue; 163 } 164 oc->good--; 165 oc->bad++; 166 xrep_dirpath_set_outcome(dl, path, XCHK_DIRPATH_DELETE); 167 break; 168 default: 169 break; 170 } 171 } 172 173 ASSERT(oc->suspect == 0); 174 ASSERT(oc->good < 2); 175 } 176 177 /* Delete all paths except for one suspect one. */ 178 STATIC void 179 xrep_dirtree_keep_one_suspect_path( 180 struct xchk_dirtree *dl, 181 struct xchk_dirtree_outcomes *oc) 182 { 183 struct xchk_dirpath *path; 184 bool foundit = false; 185 186 xchk_dirtree_for_each_path(dl, path) { 187 switch (path->outcome) { 188 case XCHK_DIRPATH_CORRUPT: 189 case XCHK_DIRPATH_LOOP: 190 if (!foundit) { 191 xrep_dirpath_retain_parent(dl, path); 192 foundit = true; 193 continue; 194 } 195 oc->suspect--; 196 oc->bad++; 197 xrep_dirpath_set_outcome(dl, path, XCHK_DIRPATH_DELETE); 198 break; 199 case XCHK_DIRPATH_OK: 200 ASSERT(0); 201 break; 202 default: 203 break; 204 } 205 } 206 207 ASSERT(oc->suspect == 1); 208 ASSERT(oc->good == 0); 209 } 210 211 /* 212 * Figure out what to do with the paths we tried to find. Returns -EDEADLOCK 213 * if the scan results have become stale. 214 */ 215 STATIC void 216 xrep_dirtree_decide_fate( 217 struct xchk_dirtree *dl, 218 struct xchk_dirtree_outcomes *oc) 219 { 220 xchk_dirtree_evaluate(dl, oc); 221 222 /* Parentless directories should not have any paths at all. */ 223 if (xchk_dirtree_parentless(dl)) { 224 xrep_dirtree_delete_all_paths(dl, oc); 225 return; 226 } 227 228 /* One path is exactly the number of paths we want. */ 229 if (oc->good + oc->suspect == 1) { 230 xrep_dirtree_find_surviving_path(dl, oc); 231 return; 232 } 233 234 /* Zero paths means we should reattach the subdir to the orphanage. */ 235 if (oc->good + oc->suspect == 0) { 236 if (dl->sc->orphanage) 237 oc->needs_adoption = true; 238 return; 239 } 240 241 /* 242 * Otherwise, this subdirectory has too many parents. If there's at 243 * least one good path, keep it and delete the others. 244 */ 245 if (oc->good > 0) { 246 xrep_dirtree_keep_one_good_path(dl, oc); 247 return; 248 } 249 250 /* 251 * There are no good paths and there are too many suspect paths. 252 * Keep the first suspect path and delete the rest. 253 */ 254 xrep_dirtree_keep_one_suspect_path(dl, oc); 255 } 256 257 /* 258 * Load the first step of this path into @step and @dl->xname/pptr 259 * for later repair work. 260 */ 261 STATIC int 262 xrep_dirtree_prep_path( 263 struct xchk_dirtree *dl, 264 struct xchk_dirpath *path, 265 struct xchk_dirpath_step *step) 266 { 267 int error; 268 269 error = xfarray_load(dl->path_steps, path->first_step, step); 270 if (error) 271 return error; 272 273 error = xfblob_loadname(dl->path_names, step->name_cookie, &dl->xname, 274 step->name_len); 275 if (error) 276 return error; 277 278 dl->pptr_rec = step->pptr_rec; /* struct copy */ 279 return 0; 280 } 281 282 /* Delete the VFS dentry for a removed child. */ 283 STATIC int 284 xrep_dirtree_purge_dentry( 285 struct xchk_dirtree *dl, 286 struct xfs_inode *dp, 287 const struct xfs_name *name) 288 { 289 struct qstr qname = QSTR_INIT(name->name, name->len); 290 struct dentry *parent_dentry, *child_dentry; 291 int error = 0; 292 293 /* 294 * Find the dentry for the parent directory. If there isn't one, we're 295 * done. Caller already holds i_rwsem for parent and child. 296 */ 297 parent_dentry = d_find_alias(VFS_I(dp)); 298 if (!parent_dentry) 299 return 0; 300 301 /* The VFS thinks the parent is a directory, right? */ 302 if (!d_is_dir(parent_dentry)) { 303 ASSERT(d_is_dir(parent_dentry)); 304 error = -EFSCORRUPTED; 305 goto out_dput_parent; 306 } 307 308 /* 309 * Try to find the dirent pointing to the child. If there isn't one, 310 * we're done. 311 */ 312 qname.hash = full_name_hash(parent_dentry, name->name, name->len); 313 child_dentry = d_lookup(parent_dentry, &qname); 314 if (!child_dentry) { 315 error = 0; 316 goto out_dput_parent; 317 } 318 319 trace_xrep_dirtree_delete_child(dp->i_mount, child_dentry); 320 321 /* Child is not a directory? We're screwed. */ 322 if (!d_is_dir(child_dentry)) { 323 ASSERT(d_is_dir(child_dentry)); 324 error = -EFSCORRUPTED; 325 goto out_dput_child; 326 } 327 328 /* Replace the child dentry with a negative one. */ 329 d_delete(child_dentry); 330 331 out_dput_child: 332 dput(child_dentry); 333 out_dput_parent: 334 dput(parent_dentry); 335 return error; 336 } 337 338 /* 339 * Prepare to delete a link by taking the IOLOCK of the parent and the child 340 * (scrub target). Caller must hold IOLOCK_EXCL on @sc->ip. Returns 0 if we 341 * took both locks, or a negative errno if we couldn't lock the parent in time. 342 */ 343 static inline int 344 xrep_dirtree_unlink_iolock( 345 struct xfs_scrub *sc, 346 struct xfs_inode *dp) 347 { 348 int error; 349 350 ASSERT(sc->ilock_flags & XFS_IOLOCK_EXCL); 351 352 if (xfs_ilock_nowait(dp, XFS_IOLOCK_EXCL)) 353 return 0; 354 355 xchk_iunlock(sc, XFS_IOLOCK_EXCL); 356 do { 357 xfs_ilock(dp, XFS_IOLOCK_EXCL); 358 if (xchk_ilock_nowait(sc, XFS_IOLOCK_EXCL)) 359 break; 360 xfs_iunlock(dp, XFS_IOLOCK_EXCL); 361 362 if (xchk_should_terminate(sc, &error)) { 363 xchk_ilock(sc, XFS_IOLOCK_EXCL); 364 return error; 365 } 366 367 delay(1); 368 } while (1); 369 370 return 0; 371 } 372 373 /* 374 * Remove a link from the directory tree and update the dcache. Returns 375 * -ESTALE if the scan data are now out of date. 376 */ 377 STATIC int 378 xrep_dirtree_unlink( 379 struct xchk_dirtree *dl, 380 struct xfs_inode *dp, 381 struct xchk_dirpath *path, 382 struct xchk_dirpath_step *step) 383 { 384 struct xfs_scrub *sc = dl->sc; 385 struct xfs_mount *mp = sc->mp; 386 xfs_ino_t dotdot_ino; 387 xfs_ino_t parent_ino = dl->parent_ino; 388 unsigned int resblks; 389 int dontcare; 390 int error; 391 392 /* Take IOLOCK_EXCL of the parent and child. */ 393 error = xrep_dirtree_unlink_iolock(sc, dp); 394 if (error) 395 return error; 396 397 /* 398 * Create the transaction that we need to sever the path. Ignore 399 * EDQUOT and ENOSPC being returned via nospace_error because the 400 * directory code can handle a reservationless update. 401 */ 402 resblks = xfs_remove_space_res(mp, step->name_len); 403 error = xfs_trans_alloc_dir(dp, &M_RES(mp)->tr_remove, sc->ip, 404 &resblks, &sc->tp, &dontcare); 405 if (error) 406 goto out_iolock; 407 408 /* 409 * Cancel if someone invalidate the paths while we were trying to get 410 * the ILOCK. 411 */ 412 mutex_lock(&dl->lock); 413 if (dl->stale) { 414 mutex_unlock(&dl->lock); 415 error = -ESTALE; 416 goto out_trans_cancel; 417 } 418 xrep_dirpath_set_outcome(dl, path, XREP_DIRPATH_DELETING); 419 mutex_unlock(&dl->lock); 420 421 trace_xrep_dirtree_delete_path(dl->sc, sc->ip, path->path_nr, 422 &dl->xname, &dl->pptr_rec); 423 424 /* 425 * Decide if we need to reset the dotdot entry. Rules: 426 * 427 * - If there's a surviving parent, we want dotdot to point there. 428 * - If we don't have any surviving parents, then point dotdot at the 429 * root dir. 430 * - If dotdot is already set to the value we want, pass in NULLFSINO 431 * for no change necessary. 432 * 433 * Do this /before/ we dirty anything, in case the dotdot lookup 434 * fails. 435 */ 436 error = xchk_dir_lookup(sc, sc->ip, &xfs_name_dotdot, &dotdot_ino); 437 if (error) 438 goto out_trans_cancel; 439 if (parent_ino == NULLFSINO) 440 parent_ino = dl->root_ino; 441 if (dotdot_ino == parent_ino) 442 parent_ino = NULLFSINO; 443 444 /* Drop the link from sc->ip's dotdot entry. */ 445 error = xfs_droplink(sc->tp, dp); 446 if (error) 447 goto out_trans_cancel; 448 449 /* Reset the dotdot entry to a surviving parent. */ 450 if (parent_ino != NULLFSINO) { 451 error = xfs_dir_replace(sc->tp, sc->ip, &xfs_name_dotdot, 452 parent_ino, 0); 453 if (error) 454 goto out_trans_cancel; 455 } 456 457 /* Drop the link from dp to sc->ip. */ 458 error = xfs_droplink(sc->tp, sc->ip); 459 if (error) 460 goto out_trans_cancel; 461 462 error = xfs_dir_removename(sc->tp, dp, &dl->xname, sc->ip->i_ino, 463 resblks); 464 if (error) { 465 ASSERT(error != -ENOENT); 466 goto out_trans_cancel; 467 } 468 469 if (xfs_has_parent(sc->mp)) { 470 error = xfs_parent_removename(sc->tp, &dl->ppargs, dp, 471 &dl->xname, sc->ip); 472 if (error) 473 goto out_trans_cancel; 474 } 475 476 /* 477 * Notify dirent hooks that we removed the bad link, invalidate the 478 * dcache, and commit the repair. 479 */ 480 xfs_dir_update_hook(dp, sc->ip, -1, &dl->xname); 481 error = xrep_dirtree_purge_dentry(dl, dp, &dl->xname); 482 if (error) 483 goto out_trans_cancel; 484 485 error = xrep_trans_commit(sc); 486 goto out_ilock; 487 488 out_trans_cancel: 489 xchk_trans_cancel(sc); 490 out_ilock: 491 xfs_iunlock(sc->ip, XFS_ILOCK_EXCL); 492 xfs_iunlock(dp, XFS_ILOCK_EXCL); 493 out_iolock: 494 xfs_iunlock(dp, XFS_IOLOCK_EXCL); 495 return error; 496 } 497 498 /* 499 * Delete a directory entry that points to this directory. Returns -ESTALE 500 * if the scan data are now out of date. 501 */ 502 STATIC int 503 xrep_dirtree_delete_path( 504 struct xchk_dirtree *dl, 505 struct xchk_dirpath *path) 506 { 507 struct xchk_dirpath_step step; 508 struct xfs_scrub *sc = dl->sc; 509 struct xfs_inode *dp; 510 int error; 511 512 /* 513 * Load the parent pointer and directory inode for this path, then 514 * drop the scan lock, the ILOCK, and the transaction so that 515 * _delete_path can reserve the proper transaction. This sets up 516 * @dl->xname for the deletion. 517 */ 518 error = xrep_dirtree_prep_path(dl, path, &step); 519 if (error) 520 return error; 521 522 error = xchk_iget(sc, be64_to_cpu(step.pptr_rec.p_ino), &dp); 523 if (error) 524 return error; 525 526 mutex_unlock(&dl->lock); 527 xchk_trans_cancel(sc); 528 xchk_iunlock(sc, XFS_ILOCK_EXCL); 529 530 /* Delete the directory link and release the parent. */ 531 error = xrep_dirtree_unlink(dl, dp, path, &step); 532 xchk_irele(sc, dp); 533 534 /* 535 * Retake all the resources we had at the beginning even if the repair 536 * failed or the scan data are now stale. This keeps things simple for 537 * the caller. 538 */ 539 xchk_trans_alloc_empty(sc); 540 xchk_ilock(sc, XFS_ILOCK_EXCL); 541 mutex_lock(&dl->lock); 542 543 if (!error && dl->stale) 544 error = -ESTALE; 545 return error; 546 } 547 548 /* Add a new path to represent our in-progress adoption. */ 549 STATIC int 550 xrep_dirtree_create_adoption_path( 551 struct xchk_dirtree *dl) 552 { 553 struct xfs_scrub *sc = dl->sc; 554 struct xchk_dirpath *path; 555 int error; 556 557 /* 558 * We should have capped the number of paths at XFS_MAXLINK-1 in the 559 * scanner. 560 */ 561 if (dl->nr_paths > XFS_MAXLINK) { 562 ASSERT(dl->nr_paths <= XFS_MAXLINK); 563 return -EFSCORRUPTED; 564 } 565 566 /* 567 * Create a new xchk_path structure to remember this parent pointer 568 * and record the first name step. 569 */ 570 path = kmalloc(sizeof(struct xchk_dirpath), XCHK_GFP_FLAGS); 571 if (!path) 572 return -ENOMEM; 573 574 INIT_LIST_HEAD(&path->list); 575 xino_bitmap_init(&path->seen_inodes); 576 path->nr_steps = 0; 577 path->outcome = XREP_DIRPATH_ADOPTING; 578 579 /* 580 * Record the new link that we just created in the orphanage. Because 581 * adoption is the last repair that we perform, we don't bother filling 582 * in the path all the way back to the root. 583 */ 584 xfs_inode_to_parent_rec(&dl->pptr_rec, sc->orphanage); 585 586 error = xino_bitmap_set(&path->seen_inodes, sc->orphanage->i_ino); 587 if (error) 588 goto out_path; 589 590 trace_xrep_dirtree_create_adoption(sc, sc->ip, dl->nr_paths, 591 &dl->xname, &dl->pptr_rec); 592 593 error = xchk_dirpath_append(dl, sc->ip, path, &dl->xname, 594 &dl->pptr_rec); 595 if (error) 596 goto out_path; 597 598 path->first_step = xfarray_length(dl->path_steps) - 1; 599 path->second_step = XFARRAY_NULLIDX; 600 path->path_nr = dl->nr_paths; 601 602 list_add_tail(&path->list, &dl->path_list); 603 dl->nr_paths++; 604 return 0; 605 606 out_path: 607 kfree(path); 608 return error; 609 } 610 611 /* 612 * Prepare to move a file to the orphanage by taking the IOLOCK of the 613 * orphanage and the child (scrub target). Caller must hold IOLOCK_EXCL on 614 * @sc->ip. Returns 0 if we took both locks, or a negative errno if we 615 * couldn't lock the orphanage in time. 616 */ 617 static inline int 618 xrep_dirtree_adopt_iolock( 619 struct xfs_scrub *sc) 620 { 621 int error; 622 623 ASSERT(sc->ilock_flags & XFS_IOLOCK_EXCL); 624 625 if (xrep_orphanage_ilock_nowait(sc, XFS_IOLOCK_EXCL)) 626 return 0; 627 628 xchk_iunlock(sc, XFS_IOLOCK_EXCL); 629 do { 630 xrep_orphanage_ilock(sc, XFS_IOLOCK_EXCL); 631 if (xchk_ilock_nowait(sc, XFS_IOLOCK_EXCL)) 632 break; 633 xrep_orphanage_iunlock(sc, XFS_IOLOCK_EXCL); 634 635 if (xchk_should_terminate(sc, &error)) { 636 xchk_ilock(sc, XFS_IOLOCK_EXCL); 637 return error; 638 } 639 640 delay(1); 641 } while (1); 642 643 return 0; 644 } 645 646 /* 647 * Reattach this orphaned directory to the orphanage. Do not call this with 648 * any resources held. Returns -ESTALE if the scan data have become out of 649 * date. 650 */ 651 STATIC int 652 xrep_dirtree_adopt( 653 struct xchk_dirtree *dl) 654 { 655 struct xfs_scrub *sc = dl->sc; 656 int error; 657 658 /* Take the IOLOCK of the orphanage and the scrub target. */ 659 error = xrep_dirtree_adopt_iolock(sc); 660 if (error) 661 return error; 662 663 /* 664 * Set up for an adoption. The directory tree fixer runs after the 665 * link counts have been corrected. Therefore, we must bump the 666 * child's link count since there will be no further opportunity to fix 667 * errors. 668 */ 669 error = xrep_adoption_trans_alloc(sc, &dl->adoption); 670 if (error) 671 goto out_iolock; 672 dl->adoption.bump_child_nlink = true; 673 674 /* Figure out what name we're going to use here. */ 675 error = xrep_adoption_compute_name(&dl->adoption, &dl->xname); 676 if (error) 677 goto out_trans; 678 679 /* 680 * Now that we have a proposed name for the orphanage entry, create 681 * a faux path so that the live update hook will see it. 682 */ 683 mutex_lock(&dl->lock); 684 if (dl->stale) { 685 mutex_unlock(&dl->lock); 686 error = -ESTALE; 687 goto out_trans; 688 } 689 error = xrep_dirtree_create_adoption_path(dl); 690 mutex_unlock(&dl->lock); 691 if (error) 692 goto out_trans; 693 694 /* Reparent the directory. */ 695 error = xrep_adoption_move(&dl->adoption); 696 if (error) 697 goto out_trans; 698 699 /* 700 * Commit the name and release all inode locks except for the scrub 701 * target's IOLOCK. 702 */ 703 error = xrep_trans_commit(sc); 704 goto out_ilock; 705 706 out_trans: 707 xchk_trans_cancel(sc); 708 out_ilock: 709 xchk_iunlock(sc, XFS_ILOCK_EXCL); 710 xrep_orphanage_iunlock(sc, XFS_ILOCK_EXCL); 711 out_iolock: 712 xrep_orphanage_iunlock(sc, XFS_IOLOCK_EXCL); 713 return error; 714 } 715 716 /* 717 * This newly orphaned directory needs to be adopted by the orphanage. 718 * Make this happen. 719 */ 720 STATIC int 721 xrep_dirtree_move_to_orphanage( 722 struct xchk_dirtree *dl) 723 { 724 struct xfs_scrub *sc = dl->sc; 725 int error; 726 727 /* 728 * Start by dropping all the resources that we hold so that we can grab 729 * all the resources that we need for the adoption. 730 */ 731 mutex_unlock(&dl->lock); 732 xchk_trans_cancel(sc); 733 xchk_iunlock(sc, XFS_ILOCK_EXCL); 734 735 /* Perform the adoption. */ 736 error = xrep_dirtree_adopt(dl); 737 738 /* 739 * Retake all the resources we had at the beginning even if the repair 740 * failed or the scan data are now stale. This keeps things simple for 741 * the caller. 742 */ 743 xchk_trans_alloc_empty(sc); 744 xchk_ilock(sc, XFS_ILOCK_EXCL); 745 mutex_lock(&dl->lock); 746 747 if (!error && dl->stale) 748 error = -ESTALE; 749 return error; 750 } 751 752 /* 753 * Try to fix all the problems. Returns -ESTALE if the scan data have become 754 * out of date. 755 */ 756 STATIC int 757 xrep_dirtree_fix_problems( 758 struct xchk_dirtree *dl, 759 struct xchk_dirtree_outcomes *oc) 760 { 761 struct xchk_dirpath *path; 762 int error; 763 764 /* Delete all the paths we don't want. */ 765 xchk_dirtree_for_each_path(dl, path) { 766 if (path->outcome != XCHK_DIRPATH_DELETE) 767 continue; 768 769 error = xrep_dirtree_delete_path(dl, path); 770 if (error) 771 return error; 772 } 773 774 /* Reparent this directory to the orphanage. */ 775 if (oc->needs_adoption) { 776 if (xrep_orphanage_can_adopt(dl->sc)) 777 return xrep_dirtree_move_to_orphanage(dl); 778 return -EFSCORRUPTED; 779 } 780 781 return 0; 782 } 783 784 /* Fix directory loops involving this directory. */ 785 int 786 xrep_dirtree( 787 struct xfs_scrub *sc) 788 { 789 struct xchk_dirtree *dl = sc->buf; 790 struct xchk_dirtree_outcomes oc; 791 int error; 792 793 /* 794 * Prepare to fix the directory tree by retaking the scan lock. The 795 * order of resource acquisition is still IOLOCK -> transaction -> 796 * ILOCK -> scan lock. 797 */ 798 mutex_lock(&dl->lock); 799 do { 800 /* 801 * Decide what we're going to do, then do it. An -ESTALE 802 * return here means the scan results are invalid and we have 803 * to walk again. 804 */ 805 if (!dl->stale) { 806 xrep_dirtree_decide_fate(dl, &oc); 807 808 trace_xrep_dirtree_decided_fate(dl, &oc); 809 810 error = xrep_dirtree_fix_problems(dl, &oc); 811 if (!error || error != -ESTALE) 812 break; 813 } 814 error = xchk_dirtree_find_paths_to_root(dl); 815 if (error == -ELNRNG || error == -ENOSR) 816 error = -EFSCORRUPTED; 817 } while (!error); 818 mutex_unlock(&dl->lock); 819 820 return error; 821 } 822
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.