]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_scrub: allow sysadmin to control background scrubs
authorDarrick J. Wong <djwong@kernel.org>
Thu, 8 Aug 2024 16:38:48 +0000 (09:38 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 8 Aug 2024 16:38:48 +0000 (09:38 -0700)
Add an extended option -o autofsck to xfs_scrub so that it selects the
operation mode from the "autofsck" filesystem property.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
man/man8/xfs_property.8
man/man8/xfs_scrub.8
scrub/phase1.c
scrub/xfs_scrub.c
scrub/xfs_scrub.h

index 19c1c0e3783f8a4e26a3f81eec6b9e8e8cadfebb..9fb1fd7ccd76fa9f9a47f811b1d75ee8857dd11b 100644 (file)
@@ -59,3 +59,11 @@ was set.
 remove
 .IR name ...
 Unsets the given filesystem properties.
+
+.SH FILESYSTEM PROPERTIES
+Known filesystem properties for XFS are:
+
+.I autofsck
+See
+.BR xfs_scrub (8)
+for more information.
index 1fd122f2a242b0b275e550467d485ff15d2a51fb..1ed4b176b6a35a0a12bcb70bfa21d25d90694abe 100644 (file)
@@ -107,6 +107,14 @@ The
 supported are:
 .RS 1.0i
 .TP
+.B autofsck
+Decide the operating mode from the value of the
+.I autofsck
+filesystem property.
+See the
+.B filesystem properties
+section for more details.
+.TP
 .BI fstrim_pct= percentage
 To constrain the amount of time spent on fstrim activities during phase 8,
 this program tries to balance estimated runtime against completeness of the
@@ -192,6 +200,44 @@ Scheduling a quotacheck for the next mount.
 .PP
 If corrupt metadata is successfully repaired, this program will log that
 a repair has succeeded instead of a corruption report.
+.SH FILESYSTEM PROPERTIES
+System administrators can convey their preferences for scrubbing of a
+particular filesystem by setting the filesystem property
+.B autofsck
+via the
+.BR xfs_property (8)
+command on the filesystem.
+These preferences will be honored if the
+.B -o autofsck
+option is specified.
+
+Recognized values for the
+.B autofsck
+property are:
+.RS
+.TP
+.I none
+Do not scan the filesystem at all.
+.TP
+.I check
+Scan and report corruption and opportunities for optimization, but do not
+change anything.
+.TP
+.I optimize
+Scan the filesystem and optimize where possible.
+Report corruptions, but do not fix them.
+.TP
+.I repair
+Scan the filesystem, fix corruptions, and optimize where possible.
+.RE
+
+If the property is not set, the default is
+.I check
+if the filesystem has either reverse mapping btrees or parent pointers enabled,
+or
+.I none
+otherwise.
+
 .SH EXIT CODE
 The exit code returned by
 .B xfs_scrub
index 091b59e57e7be224bbc5efd9e93959a202adc7ee..d03a9099a2173ca329984ec645066ba14ba878fb 100644 (file)
@@ -28,6 +28,8 @@
 #include "repair.h"
 #include "libfrog/fsgeom.h"
 #include "xfs_errortag.h"
+#include "libfrog/fsprops.h"
+#include "libfrog/fsproperties.h"
 
 /* Phase 1: Find filesystem geometry (and clean up after) */
 
@@ -130,6 +132,87 @@ enable_force_repair(
        return error;
 }
 
+/*
+ * Decide the operating mode from the autofsck fs property.  No fs property or
+ * system errors means we check the fs if rmapbt or pptrs are enabled, or none
+ * if it doesn't.
+ */
+static void
+mode_from_autofsck(
+       struct scrub_ctx        *ctx)
+{
+       struct fsprops_handle   fph = { };
+       char                    valuebuf[FSPROP_MAX_VALUELEN + 1] = { 0 };
+       size_t                  valuelen = FSPROP_MAX_VALUELEN;
+       enum fsprop_autofsck    shval;
+       int                     ret;
+
+       ret = fsprops_open_handle(&ctx->mnt, &ctx->fsinfo, &fph);
+       if (ret)
+               goto no_property;
+
+       ret = fsprops_get(&fph, FSPROP_AUTOFSCK_NAME, valuebuf, &valuelen);
+       if (ret)
+               goto no_property;
+
+       shval = fsprop_autofsck_read(valuebuf);
+       switch (shval) {
+       case FSPROP_AUTOFSCK_NONE:
+               ctx->mode = SCRUB_MODE_NONE;
+               break;
+       case FSPROP_AUTOFSCK_OPTIMIZE:
+               ctx->mode = SCRUB_MODE_PREEN;
+               break;
+       case FSPROP_AUTOFSCK_REPAIR:
+               ctx->mode = SCRUB_MODE_REPAIR;
+               break;
+       case FSPROP_AUTOFSCK_UNSET:
+               str_info(ctx, ctx->mntpoint,
+ _("Unknown autofsck directive \"%s\"."),
+                               valuebuf);
+               goto no_property;
+       case FSPROP_AUTOFSCK_CHECK:
+               ctx->mode = SCRUB_MODE_DRY_RUN;
+               break;
+       }
+
+       fsprops_free_handle(&fph);
+
+summarize:
+       switch (ctx->mode) {
+       case SCRUB_MODE_NONE:
+               str_info(ctx, ctx->mntpoint,
+ _("Disabling scrub per autofsck directive."));
+               break;
+       case SCRUB_MODE_DRY_RUN:
+               str_info(ctx, ctx->mntpoint,
+ _("Checking per autofsck directive."));
+               break;
+       case SCRUB_MODE_PREEN:
+               str_info(ctx, ctx->mntpoint,
+ _("Optimizing per autofsck directive."));
+               break;
+       case SCRUB_MODE_REPAIR:
+               str_info(ctx, ctx->mntpoint,
+ _("Checking and repairing per autofsck directive."));
+               break;
+       }
+
+       return;
+no_property:
+       /*
+        * If we don't find an autofsck property, check the metadata if any
+        * backrefs are available for cross-referencing.  Otherwise do no
+        * checking.
+        */
+       if (ctx->mnt.fsgeom.flags & (XFS_FSOP_GEOM_FLAGS_PARENT |
+                                    XFS_FSOP_GEOM_FLAGS_RMAPBT))
+               ctx->mode = SCRUB_MODE_DRY_RUN;
+       else
+               ctx->mode = SCRUB_MODE_NONE;
+       goto summarize;
+}
+
 /*
  * 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.
@@ -206,6 +289,14 @@ _("Not an XFS filesystem."));
                return error;
        }
 
+       /*
+        * If we've been instructed to decide the operating mode from the
+        * autofsck fs property, do that now before we start downgrading based
+        * on actual fs/kernel capabilities.
+        */
+       if (ctx->mode == SCRUB_MODE_NONE)
+               mode_from_autofsck(ctx);
+
        /* Do we have kernel-assisted metadata scrubbing? */
        if (!can_scrub_fs_metadata(ctx) || !can_scrub_inode(ctx) ||
            !can_scrub_bmap(ctx) || !can_scrub_dir(ctx) ||
index f5b58de128123d1c4e2802ceac2632be69ebd138..3e7d9138f97ec20b9f9538d39aefa213ac9e8f30 100644 (file)
@@ -526,6 +526,10 @@ _("Scrub aborted after phase %d."),
                if (ret)
                        break;
 
+               /* Did background scrub get canceled on us? */
+               if (ctx->mode == SCRUB_MODE_NONE)
+                       break;
+
                /* Too many errors? */
                if (scrub_excessive_errors(ctx)) {
                        ret = ECANCELED;
@@ -630,12 +634,14 @@ report_outcome(
 enum o_opt_nums {
        IWARN = 0,
        FSTRIM_PCT,
+       AUTOFSCK,
        O_MAX_OPTS,
 };
 
 static char *o_opts[] = {
        [IWARN]                 = "iwarn",
        [FSTRIM_PCT]            = "fstrim_pct",
+       [AUTOFSCK]              = "autofsck",
        [O_MAX_OPTS]            = NULL,
 };
 
@@ -688,6 +694,14 @@ parse_o_opts(
 
                        ctx->fstrim_block_pct = dval / 100.0;
                        break;
+               case AUTOFSCK:
+                       if (val) {
+                               fprintf(stderr,
+ _("-o autofsck does not take an argument\n"));
+                               usage();
+                       }
+                       ctx->mode = SCRUB_MODE_NONE;
+                       break;
                default:
                        usage();
                        break;
index 4d9a028921b55e52bcfadf51907457392cea5a3e..5d336cb55c742255b3879b0116d6f775fa4f7848 100644 (file)
@@ -26,6 +26,13 @@ extern bool                  use_force_rebuild;
 extern bool                    info_is_warning;
 
 enum scrub_mode {
+       /*
+        * Prior to phase 1, this means that xfs_scrub should read the
+        * "autofsck" fs property from the mount and set the value
+        * appropriate.  If it's still set after phase 1, this means we should
+        * exit without doing anything.
+        */
+       SCRUB_MODE_NONE,
        SCRUB_MODE_DRY_RUN,
        SCRUB_MODE_PREEN,
        SCRUB_MODE_REPAIR,