File Index
Files and directories
Sign in
FILE

dirtree_repair.c

File preview with syntax highlighting.

linux-6.19.14/fs/xfs/scrub/dirtree_repair.c C
  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. */
 46int
 47xrep_setup_dirtree(
 48	struct xfs_scrub	*sc)
 49{
 50	return xrep_orphanage_try_create(sc);
 51}
 52
 53/* Change the outcome of this path. */
 54static inline void
 55xrep_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. */
 67STATIC void
 68xrep_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. */
 97STATIC void
 98xrep_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. */
113STATIC void
114xrep_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. */
142STATIC void
143xrep_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. */
178STATIC void
179xrep_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 */
215STATIC void
216xrep_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 */
261STATIC int
262xrep_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. */
283STATIC int
284xrep_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
331out_dput_child:
332	dput(child_dentry);
333out_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 */
343static inline int
344xrep_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 */
377STATIC int
378xrep_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
488out_trans_cancel:
489	xchk_trans_cancel(sc);
490out_ilock:
491	xfs_iunlock(sc->ip, XFS_ILOCK_EXCL);
492	xfs_iunlock(dp, XFS_ILOCK_EXCL);
493out_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 */
502STATIC int
503xrep_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. */
549STATIC int
550xrep_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
606out_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 */
617static inline int
618xrep_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 */
651STATIC int
652xrep_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
706out_trans:
707	xchk_trans_cancel(sc);
708out_ilock:
709	xchk_iunlock(sc, XFS_ILOCK_EXCL);
710	xrep_orphanage_iunlock(sc, XFS_ILOCK_EXCL);
711out_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 */
720STATIC int
721xrep_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 */
756STATIC int
757xrep_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. */
785int
786xrep_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}
~/ Read-only file preview.