Commit b1991ee3 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: online repair of directories



If a directory looks like it's in bad shape, try to sift through the
rubble to find whatever directory entries we can, scan the directory
tree for the parent (if needed), stage the new directory contents in a
temporary file and use the atomic extent swapping mechanism to commit
the results in bulk.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 8d81082a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -198,6 +198,7 @@ xfs-y += $(addprefix scrub/, \
				   attr_repair.o \
				   bmap_repair.o \
				   cow_repair.o \
				   dir_repair.o \
				   fscounters_repair.o \
				   ialloc_repair.o \
				   inode_repair.o \
+9 −0
Original line number Diff line number Diff line
@@ -21,12 +21,21 @@
#include "scrub/dabtree.h"
#include "scrub/readdir.h"
#include "scrub/health.h"
#include "scrub/repair.h"

/* Set us up to scrub directories. */
int
xchk_setup_directory(
	struct xfs_scrub	*sc)
{
	int			error;

	if (xchk_could_repair(sc)) {
		error = xrep_setup_directory(sc);
		if (error)
			return error;
	}

	return xchk_setup_inode_contents(sc, 0);
}

+1349 −0

File added.

Preview size limit exceeded, changes collapsed.

+5 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
#include "scrub/repair.h"
#include "scrub/iscan.h"
#include "scrub/readdir.h"
#include "scrub/tempfile.h"

/*
 * Inode Record Repair
@@ -340,6 +341,10 @@ xrep_dinode_findmode_walk_directory(
	unsigned int		lock_mode;
	int			error = 0;

	/* Ignore temporary repair directories. */
	if (xrep_is_tempfile(dp))
		return 0;

	/*
	 * Scan the directory to see if there it contains an entry pointing to
	 * the directory that we are repairing.
+23 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "scrub/nlinks.h"
#include "scrub/trace.h"
#include "scrub/readdir.h"
#include "scrub/tempfile.h"

/*
 * Live Inode Link Count Checking
@@ -152,6 +153,13 @@ xchk_nlinks_live_update(

	xnc = container_of(nb, struct xchk_nlink_ctrs, dhook.dirent_hook.nb);

	/*
	 * Ignore temporary directories being used to stage dir repairs, since
	 * we don't bump the link counts of the children.
	 */
	if (xrep_is_tempfile(p->dp))
		return NOTIFY_DONE;

	trace_xchk_nlinks_live_update(xnc->sc->mp, p->dp, action, p->ip->i_ino,
			p->delta, p->name->name, p->name->len);

@@ -303,6 +311,13 @@ xchk_nlinks_collect_dir(
	unsigned int		lock_mode;
	int			error = 0;

	/*
	 * Ignore temporary directories being used to stage dir repairs, since
	 * we don't bump the link counts of the children.
	 */
	if (xrep_is_tempfile(dp))
		return 0;

	/* Prevent anyone from changing this directory while we walk it. */
	xfs_ilock(dp, XFS_IOLOCK_SHARED);
	lock_mode = xfs_ilock_data_map_shared(dp);
@@ -537,6 +552,14 @@ xchk_nlinks_compare_inode(
	unsigned int		actual_nlink;
	int			error;

	/*
	 * Ignore temporary files being used to stage repairs, since we assume
	 * they're correct for non-directories, and the directory repair code
	 * doesn't bump the link counts for the children.
	 */
	if (xrep_is_tempfile(ip))
		return 0;

	xfs_ilock(ip, XFS_ILOCK_SHARED);
	mutex_lock(&xnc->lock);

Loading