From: Darrick J. Wong Date: Sun, 22 Feb 2026 22:41:15 +0000 (-0800) Subject: xfs_healer: use the autofsck fsproperty to select mode X-Git-Tag: v7.0.0~41 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=bf8b99270c6be130aa9685e669abd81ef4282ed8;p=xfsprogs-dev.git xfs_healer: use the autofsck fsproperty to select mode Make the xfs_healer background service query the autofsck filesystem property to figure out which operating mode it should use. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- diff --git a/healer/xfs_healer.c b/healer/xfs_healer.c index cf26f9c0..95e952ed 100644 --- a/healer/xfs_healer.c +++ b/healer/xfs_healer.c @@ -6,6 +6,7 @@ #include "xfs.h" #include #include +#include #include "platform_defs.h" #include "libfrog/fsgeom.h" @@ -13,6 +14,7 @@ #include "libfrog/healthevent.h" #include "libfrog/workqueue.h" #include "libfrog/systemd.h" +#include "libfrog/fsproperties.h" #include "xfs_healer.h" /* Program name; needed for libfrog error reports. */ @@ -195,6 +197,63 @@ healer_nproc( return ctx->foreground ? platform_nproc() : 1; } +enum want_repair { + WR_REPAIR, + WR_LOG_ONLY, + WR_EXIT, +}; + +/* Determine want_repair from the autofsck filesystem property. */ +static enum want_repair +want_repair_from_autofsck( + struct healer_ctx *ctx) +{ + char valuebuf[FSPROP_MAX_VALUELEN + 1] = { 0 }; + enum fsprop_autofsck shval; + ssize_t ret; + + /* + * Any OS error (including ENODATA) or string parsing error is treated + * the same as an unrecognized value. + */ + ret = fgetxattr(ctx->mnt.fd, VFS_FSPROP_AUTOFSCK_NAME, valuebuf, + FSPROP_MAX_VALUELEN); + if (ret < 0) + goto no_advice; + + shval = fsprop_autofsck_read(valuebuf); + switch (shval) { + case FSPROP_AUTOFSCK_NONE: + /* don't run at all */ + ret = WR_EXIT; + break; + case FSPROP_AUTOFSCK_CHECK: + case FSPROP_AUTOFSCK_OPTIMIZE: + /* log events, do not repair */ + ret = WR_LOG_ONLY; + break; + case FSPROP_AUTOFSCK_REPAIR: + /* repair stuff */ + ret = WR_REPAIR; + break; + case FSPROP_AUTOFSCK_UNSET: + goto no_advice; + } + + return ret; + +no_advice: + /* + * For an unrecognized value, log but do not fix runtime corruption if + * backref metadata are enabled. If no backref metadata are available, + * the fs is too old so don't run at all. + */ + if (healer_has_rmapbt(ctx) || healer_has_parent(ctx)) + return WR_LOG_ONLY; + + return WR_EXIT; +} + enum mon_state { MON_START, MON_EXIT, @@ -225,14 +284,46 @@ setup_monitor( goto out_mnt_fd; } - if (ctx->want_repair) { - /* Check that the kernel supports repairs at all. */ - if (!healer_can_repair(ctx)) { + if (ctx->autofsck) { + switch (want_repair_from_autofsck(ctx)) { + case WR_EXIT: + printf("%s: %s\n", ctx->mntpoint, + _("Disabling daemon per autofsck directive.")); + fflush(stdout); + close(ctx->mnt.fd); + return MON_UNSUPPORTED; + case WR_REPAIR: + ctx->want_repair = 1; + printf("%s: %s\n", ctx->mntpoint, + _("Automatically repairing per autofsck directive.")); + fflush(stdout); + break; + case WR_LOG_ONLY: + ctx->want_repair = 0; + if (ctx->log != 0) { + printf("%s: %s\n", ctx->mntpoint, + _("Only logging errors per autofsck directive.")); + fflush(stdout); + } + break; + } + } + + /* Check that the kernel supports repairs at all. */ + if (ctx->want_repair && !healer_can_repair(ctx)) { + if (!ctx->autofsck) { fprintf(stderr, "%s: %s\n", ctx->mntpoint, _("XFS online repair is not supported, exiting")); goto out_mnt_fd; } + printf("%s: %s\n", ctx->mntpoint, + _("XFS online repair is not supported, will report only")); + fflush(stdout); + ctx->want_repair = 0; + } + + if (ctx->want_repair) { /* Check for backref metadata that makes repair effective. */ if (!healer_has_rmapbt(ctx)) fprintf(stderr, "%s: %s\n", ctx->mntpoint, @@ -429,6 +520,7 @@ usage(void) fprintf(stderr, _(" --debug Enable debugging messages.\n")); fprintf(stderr, _(" --everything Capture all events.\n")); fprintf(stderr, _(" --foreground Process events as soon as possible.\n")); + fprintf(stderr, _(" --no-autofsck Do not use the \"autofsck\" fs property to decide to repair.\n")); fprintf(stderr, _(" --quiet Do not log health events to stdout.\n")); fprintf(stderr, _(" --repair Repair corrupt metadata found at runtime.\n")); fprintf(stderr, _(" --supported Check that health monitoring is supported.\n")); @@ -442,6 +534,7 @@ enum long_opt_nr { LOPT_EVERYTHING, LOPT_FOREGROUND, LOPT_HELP, + LOPT_NO_AUTOFSCK, LOPT_QUIET, LOPT_REPAIR, LOPT_SUPPORTED, @@ -459,6 +552,7 @@ main( .conlock = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER, .log = 1, .mnt.fd = -1, + .autofsck = 1, }; int option_index; int vflag = 0; @@ -475,6 +569,7 @@ main( [LOPT_EVERYTHING] = {"everything", no_argument, &ctx.everything, 1 }, [LOPT_FOREGROUND] = {"foreground", no_argument, &ctx.foreground, 1 }, [LOPT_HELP] = {"help", no_argument, NULL, 0 }, + [LOPT_NO_AUTOFSCK] = {"no-autofsck", no_argument, &ctx.autofsck, 0 }, [LOPT_QUIET] = {"quiet", no_argument, &ctx.log, 0 }, [LOPT_REPAIR] = {"repair", no_argument, &ctx.want_repair, 1 }, [LOPT_SUPPORTED] = {"supported", no_argument, &ctx.support_check, 1 }, @@ -512,6 +607,8 @@ main( if (optind != argc - 1) usage(); + if (ctx.want_repair) + ctx.autofsck = 0; ctx.mntpoint = argv[optind]; diff --git a/healer/xfs_healer.h b/healer/xfs_healer.h index 7caa6c66..a2a46053 100644 --- a/healer/xfs_healer.h +++ b/healer/xfs_healer.h @@ -28,6 +28,7 @@ struct healer_ctx { int want_repair; int print_svcname; int support_check; + int autofsck; /* fd and fs geometry for mount */ struct xfs_fd mnt; diff --git a/libfrog/fsproperties.h b/libfrog/fsproperties.h index 11d6530b..1cf90d05 100644 --- a/libfrog/fsproperties.h +++ b/libfrog/fsproperties.h @@ -52,6 +52,11 @@ bool fsprop_validate(const char *name, const char *value); #define FSPROP_AUTOFSCK_NAME "autofsck" +/* filesystem property name for fgetxattr */ +#define VFS_FSPROP_AUTOFSCK_NAME (FSPROP_NAMESPACE \ + FSPROP_NAME_PREFIX \ + FSPROP_AUTOFSCK_NAME) + enum fsprop_autofsck { FSPROP_AUTOFSCK_UNSET = 0, /* do not set property */ FSPROP_AUTOFSCK_NONE, /* no background scrubs */