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
xrep_setup_dirtree(struct xfs_scrub * sc)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
xrep_dirpath_set_outcome(struct xchk_dirtree * dl,struct xchk_dirpath * path,enum xchk_dirpath_outcome outcome)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
xrep_dirtree_delete_all_paths(struct xchk_dirtree * dl,struct xchk_dirtree_outcomes * oc)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
xrep_dirpath_retain_parent(struct xchk_dirtree * dl,struct xchk_dirpath * path)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
xrep_dirtree_find_surviving_path(struct xchk_dirtree * dl,struct xchk_dirtree_outcomes * oc)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
xrep_dirtree_keep_one_good_path(struct xchk_dirtree * dl,struct xchk_dirtree_outcomes * oc)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
xrep_dirtree_keep_one_suspect_path(struct xchk_dirtree * dl,struct xchk_dirtree_outcomes * oc)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
xrep_dirtree_decide_fate(struct xchk_dirtree * dl,struct xchk_dirtree_outcomes * oc)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
xrep_dirtree_prep_path(struct xchk_dirtree * dl,struct xchk_dirpath * path,struct xchk_dirpath_step * step)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
xrep_dirtree_purge_dentry(struct xchk_dirtree * dl,struct xfs_inode * dp,const struct xfs_name * name)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
xrep_dirtree_unlink_iolock(struct xfs_scrub * sc,struct xfs_inode * dp)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
xrep_dirtree_unlink(struct xchk_dirtree * dl,struct xfs_inode * dp,struct xchk_dirpath * path,struct xchk_dirpath_step * step)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
xrep_dirtree_delete_path(struct xchk_dirtree * dl,struct xchk_dirpath * path)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
xrep_dirtree_create_adoption_path(struct xchk_dirtree * dl)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
xrep_dirtree_adopt_iolock(struct xfs_scrub * sc)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
xrep_dirtree_adopt(struct xchk_dirtree * dl)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
xrep_dirtree_move_to_orphanage(struct xchk_dirtree * dl)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
xrep_dirtree_fix_problems(struct xchk_dirtree * dl,struct xchk_dirtree_outcomes * oc)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
xrep_dirtree(struct xfs_scrub * sc)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