Commit 5221002c authored by Chandan Babu R's avatar Chandan Babu R
Browse files

Merge tag 'repair-force-rebuild-6.6_2023-08-10' of...

Merge tag 'repair-force-rebuild-6.6_2023-08-10' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux

 into xfs-6.6-mergeA

xfs: force rebuilding of metadata

This patchset adds a new IFLAG to the scrub ioctl so that userspace can
force a rebuild of an otherwise consistent piece of metadata.  This will
eventually enable the use of online repair to relocate metadata during a
filesystem reorganization (e.g. shrink).  For now, it facilitates stress
testing of online repair without needing the debugging knobs to be
enabled.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarChandan Babu R <chandan.babu@oracle.com>

* tag 'repair-force-rebuild-6.6_2023-08-10' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux:
  xfs: allow userspace to rebuild metadata structures
  xfs: don't complain about unfixed metadata when repairs were injected
parents 7857acd8 5c83df2e
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -743,7 +743,11 @@ struct xfs_scrub_metadata {
 */
#define XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED (1u << 7)

#define XFS_SCRUB_FLAGS_IN	(XFS_SCRUB_IFLAG_REPAIR)
/* i: Rebuild the data structure. */
#define XFS_SCRUB_IFLAG_FORCE_REBUILD	(1u << 8)

#define XFS_SCRUB_FLAGS_IN	(XFS_SCRUB_IFLAG_REPAIR | \
				 XFS_SCRUB_IFLAG_FORCE_REBUILD)
#define XFS_SCRUB_FLAGS_OUT	(XFS_SCRUB_OFLAG_CORRUPT | \
				 XFS_SCRUB_OFLAG_PREEN | \
				 XFS_SCRUB_OFLAG_XFAIL | \
+12 −0
Original line number Diff line number Diff line
@@ -167,6 +167,18 @@ static inline bool xchk_skip_xref(struct xfs_scrub_metadata *sm)
			       XFS_SCRUB_OFLAG_XCORRUPT);
}

#ifdef CONFIG_XFS_ONLINE_REPAIR
/* Decide if a repair is required. */
static inline bool xchk_needs_repair(const struct xfs_scrub_metadata *sm)
{
	return sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
			       XFS_SCRUB_OFLAG_XCORRUPT |
			       XFS_SCRUB_OFLAG_PREEN);
}
#else
# define xchk_needs_repair(sc)		(false)
#endif /* CONFIG_XFS_ONLINE_REPAIR */

int xchk_metadata_inode_forks(struct xfs_scrub *sc);

/*
+12 −6
Original line number Diff line number Diff line
@@ -409,6 +409,11 @@ xchk_validate_inputs(
		goto out;
	}

	/* No rebuild without repair. */
	if ((sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD) &&
	    !(sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR))
		return -EINVAL;

	/*
	 * We only want to repair read-write v5+ filesystems.  Defer the check
	 * for ops->repair until after our scrub confirms that we need to
@@ -535,15 +540,16 @@ xfs_scrub_metadata(

	if ((sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR) &&
	    !(sc->flags & XREP_ALREADY_FIXED)) {
		bool needs_fix;
		bool needs_fix = xchk_needs_repair(sc->sm);

		/* Userspace asked us to rebuild the structure regardless. */
		if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_FORCE_REBUILD)
			needs_fix = true;

		/* Let debug users force us into the repair routines. */
		if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_FORCE_SCRUB_REPAIR))
			sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
		if (XFS_TEST_ERROR(needs_fix, mp, XFS_ERRTAG_FORCE_SCRUB_REPAIR))
			needs_fix = true;

		needs_fix = (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
						 XFS_SCRUB_OFLAG_XCORRUPT |
						 XFS_SCRUB_OFLAG_PREEN));
		/*
		 * If userspace asked for a repair but it wasn't necessary,
		 * report that back to userspace.
+2 −1
Original line number Diff line number Diff line
@@ -98,7 +98,8 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FSCOUNTERS);
	{ XFS_SCRUB_OFLAG_XCORRUPT,		"xcorrupt" }, \
	{ XFS_SCRUB_OFLAG_INCOMPLETE,		"incomplete" }, \
	{ XFS_SCRUB_OFLAG_WARNING,		"warning" }, \
	{ XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED,	"norepair" }
	{ XFS_SCRUB_OFLAG_NO_REPAIR_NEEDED,	"norepair" }, \
	{ XFS_SCRUB_IFLAG_FORCE_REBUILD,	"rebuild" }

#define XFS_SCRUB_STATE_STRINGS \
	{ XCHK_TRY_HARDER,			"try_harder" }, \