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

xfs: repair inode records



If an inode is so badly damaged that it cannot be loaded into the cache,
fix the ondisk metadata and try again.  If there /is/ a cached inode,
fix any problems and apply any optimizations that can be solved incore.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent d9041681
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -184,6 +184,7 @@ xfs-y += $(addprefix scrub/, \
				   agheader_repair.o \
				   alloc_repair.o \
				   ialloc_repair.o \
				   inode_repair.o \
				   newbt.o \
				   reap.o \
				   refcount_repair.o \
+5 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "scrub/common.h"
#include "scrub/btree.h"
#include "scrub/trace.h"
#include "scrub/repair.h"

/* Prepare the attached inode for scrubbing. */
static inline int
@@ -185,8 +186,11 @@ xchk_setup_inode(
	 * saying the inode is allocated and the icache being unable to load
	 * the inode until we can flag the corruption in xchk_inode.  The
	 * scrub function has to note the corruption, since we're not really
	 * supposed to do that from the setup function.
	 * supposed to do that from the setup function.  Save the mapping to
	 * make repairs to the ondisk inode buffer.
	 */
	if (xchk_could_repair(sc))
		xrep_setup_inode(sc, &imap);
	return 0;

out_cancel:
+820 −0

File added.

Preview size limit exceeded, changes collapsed.

+42 −0
Original line number Diff line number Diff line
@@ -176,6 +176,16 @@ xrep_roll_ag_trans(
	return 0;
}

/* Roll the scrub transaction, holding the primary metadata locked. */
int
xrep_roll_trans(
	struct xfs_scrub	*sc)
{
	if (!sc->ip)
		return xrep_roll_ag_trans(sc);
	return xfs_trans_roll_inode(&sc->tp, sc->ip);
}

/* Finish all deferred work attached to the repair transaction. */
int
xrep_defer_finish(
@@ -740,6 +750,38 @@ xrep_ino_dqattach(
}
#endif /* CONFIG_XFS_QUOTA */

/*
 * Ensure that the inode being repaired is ready to handle a certain number of
 * extents, or return EFSCORRUPTED.  Caller must hold the ILOCK of the inode
 * being repaired and have joined it to the scrub transaction.
 */
int
xrep_ino_ensure_extent_count(
	struct xfs_scrub	*sc,
	int			whichfork,
	xfs_extnum_t		nextents)
{
	xfs_extnum_t		max_extents;
	bool			inode_has_nrext64;

	inode_has_nrext64 = xfs_inode_has_large_extent_counts(sc->ip);
	max_extents = xfs_iext_max_nextents(inode_has_nrext64, whichfork);
	if (nextents <= max_extents)
		return 0;
	if (inode_has_nrext64)
		return -EFSCORRUPTED;
	if (!xfs_has_large_extent_counts(sc->mp))
		return -EFSCORRUPTED;

	max_extents = xfs_iext_max_nextents(true, whichfork);
	if (nextents > max_extents)
		return -EFSCORRUPTED;

	sc->ip->i_diflags2 |= XFS_DIFLAG2_NREXT64;
	xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
	return 0;
}

/*
 * Initialize all the btree cursors for an AG repair except for the btree that
 * we're rebuilding.
+20 −0

File changed.

Preview size limit exceeded, changes collapsed.

Loading