]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: scrub the realtime group superblock
authorDarrick J. Wong <djwong@kernel.org>
Thu, 1 Aug 2024 15:17:00 +0000 (17:17 +0200)
committerChristoph Hellwig <hch@lst.de>
Tue, 6 Aug 2024 13:05:17 +0000 (06:05 -0700)
Enable scrubbing of realtime group superblocks.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/Makefile
fs/xfs/libxfs/xfs_fs.h
fs/xfs/scrub/common.h
fs/xfs/scrub/health.c
fs/xfs/scrub/rgsuper.c [new file with mode: 0644]
fs/xfs/scrub/scrub.c
fs/xfs/scrub/scrub.h
fs/xfs/scrub/stats.c
fs/xfs/scrub/trace.h

index 388b5cef48ca5df33fce880a3dc52084c70553c6..56f518e5017fddd97b76d1276b7266c2632ca040 100644 (file)
@@ -190,6 +190,7 @@ xfs-y                               += $(addprefix scrub/, \
 xfs-$(CONFIG_XFS_ONLINE_SCRUB_STATS) += scrub/stats.o
 
 xfs-$(CONFIG_XFS_RT)           += $(addprefix scrub/, \
+                                  rgsuper.o \
                                   rtbitmap.o \
                                   rtsummary.o \
                                   )
index 06e8e18ad4c35017c86bfe0a109e686728d1bf9e..6f493ecf0da15cc38ebbdb153fb9d71eae4907f8 100644 (file)
@@ -736,9 +736,10 @@ struct xfs_scrub_metadata {
 #define XFS_SCRUB_TYPE_HEALTHY 27      /* everything checked out ok */
 #define XFS_SCRUB_TYPE_DIRTREE 28      /* directory tree structure */
 #define XFS_SCRUB_TYPE_METAPATH        29      /* metadata directory tree paths */
+#define XFS_SCRUB_TYPE_RGSUPER 30      /* realtime superblock */
 
 /* Number of scrub subcommands. */
-#define XFS_SCRUB_TYPE_NR      30
+#define XFS_SCRUB_TYPE_NR      31
 
 /*
  * This special type code only applies to the vectored scrub implementation.
index 09a38d8439bfdeeb548f68319162932daea0e54d..213a5378a1d7a1d113b106b0960cecd8d7c2ad5e 100644 (file)
@@ -79,9 +79,11 @@ int xchk_setup_metapath(struct xfs_scrub *sc);
 #ifdef CONFIG_XFS_RT
 int xchk_setup_rtbitmap(struct xfs_scrub *sc);
 int xchk_setup_rtsummary(struct xfs_scrub *sc);
+int xchk_setup_rgsuperblock(struct xfs_scrub *sc);
 #else
 # define xchk_setup_rtbitmap           xchk_setup_nothing
 # define xchk_setup_rtsummary          xchk_setup_nothing
+# define xchk_setup_rgsuperblock       xchk_setup_nothing
 #endif
 #ifdef CONFIG_XFS_QUOTA
 int xchk_ino_dqattach(struct xfs_scrub *sc);
index a0a721ae5763d3ebfac98bdbe68f3f1d1d61f658..3406579db71ebdd930edbca09308d52debcafa68 100644 (file)
@@ -111,6 +111,7 @@ static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = {
        [XFS_SCRUB_TYPE_NLINKS]         = { XHG_FS,  XFS_SICK_FS_NLINKS },
        [XFS_SCRUB_TYPE_DIRTREE]        = { XHG_INO, XFS_SICK_INO_DIRTREE },
        [XFS_SCRUB_TYPE_METAPATH]       = { XHG_FS,  XFS_SICK_FS_METAPATH },
+       [XFS_SCRUB_TYPE_RGSUPER]        = { XHG_RTGROUP, XFS_SICK_RG_SUPER },
 };
 
 /* Return the health status mask for this scrub type. */
diff --git a/fs/xfs/scrub/rgsuper.c b/fs/xfs/scrub/rgsuper.c
new file mode 100644 (file)
index 0000000..cb2c6ee
--- /dev/null
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2022-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_shared.h"
+#include "xfs_format.h"
+#include "xfs_trans_resv.h"
+#include "xfs_mount.h"
+#include "xfs_rtgroup.h"
+#include "scrub/scrub.h"
+#include "scrub/common.h"
+
+/* Set us up with a transaction and an empty context. */
+int
+xchk_setup_rgsuperblock(
+       struct xfs_scrub        *sc)
+{
+       return xchk_trans_alloc(sc, 0);
+}
+
+/* Cross-reference with the other rt metadata. */
+STATIC void
+xchk_rgsuperblock_xref(
+       struct xfs_scrub        *sc)
+{
+       struct xfs_mount        *mp = sc->mp;
+       xfs_rgnumber_t          rgno = sc->sr.rtg->rtg_rgno;
+       xfs_rtblock_t           rtbno;
+
+       if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
+               return;
+
+       rtbno = xfs_rgbno_to_rtb(mp, rgno, 0);
+       xchk_xref_is_used_rt_space(sc, rtbno, 1);
+}
+
+int
+xchk_rgsuperblock(
+       struct xfs_scrub        *sc)
+{
+       xfs_rgnumber_t          rgno = sc->sm->sm_agno;
+       int                     error;
+
+       /*
+        * Only rtgroup 0 has a superblock.  We may someday want to use higher
+        * rgno for other functions, similar to what we do with the primary
+        * super scrub function.
+        */
+       if (rgno != 0)
+               return -ENOENT;
+
+       /*
+        * Grab an active reference to the rtgroup structure.  If we can't get
+        * it, we're racing with something that's tearing down the group, so
+        * signal that the group no longer exists.  Take the rtbitmap in shared
+        * mode so that the group can't change while we're doing things.
+        */
+       error = xchk_rtgroup_init(sc, rgno, &sc->sr);
+       if (error)
+               return error;
+       xchk_rtgroup_lock(&sc->sr, XFS_RTGLOCK_BITMAP_SHARED);
+
+       /*
+        * Since we already validated the rt superblock at mount time, we don't
+        * need to check its contents again.  All we need is to cross-reference.
+        */
+       xchk_rgsuperblock_xref(sc);
+       return 0;
+}
index 8a7e1feb38a448a928e976307c21dc23b452a21f..ec59e601b66cfdd3c0fe5ebed1e3c7128e968673 100644 (file)
@@ -451,6 +451,13 @@ static const struct xchk_meta_ops meta_scrub_ops[] = {
                .has    = xfs_has_metadir,
                .repair = xrep_metapath,
        },
+       [XFS_SCRUB_TYPE_RGSUPER] = {    /* realtime group superblock */
+               .type   = ST_RTGROUP,
+               .setup  = xchk_setup_rgsuperblock,
+               .scrub  = xchk_rgsuperblock,
+               .has    = xfs_has_rtsb,
+               .repair = xrep_notsupported,
+       },
 };
 
 static int
index f73c6d0d90a11ab2d13873d2ae3f1688093a8a62..a7fda3e2b013776459cb4efe1c5ac1345148f2a2 100644 (file)
@@ -273,9 +273,11 @@ int xchk_metapath(struct xfs_scrub *sc);
 #ifdef CONFIG_XFS_RT
 int xchk_rtbitmap(struct xfs_scrub *sc);
 int xchk_rtsummary(struct xfs_scrub *sc);
+int xchk_rgsuperblock(struct xfs_scrub *sc);
 #else
 # define xchk_rtbitmap         xchk_nothing
 # define xchk_rtsummary                xchk_nothing
+# define xchk_rgsuperblock     xchk_nothing
 #endif
 #ifdef CONFIG_XFS_QUOTA
 int xchk_quota(struct xfs_scrub *sc);
index edcd02dc2e62c0dd465fe94095bbc0e9f2d26f96..a476c7b2ab75973ba5bd6754bebd7f493181ecf7 100644 (file)
@@ -81,6 +81,7 @@ static const char *name_map[XFS_SCRUB_TYPE_NR] = {
        [XFS_SCRUB_TYPE_NLINKS]         = "nlinks",
        [XFS_SCRUB_TYPE_DIRTREE]        = "dirtree",
        [XFS_SCRUB_TYPE_METAPATH]       = "metapath",
+       [XFS_SCRUB_TYPE_RGSUPER]        = "rgsuper",
 };
 
 /* Format the scrub stats into a text buffer, similar to pcp style. */
index fe901b9138b4bd97608701fdf903d25b51bca507..d4d0e8ceeeb7b8ebb4a9b9975a34d2ebde514ad4 100644 (file)
@@ -71,6 +71,7 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_HEALTHY);
 TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_DIRTREE);
 TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_BARRIER);
 TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_METAPATH);
+TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_RGSUPER);
 
 #define XFS_SCRUB_TYPE_STRINGS \
        { XFS_SCRUB_TYPE_PROBE,         "probe" }, \
@@ -103,7 +104,8 @@ TRACE_DEFINE_ENUM(XFS_SCRUB_TYPE_METAPATH);
        { XFS_SCRUB_TYPE_HEALTHY,       "healthy" }, \
        { XFS_SCRUB_TYPE_DIRTREE,       "dirtree" }, \
        { XFS_SCRUB_TYPE_BARRIER,       "barrier" }, \
-       { XFS_SCRUB_TYPE_METAPATH,      "metapath" }
+       { XFS_SCRUB_TYPE_METAPATH,      "metapath" }, \
+       { XFS_SCRUB_TYPE_RGSUPER,       "rgsuper" }
 
 #define XFS_SCRUB_FLAG_STRINGS \
        { XFS_SCRUB_IFLAG_REPAIR,               "repair" }, \