From ea178059ff72c3bccd207c93e0013d2ae2f0df36 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Sun, 22 Feb 2026 14:41:15 -0800 Subject: [PATCH] xfs_healer: don't start service if kernel support unavailable Use ExecCondition= in the system service to check if kernel support for the health monitor is available. If not, we don't want to run the service, have it fail, and generate a bunch of silly log messages. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- healer/xfs_healer.c | 52 ++++++++++++++++++++++++++++------- healer/xfs_healer.h | 1 + healer/xfs_healer@.service.in | 1 + 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/healer/xfs_healer.c b/healer/xfs_healer.c index d9ab53c1..cf26f9c0 100644 --- a/healer/xfs_healer.c +++ b/healer/xfs_healer.c @@ -195,19 +195,27 @@ healer_nproc( return ctx->foreground ? platform_nproc() : 1; } +enum mon_state { + MON_START, + MON_EXIT, + MON_ERROR, + MON_UNSUPPORTED, +}; + /* Set ourselves up to monitor the given mountpoint for health events. */ -static int +static enum mon_state setup_monitor( struct healer_ctx *ctx) { const long BUF_SIZE = sysconf(_SC_PAGE_SIZE) * 2; + enum mon_state outcome = MON_ERROR; int mon_fd; int ret; ret = xfd_open(&ctx->mnt, ctx->mntpoint, O_RDONLY); if (ret) { perror(ctx->mntpoint); - return -1; + return outcome; } ret = try_capture_fsinfo(ctx); @@ -263,6 +271,7 @@ setup_monitor( case EOPNOTSUPP: fprintf(stderr, "%s: %s\n", ctx->mntpoint, _("XFS health monitoring not supported.")); + outcome = MON_UNSUPPORTED; break; case EEXIST: fprintf(stderr, "%s: %s\n", ctx->mntpoint, @@ -278,6 +287,16 @@ setup_monitor( close(ctx->mnt.fd); ctx->mnt.fd = -1; + /* + * At this point, we know that the kernel is capable of repairing the + * filesystem and telling us that it needs repairs. If the user only + * wanted us to check for the capability, we're done. + */ + if (ctx->support_check) { + close(mon_fd); + return MON_EXIT; + } + /* * mon_fp consumes mon_fd. We intentionally leave mon_fp attached to * the context so that we keep the monitoring fd open until we've torn @@ -309,7 +328,7 @@ setup_monitor( } ctx->queue_active = true; - return 0; + return MON_START; out_mon_fp: if (ctx->mon_fp) @@ -322,7 +341,7 @@ out_mnt_fd: if (ctx->mnt.fd >= 0) close(ctx->mnt.fd); ctx->mnt.fd = -1; - return -1; + return outcome; } /* Monitor the given mountpoint for health events. */ @@ -412,6 +431,7 @@ usage(void) fprintf(stderr, _(" --foreground Process events as soon as possible.\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")); fprintf(stderr, _(" -V Print version.\n")); exit(EXIT_FAILURE); @@ -424,6 +444,7 @@ enum long_opt_nr { LOPT_HELP, LOPT_QUIET, LOPT_REPAIR, + LOPT_SUPPORTED, LOPT_SVCNAME, LOPT_MAX, @@ -456,6 +477,7 @@ main( [LOPT_HELP] = {"help", no_argument, NULL, 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 }, [LOPT_SVCNAME] = {"svcname", no_argument, &ctx.print_svcname, 1 }, [LOPT_MAX] = {NULL, 0, NULL, 0 }, @@ -507,14 +529,24 @@ main( return EXIT_SUCCESS; } - ret = setup_monitor(&ctx); - if (ret) - goto out_events; - - ret = monitor(&ctx); + switch (setup_monitor(&ctx)) { + case MON_UNSUPPORTED: + ret = 1; /* condition not met */ + break; + case MON_ERROR: + ret = 255; /* service failed */ + break; + case MON_EXIT: + ret = 0; + break; + case MON_START: + ret = monitor(&ctx); + break; + } -out_events: teardown_monitor(&ctx); free((char *)ctx.fsname); + if (ctx.support_check) + return ret; return systemd_service_exit(ret); } diff --git a/healer/xfs_healer.h b/healer/xfs_healer.h index 679bdc95..7caa6c66 100644 --- a/healer/xfs_healer.h +++ b/healer/xfs_healer.h @@ -27,6 +27,7 @@ struct healer_ctx { int foreground; int want_repair; int print_svcname; + int support_check; /* fd and fs geometry for mount */ struct xfs_fd mnt; diff --git a/healer/xfs_healer@.service.in b/healer/xfs_healer@.service.in index 38525787..53f89cf9 100644 --- a/healer/xfs_healer@.service.in +++ b/healer/xfs_healer@.service.in @@ -17,6 +17,7 @@ RequiresMountsFor=%f [Service] Type=exec Environment=SERVICE_MODE=1 +ExecCondition=@pkg_libexec_dir@/xfs_healer --supported %f ExecStart=@pkg_libexec_dir@/xfs_healer %f SyslogIdentifier=%N -- 2.47.3