From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: sandeen@redhat.com
Cc: linux-xfs@vger.kernel.org
Subject: [PATCH 28/27] xfs_scrub: wire up repair ioctl
Date: Tue, 16 Jan 2018 11:21:32 -0800 [thread overview]
Message-ID: <20180116192132.GR5602@magnolia> (raw)
In-Reply-To: <151520348769.2027.9860697266310422360.stgit@magnolia>
From: Darrick J. Wong <darrick.wong@oracle.com>
Create the mechanism we need to actually call the kernel's online repair
functionality. The interface will consume a repair description; the
descriptor management will follow in the next patch.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
scrub/common.c | 51 +++++++++++++++++++
scrub/common.h | 2 +
scrub/phase1.c | 15 ++++++
scrub/phase2.c | 1
scrub/phase3.c | 1
scrub/phase5.c | 1
scrub/scrub.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++
scrub/scrub.h | 20 ++++++++
scrub/xfs_scrub.h | 2 +
9 files changed, 232 insertions(+)
diff --git a/scrub/common.c b/scrub/common.c
index 48ee01c..bd3e939 100644
--- a/scrub/common.c
+++ b/scrub/common.c
@@ -180,6 +180,57 @@ __str_info(
pthread_mutex_unlock(&ctx->lock);
}
+/* Increment the repair count. */
+void
+__record_repair(
+ struct scrub_ctx *ctx,
+ const char *descr,
+ const char *file,
+ int line,
+ const char *format,
+ ...)
+{
+ va_list args;
+
+ pthread_mutex_lock(&ctx->lock);
+ fprintf(stderr, _("Repaired: %s: "), descr);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ if (debug)
+ fprintf(stderr, _(" (%s line %d)"), file, line);
+ fprintf(stderr, "\n");
+ ctx->repairs++;
+ pthread_mutex_unlock(&ctx->lock);
+}
+
+/* Increment the optimization (preening) count. */
+void
+__record_preen(
+ struct scrub_ctx *ctx,
+ const char *descr,
+ const char *file,
+ int line,
+ const char *format,
+ ...)
+{
+ va_list args;
+
+ pthread_mutex_lock(&ctx->lock);
+ if (debug || verbose) {
+ fprintf(stdout, _("Optimized: %s: "), descr);
+ va_start(args, format);
+ vfprintf(stdout, format, args);
+ va_end(args);
+ if (debug)
+ fprintf(stdout, _(" (%s line %d)"), file, line);
+ fprintf(stdout, "\n");
+ fflush(stdout);
+ }
+ ctx->preens++;
+ pthread_mutex_unlock(&ctx->lock);
+}
+
/* Catch fatal errors from pieces we import from xfs_repair. */
void __attribute__((noreturn))
do_error(char const *msg, ...)
diff --git a/scrub/common.h b/scrub/common.h
index bd67a17..ea3bc3f 100644
--- a/scrub/common.h
+++ b/scrub/common.h
@@ -49,6 +49,8 @@ void __str_errno_warn(struct scrub_ctx *, const char *descr, const char *file,
#define str_warn(ctx, str, ...) __str_warn(ctx, str, __FILE__, __LINE__, __VA_ARGS__)
#define str_info(ctx, str, ...) __str_info(ctx, str, __FILE__, __LINE__, __VA_ARGS__)
#define str_errno_warn(ctx, str) __str_errno_warn(ctx, str, __FILE__, __LINE__)
+#define record_repair(ctx, str, ...) __record_repair(ctx, str, __FILE__, __LINE__, __VA_ARGS__)
+#define record_preen(ctx, str, ...) __record_preen(ctx, str, __FILE__, __LINE__, __VA_ARGS__)
#define dbg_printf(fmt, ...) {if (debug > 1) {printf(fmt, __VA_ARGS__);}}
/* Is this debug tweak enabled? */
diff --git a/scrub/phase1.c b/scrub/phase1.c
index d7a321f..3a2fbd7 100644
--- a/scrub/phase1.c
+++ b/scrub/phase1.c
@@ -176,6 +176,21 @@ _("Does not appear to be an XFS filesystem!"));
!xfs_can_scrub_parent(ctx))
return false;
+ /* Do we have kernel-assisted metadata repair? */
+ if (ctx->mode != SCRUB_MODE_DRY_RUN && !xfs_can_repair(ctx)) {
+ if (ctx->mode == SCRUB_MODE_PREEN) {
+ /* w/o repair, demote preen to dry run. */
+ if (debug || verbose)
+ str_info(ctx, ctx->mntpoint,
+_("Metadata repairing not supported; demoting to scan mode.")
+ );
+ ctx->mode = SCRUB_MODE_DRY_RUN;
+ } else {
+ /* Repair mode w/o repair; abort. */
+ return false;
+ }
+ }
+
/* Go find the XFS devices if we have a usable fsmap. */
fs_table_initialise(0, NULL, 0, NULL);
errno = 0;
diff --git a/scrub/phase2.c b/scrub/phase2.c
index e8eb1ca..32e2752 100644
--- a/scrub/phase2.c
+++ b/scrub/phase2.c
@@ -24,6 +24,7 @@
#include <sys/stat.h>
#include <sys/statvfs.h>
#include "xfs.h"
+#include "list.h"
#include "path.h"
#include "workqueue.h"
#include "xfs_scrub.h"
diff --git a/scrub/phase3.c b/scrub/phase3.c
index 43697c6..f4117b0 100644
--- a/scrub/phase3.c
+++ b/scrub/phase3.c
@@ -24,6 +24,7 @@
#include <sys/stat.h>
#include <sys/statvfs.h>
#include "xfs.h"
+#include "list.h"
#include "path.h"
#include "workqueue.h"
#include "xfs_scrub.h"
diff --git a/scrub/phase5.c b/scrub/phase5.c
index fc3308b..703b279 100644
--- a/scrub/phase5.c
+++ b/scrub/phase5.c
@@ -29,6 +29,7 @@
#endif
#include "xfs.h"
#include "handle.h"
+#include "list.h"
#include "path.h"
#include "workqueue.h"
#include "xfs_scrub.h"
diff --git a/scrub/scrub.c b/scrub/scrub.c
index bc4eab4..5729b9b 100644
--- a/scrub/scrub.c
+++ b/scrub/scrub.c
@@ -28,6 +28,7 @@
#include <sys/statvfs.h>
#include "xfs.h"
#include "xfs_fs.h"
+#include "list.h"
#include "path.h"
#include "xfs_scrub.h"
#include "common.h"
@@ -561,10 +562,20 @@ __xfs_scrub_test(
bool repair)
{
struct xfs_scrub_metadata meta = {0};
+ struct xfs_error_injection inject;
+ static bool injected;
int error;
if (debug_tweak_on("XFS_SCRUB_NO_KERNEL"))
return false;
+ if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR") && !injected) {
+ inject.fd = ctx->mnt_fd;
+ inject.errtag = XFS_ERRTAG_FORCE_SCRUB_REPAIR;
+ error = ioctl(ctx->mnt_fd,
+ XFS_IOC_ERROR_INJECTION, &inject);
+ if (error == 0)
+ injected = true;
+ }
meta.sm_type = type;
if (repair)
@@ -646,3 +657,131 @@ xfs_can_scrub_parent(
{
return __xfs_scrub_test(ctx, XFS_SCRUB_TYPE_PARENT, false);
}
+
+bool
+xfs_can_repair(
+ struct scrub_ctx *ctx)
+{
+ return __xfs_scrub_test(ctx, XFS_SCRUB_TYPE_PROBE, true);
+}
+
+/* General repair routines. */
+
+/* Repair some metadata. */
+enum check_outcome
+xfs_repair_metadata(
+ struct scrub_ctx *ctx,
+ int fd,
+ struct repair_item *ri,
+ unsigned int repair_flags)
+{
+ char buf[DESCR_BUFSZ];
+ struct xfs_scrub_metadata meta = { 0 };
+ struct xfs_scrub_metadata oldm;
+ int error;
+
+ assert(ri->type < XFS_SCRUB_TYPE_NR);
+ assert(!debug_tweak_on("XFS_SCRUB_NO_KERNEL"));
+ meta.sm_type = ri->type;
+ meta.sm_flags = ri->flags | XFS_SCRUB_IFLAG_REPAIR;
+ switch (scrubbers[ri->type].type) {
+ case ST_AGHEADER:
+ case ST_PERAG:
+ meta.sm_agno = ri->agno;
+ break;
+ case ST_INODE:
+ meta.sm_ino = ri->ino;
+ meta.sm_gen = ri->gen;
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * If this is a preen operation but we're only repairing
+ * critical items, defer the preening until later.
+ */
+ if (!needs_repair(&meta) && (repair_flags & XRM_REPAIR_ONLY))
+ return CHECK_RETRY;
+
+ memcpy(&oldm, &meta, sizeof(oldm));
+ format_scrub_descr(buf, DESCR_BUFSZ, &meta, &scrubbers[meta.sm_type]);
+
+ if (needs_repair(&meta))
+ str_info(ctx, buf, _("Attempting repair."));
+ else if (debug || verbose)
+ str_info(ctx, buf, _("Attempting optimization."));
+
+ error = ioctl(fd, XFS_IOC_SCRUB_METADATA, &meta);
+ /*
+ * If the caller doesn't want us to complain, tell the caller to
+ * requeue the repair for later and don't say a thing.
+ */
+ if (!(repair_flags & XRM_NOFIX_COMPLAIN) &&
+ (error || needs_repair(&meta)))
+ return CHECK_RETRY;
+ if (error) {
+ switch (errno) {
+ case EDEADLOCK:
+ case EBUSY:
+ /* Filesystem is busy, try again later. */
+ if (debug || verbose)
+ str_info(ctx, buf,
+_("Filesystem is busy, deferring repair."));
+ return CHECK_RETRY;
+ case ESHUTDOWN:
+ /* Filesystem is already shut down, abort. */
+ str_error(ctx, buf,
+_("Filesystem is shut down, aborting."));
+ return CHECK_ABORT;
+ case ENOTTY:
+ case EOPNOTSUPP:
+ /*
+ * If we forced repairs, don't complain if kernel
+ * doesn't know how to fix.
+ */
+ if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR"))
+ return CHECK_DONE;
+ /* fall through */
+ case EINVAL:
+ /* Kernel doesn't know how to repair this? */
+ str_error(ctx, buf,
+_("Don't know how to fix; offline repair required."));
+ return CHECK_DONE;
+ case EROFS:
+ /* Read-only filesystem, can't fix. */
+ if (verbose || debug || needs_repair(&oldm))
+ str_info(ctx, buf,
+_("Read-only filesystem; cannot make changes."));
+ return CHECK_DONE;
+ case ENOENT:
+ /* Metadata not present, just skip it. */
+ return CHECK_DONE;
+ case ENOMEM:
+ case ENOSPC:
+ /* Don't care if preen fails due to low resources. */
+ if (is_unoptimized(&oldm) && !needs_repair(&oldm))
+ return CHECK_DONE;
+ /* fall through */
+ default:
+ /* Operational error. */
+ str_errno(ctx, buf);
+ return CHECK_DONE;
+ }
+ }
+ if (repair_flags & XRM_NOFIX_COMPLAIN)
+ xfs_scrub_warn_incomplete_scrub(ctx, buf, &meta);
+ if (needs_repair(&meta)) {
+ /* Still broken, try again or fix offline. */
+ if (repair_flags & XRM_NOFIX_COMPLAIN)
+ str_error(ctx, buf,
+_("Repair unsuccessful; offline repair required."));
+ } else {
+ /* Clean operation, no corruption detected. */
+ if (needs_repair(&oldm))
+ record_repair(ctx, buf, _("Repairs successful."));
+ else
+ record_preen(ctx, buf, _("Optimization successful."));
+ }
+ return CHECK_DONE;
+}
diff --git a/scrub/scrub.h b/scrub/scrub.h
index 0b454df..1c44fba 100644
--- a/scrub/scrub.h
+++ b/scrub/scrub.h
@@ -41,6 +41,7 @@ bool xfs_can_scrub_dir(struct scrub_ctx *ctx);
bool xfs_can_scrub_attr(struct scrub_ctx *ctx);
bool xfs_can_scrub_symlink(struct scrub_ctx *ctx);
bool xfs_can_scrub_parent(struct scrub_ctx *ctx);
+bool xfs_can_repair(struct scrub_ctx *ctx);
bool xfs_scrub_inode_fields(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
int fd);
@@ -59,4 +60,23 @@ bool xfs_scrub_symlink(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
bool xfs_scrub_parent(struct scrub_ctx *ctx, uint64_t ino, uint32_t gen,
int fd);
+/* Repair parameters are the scrub inputs and retry count. */
+struct repair_item {
+ struct list_head list;
+ __u64 ino;
+ __u32 type;
+ __u32 flags;
+ __u32 gen;
+ __u32 agno;
+};
+
+/* Only perform repairs; leave optimization-only actions for later. */
+#define XRM_REPAIR_ONLY (1U << 0)
+
+/* Complain if still broken even after fix. */
+#define XRM_NOFIX_COMPLAIN (1U << 1)
+
+enum check_outcome xfs_repair_metadata(struct scrub_ctx *ctx, int fd,
+ struct repair_item *ri, unsigned int repair_flags);
+
#endif /* XFS_SCRUB_SCRUB_H_ */
diff --git a/scrub/xfs_scrub.h b/scrub/xfs_scrub.h
index 9b5e490..83b8ae2 100644
--- a/scrub/xfs_scrub.h
+++ b/scrub/xfs_scrub.h
@@ -97,6 +97,8 @@ struct scrub_ctx {
unsigned long long inodes_checked;
unsigned long long bytes_checked;
unsigned long long naming_warnings;
+ unsigned long long repairs;
+ unsigned long long preens;
bool need_repair;
bool preen_triggers[XFS_SCRUB_TYPE_NR];
};
next prev parent reply other threads:[~2018-01-16 19:24 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-06 1:51 [PATCH v11 00/27] xfsprogs: online scrub/repair support Darrick J. Wong
2018-01-06 1:51 ` [PATCH 01/27] xfs_scrub: create online filesystem scrub program Darrick J. Wong
2018-01-12 0:16 ` Eric Sandeen
2018-01-12 1:08 ` Darrick J. Wong
2018-01-12 1:07 ` Eric Sandeen
2018-01-12 1:10 ` Darrick J. Wong
2018-01-06 1:51 ` [PATCH 02/27] xfs_scrub: common error handling Darrick J. Wong
2018-01-12 1:15 ` Eric Sandeen
2018-01-12 1:23 ` Darrick J. Wong
2018-01-06 1:51 ` [PATCH 03/27] xfs_scrub: set up command line argument parsing Darrick J. Wong
2018-01-11 23:39 ` Eric Sandeen
2018-01-12 1:53 ` Darrick J. Wong
2018-01-12 1:30 ` Eric Sandeen
2018-01-12 2:03 ` Darrick J. Wong
2018-01-06 1:51 ` [PATCH 04/27] xfs_scrub: dispatch the various phases of the scrub program Darrick J. Wong
2018-01-06 1:51 ` [PATCH 05/27] xfs_scrub: figure out how many threads we're going to need Darrick J. Wong
2018-01-06 1:52 ` [PATCH 06/27] xfs_scrub: create an abstraction for a block device Darrick J. Wong
2018-01-11 23:24 ` Eric Sandeen
2018-01-11 23:59 ` Darrick J. Wong
2018-01-12 0:04 ` Eric Sandeen
2018-01-12 1:27 ` Darrick J. Wong
2018-01-06 1:52 ` [PATCH 07/27] xfs_scrub: find XFS filesystem geometry Darrick J. Wong
2018-01-06 1:52 ` [PATCH 08/27] xfs_scrub: add inode iteration functions Darrick J. Wong
2018-01-06 1:52 ` [PATCH 09/27] xfs_scrub: add space map " Darrick J. Wong
2018-01-06 1:52 ` [PATCH 10/27] xfs_scrub: add file " Darrick J. Wong
2018-01-11 23:19 ` Eric Sandeen
2018-01-12 0:24 ` Darrick J. Wong
2018-01-06 1:52 ` [PATCH 11/27] xfs_scrub: filesystem counter collection functions Darrick J. Wong
2018-01-06 1:52 ` [PATCH 12/27] xfs_scrub: wrap the scrub ioctl Darrick J. Wong
2018-01-11 23:12 ` Eric Sandeen
2018-01-12 0:28 ` Darrick J. Wong
2018-01-06 1:52 ` [PATCH 13/27] xfs_scrub: scan filesystem and AG metadata Darrick J. Wong
2018-01-06 1:52 ` [PATCH 14/27] xfs_scrub: thread-safe stats counter Darrick J. Wong
2018-01-06 1:53 ` [PATCH 15/27] xfs_scrub: scan inodes Darrick J. Wong
2018-01-06 1:53 ` [PATCH 16/27] xfs_scrub: check directory connectivity Darrick J. Wong
2018-01-06 1:53 ` [PATCH 17/27] xfs_scrub: warn about suspicious characters in directory/xattr names Darrick J. Wong
2018-01-06 1:53 ` [PATCH 18/27] xfs_scrub: warn about normalized Unicode name collisions Darrick J. Wong
2018-01-16 23:52 ` Eric Sandeen
2018-01-16 23:57 ` Eric Sandeen
2018-01-16 23:59 ` Darrick J. Wong
2018-01-06 1:53 ` [PATCH 19/27] xfs_scrub: create a bitmap data structure Darrick J. Wong
2018-01-06 1:53 ` [PATCH 20/27] xfs_scrub: create infrastructure to read verify data blocks Darrick J. Wong
2018-01-06 1:53 ` [PATCH 21/27] xfs_scrub: scrub file " Darrick J. Wong
2018-01-11 23:25 ` Eric Sandeen
2018-01-12 0:29 ` Darrick J. Wong
2018-01-06 1:53 ` [PATCH 22/27] xfs_scrub: optionally use SCSI READ VERIFY commands to scrub data blocks on disk Darrick J. Wong
2018-01-06 1:53 ` [PATCH 23/27] xfs_scrub: check summary counters Darrick J. Wong
2018-01-06 1:54 ` [PATCH 24/27] xfs_scrub: fstrim the free areas if there are no errors on the filesystem Darrick J. Wong
2018-01-16 22:07 ` Eric Sandeen
2018-01-16 22:23 ` Darrick J. Wong
2018-01-06 1:54 ` [PATCH 25/27] xfs_scrub: progress indicator Darrick J. Wong
2018-01-11 23:27 ` Eric Sandeen
2018-01-12 0:32 ` Darrick J. Wong
2018-01-06 1:54 ` [PATCH 26/27] xfs_scrub: create a script to scrub all xfs filesystems Darrick J. Wong
2018-01-06 1:54 ` [PATCH 27/27] xfs_scrub: integrate services with systemd Darrick J. Wong
2018-01-06 3:50 ` [PATCH 07/27] xfs_scrub: find XFS filesystem geometry Darrick J. Wong
2018-01-12 4:17 ` [PATCH v11 00/27] xfsprogs: online scrub/repair support Eric Sandeen
2018-01-17 1:31 ` Darrick J. Wong
2018-01-16 19:21 ` Darrick J. Wong [this message]
2018-01-16 19:21 ` [PATCH 29/27] xfs_scrub: schedule and manage repairs to the filesystem Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180116192132.GR5602@magnolia \
--to=darrick.wong@oracle.com \
--cc=linux-xfs@vger.kernel.org \
--cc=sandeen@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.