]> git.apps.os.sepia.ceph.com Git - xfsprogs-dev.git/commitdiff
xfs_scrub: try to use XFS_SCRUB_IFLAG_FORCE_REBUILD
authorDarrick J. Wong <djwong@kernel.org>
Wed, 20 Dec 2023 16:53:47 +0000 (08:53 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 22 Dec 2023 02:29:14 +0000 (18:29 -0800)
Now that we have a FORCE_REBUILD flag to the scrub ioctl, try to use
that over the (much noisier) error injection knob, which may or may not
even be enabled in the kernel config.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
scrub/phase1.c
scrub/scrub.c
scrub/scrub.h
scrub/xfs_scrub.c
scrub/xfs_scrub.h

index fd1050c92027bae75de3381ee60a511ddd328448..2daf5c7bb389213a2ec55d962049611c2b8a338c 100644 (file)
@@ -27,6 +27,7 @@
 #include "scrub.h"
 #include "repair.h"
 #include "libfrog/fsgeom.h"
+#include "xfs_errortag.h"
 
 /* Phase 1: Find filesystem geometry (and clean up after) */
 
@@ -68,6 +69,27 @@ scrub_cleanup(
        return error;
 }
 
+/* Decide if we're using FORCE_REBUILD or injecting FORCE_REPAIR. */
+static int
+enable_force_repair(
+       struct scrub_ctx                *ctx)
+{
+       struct xfs_error_injection      inject = {
+               .fd                     = ctx->mnt.fd,
+               .errtag                 = XFS_ERRTAG_FORCE_SCRUB_REPAIR,
+       };
+       int                             error;
+
+       use_force_rebuild = can_force_rebuild(ctx);
+       if (use_force_rebuild)
+               return 0;
+
+       error = ioctl(ctx->mnt.fd, XFS_IOC_ERROR_INJECTION, &inject);
+       if (error)
+               str_errno(ctx, _("force_repair"));
+       return error;
+}
+
 /*
  * Bind to the mountpoint, read the XFS geometry, bind to the block devices.
  * Anything we've already built will be cleaned up by scrub_cleanup.
@@ -156,6 +178,12 @@ _("Kernel metadata repair facility is not available.  Use -n to scrub."));
                return ECANCELED;
        }
 
+       if (debug_tweak_on("XFS_SCRUB_FORCE_REPAIR")) {
+               error = enable_force_repair(ctx);
+               if (error)
+                       return error;
+       }
+
        /* Did we find the log and rt devices, if they're present? */
        if (ctx->mnt.fsgeom.logstart == 0 && ctx->fsinfo.fs_log == NULL) {
                str_error(ctx, ctx->mntpoint,
index 1a4506875f737ffee5e1c4e978e352b04e93ea5f..1469058bd23efd8767ce191d0d65840a348d44a0 100644 (file)
@@ -18,7 +18,6 @@
 #include "common.h"
 #include "progress.h"
 #include "scrub.h"
-#include "xfs_errortag.h"
 #include "repair.h"
 #include "descr.h"
 
@@ -500,26 +499,16 @@ static bool
 __scrub_test(
        struct scrub_ctx                *ctx,
        unsigned int                    type,
-       bool                            repair)
+       unsigned int                    flags)
 {
        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)
-               meta.sm_flags |= XFS_SCRUB_IFLAG_REPAIR;
+       meta.sm_flags = flags;
        error = -xfrog_scrub_metadata(&ctx->mnt, &meta);
        switch (error) {
        case 0:
@@ -532,13 +521,15 @@ _("Filesystem is mounted read-only; cannot proceed."));
                str_info(ctx, ctx->mntpoint,
 _("Filesystem is mounted norecovery; cannot proceed."));
                return false;
+       case EINVAL:
        case EOPNOTSUPP:
        case ENOTTY:
                if (debug || verbose)
                        str_info(ctx, ctx->mntpoint,
 _("Kernel %s %s facility not detected."),
                                        _(xfrog_scrubbers[type].descr),
-                                       repair ? _("repair") : _("scrub"));
+                                       (flags & XFS_SCRUB_IFLAG_REPAIR) ?
+                                               _("repair") : _("scrub"));
                return false;
        case ENOENT:
                /* Scrubber says not present on this fs; that's fine. */
@@ -553,56 +544,64 @@ bool
 can_scrub_fs_metadata(
        struct scrub_ctx        *ctx)
 {
-       return __scrub_test(ctx, XFS_SCRUB_TYPE_PROBE, false);
+       return __scrub_test(ctx, XFS_SCRUB_TYPE_PROBE, 0);
 }
 
 bool
 can_scrub_inode(
        struct scrub_ctx        *ctx)
 {
-       return __scrub_test(ctx, XFS_SCRUB_TYPE_INODE, false);
+       return __scrub_test(ctx, XFS_SCRUB_TYPE_INODE, 0);
 }
 
 bool
 can_scrub_bmap(
        struct scrub_ctx        *ctx)
 {
-       return __scrub_test(ctx, XFS_SCRUB_TYPE_BMBTD, false);
+       return __scrub_test(ctx, XFS_SCRUB_TYPE_BMBTD, 0);
 }
 
 bool
 can_scrub_dir(
        struct scrub_ctx        *ctx)
 {
-       return __scrub_test(ctx, XFS_SCRUB_TYPE_DIR, false);
+       return __scrub_test(ctx, XFS_SCRUB_TYPE_DIR, 0);
 }
 
 bool
 can_scrub_attr(
        struct scrub_ctx        *ctx)
 {
-       return __scrub_test(ctx, XFS_SCRUB_TYPE_XATTR, false);
+       return __scrub_test(ctx, XFS_SCRUB_TYPE_XATTR, 0);
 }
 
 bool
 can_scrub_symlink(
        struct scrub_ctx        *ctx)
 {
-       return __scrub_test(ctx, XFS_SCRUB_TYPE_SYMLINK, false);
+       return __scrub_test(ctx, XFS_SCRUB_TYPE_SYMLINK, 0);
 }
 
 bool
 can_scrub_parent(
        struct scrub_ctx        *ctx)
 {
-       return __scrub_test(ctx, XFS_SCRUB_TYPE_PARENT, false);
+       return __scrub_test(ctx, XFS_SCRUB_TYPE_PARENT, 0);
 }
 
 bool
 xfs_can_repair(
        struct scrub_ctx        *ctx)
 {
-       return __scrub_test(ctx, XFS_SCRUB_TYPE_PROBE, true);
+       return __scrub_test(ctx, XFS_SCRUB_TYPE_PROBE, XFS_SCRUB_IFLAG_REPAIR);
+}
+
+bool
+can_force_rebuild(
+       struct scrub_ctx        *ctx)
+{
+       return __scrub_test(ctx, XFS_SCRUB_TYPE_PROBE,
+                       XFS_SCRUB_IFLAG_REPAIR | XFS_SCRUB_IFLAG_FORCE_REBUILD);
 }
 
 /* General repair routines. */
@@ -624,6 +623,8 @@ xfs_repair_metadata(
        assert(!debug_tweak_on("XFS_SCRUB_NO_KERNEL"));
        meta.sm_type = aitem->type;
        meta.sm_flags = aitem->flags | XFS_SCRUB_IFLAG_REPAIR;
+       if (use_force_rebuild)
+               meta.sm_flags |= XFS_SCRUB_IFLAG_FORCE_REBUILD;
        switch (xfrog_scrubbers[aitem->type].type) {
        case XFROG_SCRUB_TYPE_AGHEADER:
        case XFROG_SCRUB_TYPE_PERAG:
index fccd82f21554f89ef1ec709ac29d9f11194470a3..023069ee066f41b397be22d68ca2e5ae2ed0d94f 100644 (file)
@@ -33,6 +33,7 @@ bool can_scrub_attr(struct scrub_ctx *ctx);
 bool can_scrub_symlink(struct scrub_ctx *ctx);
 bool can_scrub_parent(struct scrub_ctx *ctx);
 bool xfs_can_repair(struct scrub_ctx *ctx);
+bool can_force_rebuild(struct scrub_ctx *ctx);
 
 int scrub_file(struct scrub_ctx *ctx, int fd, const struct xfs_bulkstat *bstat,
                unsigned int type, struct action_list *alist);
index 7a0411b0cc86d8768192d241721d0e5d6954717f..597be59f9f985b09d3fa98a8800f29411aae0263 100644 (file)
@@ -157,6 +157,9 @@ bool                                stdout_isatty;
  */
 bool                           is_service;
 
+/* Set to true if the kernel supports XFS_SCRUB_IFLAG_FORCE_REBUILD */
+bool                           use_force_rebuild;
+
 #define SCRUB_RET_SUCCESS      (0)     /* no problems left behind */
 #define SCRUB_RET_CORRUPT      (1)     /* corruption remains on fs */
 #define SCRUB_RET_UNOPTIMIZED  (2)     /* fs could be optimized */
index f6712d368c6b4117818f250c2a5a372b836bb30b..0d6b9dad2c970464915864555e33d56ace18cab2 100644 (file)
@@ -21,6 +21,7 @@ extern bool                   want_fstrim;
 extern bool                    stderr_isatty;
 extern bool                    stdout_isatty;
 extern bool                    is_service;
+extern bool                    use_force_rebuild;
 
 enum scrub_mode {
        SCRUB_MODE_DRY_RUN,