]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: update health status if we get a clean bill of health
authorDarrick J. Wong <djwong@kernel.org>
Thu, 22 Feb 2024 20:33:04 +0000 (12:33 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 22 Feb 2024 20:33:04 +0000 (12:33 -0800)
If scrub finds that everything is ok with the filesystem, we need a way
to tell the health tracking that it can let go of indirect health flags,
since indirect flags only mean that at some point in the past we lost
some context.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_fs.h
fs/xfs/scrub/health.c
fs/xfs/scrub/health.h
fs/xfs/scrub/repair.c
fs/xfs/scrub/scrub.c
fs/xfs/scrub/trace.h

index b5c8da7e6aa99ad5d8fb6cdd911f457ec3969a9c..ca1b17d014377389ae45d7c96a00420f357d669e 100644 (file)
@@ -714,9 +714,10 @@ struct xfs_scrub_metadata {
 #define XFS_SCRUB_TYPE_FSCOUNTERS 24   /* fs summary counters */
 #define XFS_SCRUB_TYPE_QUOTACHECK 25   /* quota counters */
 #define XFS_SCRUB_TYPE_NLINKS  26      /* inode link counts */
+#define XFS_SCRUB_TYPE_HEALTHY 27      /* everything checked out ok */
 
 /* Number of scrub subcommands. */
-#define XFS_SCRUB_TYPE_NR      27
+#define XFS_SCRUB_TYPE_NR      28
 
 /* i: Repair this metadata. */
 #define XFS_SCRUB_IFLAG_REPAIR         (1u << 0)
index af192b41e78cd83ec482f0c20085217b3298eb82..7878da941c127ed7125ac53e7072d44df43dc259 100644 (file)
@@ -14,6 +14,7 @@
 #include "xfs_health.h"
 #include "scrub/scrub.h"
 #include "scrub/health.h"
+#include "scrub/common.h"
 
 /*
  * Scrub and In-Core Filesystem Health Assessments
@@ -149,6 +150,24 @@ xchk_file_looks_zapped(
        return xfs_inode_has_sickness(sc->ip, mask);
 }
 
+/*
+ * Scrub gave the filesystem a clean bill of health, so clear all the indirect
+ * markers of past problems (at least for the fs and ags) so that we can be
+ * healthy again.
+ */
+STATIC void
+xchk_mark_all_healthy(
+       struct xfs_mount        *mp)
+{
+       struct xfs_perag        *pag;
+       xfs_agnumber_t          agno;
+
+       xfs_fs_mark_healthy(mp, XFS_SICK_FS_INDIRECT);
+       xfs_rt_mark_healthy(mp, XFS_SICK_RT_INDIRECT);
+       for_each_perag(mp, agno, pag)
+               xfs_ag_mark_healthy(pag, XFS_SICK_AG_INDIRECT);
+}
+
 /*
  * Update filesystem health assessments based on what we found and did.
  *
@@ -166,6 +185,18 @@ xchk_update_health(
        struct xfs_perag        *pag;
        bool                    bad;
 
+       /*
+        * The HEALTHY scrub type is a request from userspace to clear all the
+        * indirect flags after a clean scan of the entire filesystem.  As such
+        * there's no sick flag defined for it, so we branch here ahead of the
+        * mask check.
+        */
+       if (sc->sm->sm_type == XFS_SCRUB_TYPE_HEALTHY &&
+           !(sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)) {
+               xchk_mark_all_healthy(sc->mp);
+               return;
+       }
+
        if (!sc->sick_mask)
                return;
 
@@ -285,3 +316,36 @@ xchk_ag_btree_healthy_enough(
 
        return true;
 }
+
+/*
+ * Quick scan to double-check that there isn't any evidence of lingering
+ * primary health problems.  If we're still clear, then the health update will
+ * take care of clearing the indirect evidence.
+ */
+int
+xchk_health_record(
+       struct xfs_scrub        *sc)
+{
+       struct xfs_mount        *mp = sc->mp;
+       struct xfs_perag        *pag;
+       xfs_agnumber_t          agno;
+
+       unsigned int            sick;
+       unsigned int            checked;
+
+       xfs_fs_measure_sickness(mp, &sick, &checked);
+       if (sick & XFS_SICK_FS_PRIMARY)
+               xchk_set_corrupt(sc);
+
+       xfs_rt_measure_sickness(mp, &sick, &checked);
+       if (sick & XFS_SICK_RT_PRIMARY)
+               xchk_set_corrupt(sc);
+
+       for_each_perag(mp, agno, pag) {
+               xfs_ag_measure_sickness(pag, &sick, &checked);
+               if (sick & XFS_SICK_AG_PRIMARY)
+                       xchk_set_corrupt(sc);
+       }
+
+       return 0;
+}
index a731b2467399f630e424af0316c1ddc7e2cea0fc..06d17941776ccf5a5e27d01e73d7998b04402ccb 100644 (file)
@@ -12,5 +12,6 @@ bool xchk_ag_btree_healthy_enough(struct xfs_scrub *sc, struct xfs_perag *pag,
                xfs_btnum_t btnum);
 void xchk_mark_healthy_if_clean(struct xfs_scrub *sc, unsigned int mask);
 bool xchk_file_looks_zapped(struct xfs_scrub *sc, unsigned int mask);
+int xchk_health_record(struct xfs_scrub *sc);
 
 #endif /* __XFS_SCRUB_HEALTH_H__ */
index 7141b17789028171b0ca59edd0a8a7355ad86f4d..ab510cea96d868da26eb96ab13851870a652068c 100644 (file)
@@ -30,6 +30,7 @@
 #include "xfs_errortag.h"
 #include "xfs_error.h"
 #include "xfs_reflink.h"
+#include "xfs_health.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
 #include "scrub/trace.h"
index c0b99184bb3efdeda0ab306f138951a481bb64a7..0f23b7f36d4a50dbb8d1a7d9a16d5e0b747f2c90 100644 (file)
@@ -378,6 +378,12 @@ static const struct xchk_meta_ops meta_scrub_ops[] = {
                .scrub  = xchk_nlinks,
                .repair = xrep_nlinks,
        },
+       [XFS_SCRUB_TYPE_HEALTHY] = {    /* fs healthy; clean all reminders */
+               .type   = ST_FS,
+               .setup  = xchk_setup_fs,
+               .scrub  = xchk_health_record,
+               .repair = xrep_notsupported,
+       },
 };
 
 static int
index c9b6b0e0bf117af57c93520c6665e02a18ceef57..b4e65f148e7b67c63c7b902019ddbec49a0f6ce0 100644 (file)
@@ -69,6 +69,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_PQUOTA);
 TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_FSCOUNTERS);
 TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_QUOTACHECK);
 TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_NLINKS);
+TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_HEALTHY);
 
 #define XFS_SCRUB_TYPE_STRINGS \
        { XFS_SCRUB_TYPE_PROBE,         "probe" }, \
@@ -97,7 +98,8 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_NLINKS);
        { XFS_SCRUB_TYPE_PQUOTA,        "prjquota" }, \
        { XFS_SCRUB_TYPE_FSCOUNTERS,    "fscounters" }, \
        { XFS_SCRUB_TYPE_QUOTACHECK,    "quotacheck" }, \
-       { XFS_SCRUB_TYPE_NLINKS,        "nlinks" }
+       { XFS_SCRUB_TYPE_NLINKS,        "nlinks" }, \
+       { XFS_SCRUB_TYPE_HEALTHY,       "healthy" }
 
 #define XFS_SCRUB_FLAG_STRINGS \
        { XFS_SCRUB_IFLAG_REPAIR,               "repair" }, \