]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: add rtgroup-based realtime scrubbing context management
authorDarrick J. Wong <djwong@kernel.org>
Wed, 29 May 2024 04:11:09 +0000 (21:11 -0700)
committerChristoph Hellwig <hch@lst.de>
Tue, 6 Aug 2024 13:02:49 +0000 (06:02 -0700)
Create a pair of helpers to deal with setting up the necessary incore
context to check metadata records against the realtime metadata.  Right
now this is limited to locking the realtime bitmap and summary inodes,
but as we add rmap and reflink to the realtime device this will grow to
include btree cursors.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/scrub/common.c
fs/xfs/scrub/common.h
fs/xfs/scrub/scrub.c
fs/xfs/scrub/scrub.h

index 5245943496c8b0deada0baa1fd83a2808602ca45..8d44f18787c42c2443efb6c4f1c306978d76757f 100644 (file)
@@ -34,6 +34,7 @@
 #include "xfs_quota.h"
 #include "xfs_exchmaps.h"
 #include "xfs_rtbitmap.h"
+#include "xfs_rtgroup.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
 #include "scrub/trace.h"
@@ -121,6 +122,17 @@ xchk_process_error(
                        XFS_SCRUB_OFLAG_CORRUPT, __return_address);
 }
 
+bool
+xchk_process_rt_error(
+       struct xfs_scrub        *sc,
+       xfs_rgnumber_t          rgno,
+       xfs_rgblock_t           rgbno,
+       int                     *error)
+{
+       return __xchk_process_error(sc, rgno, rgbno, error,
+                       XFS_SCRUB_OFLAG_CORRUPT, __return_address);
+}
+
 bool
 xchk_xref_process_error(
        struct xfs_scrub        *sc,
@@ -684,6 +696,72 @@ xchk_ag_init(
        return 0;
 }
 
+#ifdef CONFIG_XFS_RT
+/*
+ * For scrubbing a realtime group, grab all the in-core resources we'll need to
+ * check the metadata, which means taking the ILOCK of the realtime group's
+ * metadata inodes.  Callers must not join these inodes to the transaction with
+ * non-zero lockflags or concurrency problems will result.  The @rtglock_flags
+ * argument takes XFS_RTGLOCK_* flags.
+ */
+int
+xchk_rtgroup_init(
+       struct xfs_scrub        *sc,
+       xfs_rgnumber_t          rgno,
+       struct xchk_rt          *sr)
+{
+       ASSERT(sr->rtg == NULL);
+       ASSERT(sr->rtlock_flags == 0);
+
+       sr->rtg = xfs_rtgroup_get(sc->mp, rgno);
+       if (!sr->rtg)
+               return -ENOENT;
+       return 0;
+}
+
+void
+xchk_rtgroup_lock(
+       struct xchk_rt          *sr,
+       unsigned int            rtglock_flags)
+{
+       xfs_rtgroup_lock(sr->rtg, rtglock_flags);
+       sr->rtlock_flags = rtglock_flags;
+}
+
+/*
+ * Unlock the realtime group.  This must be done /after/ committing (or
+ * cancelling) the scrub transaction.
+ */
+static void
+xchk_rtgroup_unlock(
+       struct xchk_rt          *sr)
+{
+       ASSERT(sr->rtg != NULL);
+
+       if (sr->rtlock_flags) {
+               xfs_rtgroup_unlock(sr->rtg, sr->rtlock_flags);
+               sr->rtlock_flags = 0;
+       }
+}
+
+/*
+ * Unlock the realtime group and release its resources.  This must be done
+ * /after/ committing (or cancelling) the scrub transaction.
+ */
+void
+xchk_rtgroup_free(
+       struct xfs_scrub        *sc,
+       struct xchk_rt          *sr)
+{
+       ASSERT(sr->rtg != NULL);
+
+       xchk_rtgroup_unlock(sr);
+
+       xfs_rtgroup_put(sr->rtg);
+       sr->rtg = NULL;
+}
+#endif /* CONFIG_XFS_RT */
+
 /* Per-scrubber setup functions */
 
 void
index 27e5bf8f7c60ba381b90e1d77836410fd70354cf..09a38d8439bfdeeb548f68319162932daea0e54d 100644 (file)
@@ -12,6 +12,8 @@ void xchk_trans_cancel(struct xfs_scrub *sc);
 
 bool xchk_process_error(struct xfs_scrub *sc, xfs_agnumber_t agno,
                xfs_agblock_t bno, int *error);
+bool xchk_process_rt_error(struct xfs_scrub *sc, xfs_rgnumber_t rgno,
+               xfs_rgblock_t rgbno, int *error);
 bool xchk_fblock_process_error(struct xfs_scrub *sc, int whichfork,
                xfs_fileoff_t offset, int *error);
 
@@ -118,6 +120,21 @@ xchk_ag_init_existing(
        return error == -ENOENT ? -EFSCORRUPTED : error;
 }
 
+#ifdef CONFIG_XFS_RT
+
+/* All the locks we need to check an rtgroup. */
+#define XCHK_RTGLOCK_ALL       (XFS_RTGLOCK_BITMAP_SHARED)
+
+int xchk_rtgroup_init(struct xfs_scrub *sc, xfs_rgnumber_t rgno,
+               struct xchk_rt *sr);
+void xchk_rtgroup_lock(struct xchk_rt *sr, unsigned int rtglock_flags);
+void xchk_rtgroup_free(struct xfs_scrub *sc, struct xchk_rt *sr);
+#else
+# define xchk_rtgroup_init(sc, rgno, sr)               (-ENOSYS)
+# define xchk_rtgroup_lock(sc, lockflags)              do { } while (0)
+# define xchk_rtgroup_free(sc, sr)                     do { } while (0)
+#endif /* CONFIG_XFS_RT */
+
 int xchk_ag_read_headers(struct xfs_scrub *sc, xfs_agnumber_t agno,
                struct xchk_ag *sa);
 void xchk_ag_btcur_free(struct xchk_ag *sa);
index 04a7a5944837d7549cb6b3d871bdfb189620904f..fe1b3dfe4848787dec2d6f42a3cac80cf102f10e 100644 (file)
@@ -225,6 +225,8 @@ xchk_teardown(
                        xfs_trans_cancel(sc->tp);
                sc->tp = NULL;
        }
+       if (sc->sr.rtg)
+               xchk_rtgroup_free(sc, &sc->sr);
        if (sc->ip) {
                if (sc->ilock_flags)
                        xchk_iunlock(sc, sc->ilock_flags);
@@ -498,6 +500,14 @@ xchk_validate_inputs(
                break;
        case ST_GENERIC:
                break;
+       case ST_RTGROUP:
+               if (sm->sm_ino || sm->sm_gen)
+                       goto out;
+               if (!xfs_has_rtgroups(mp) && sm->sm_agno != 0)
+                       goto out;
+               if (xfs_has_rtgroups(mp) && sm->sm_agno >= mp->m_sb.sb_rgcount)
+                       goto out;
+               break;
        default:
                goto out;
        }
index c688ff4fc7fc4c5d3344d011b84cd743d4f7ff02..f73c6d0d90a11ab2d13873d2ae3f1688093a8a62 100644 (file)
@@ -74,6 +74,7 @@ enum xchk_type {
        ST_FS,          /* per-FS metadata */
        ST_INODE,       /* per-inode metadata */
        ST_GENERIC,     /* determined by the scrubber */
+       ST_RTGROUP,     /* rtgroup metadata */
 };
 
 struct xchk_meta_ops {
@@ -118,6 +119,15 @@ struct xchk_ag {
        struct xfs_btree_cur    *refc_cur;
 };
 
+/* Inode lock state for the RT volume. */
+struct xchk_rt {
+       /* incore rtgroup, if applicable */
+       struct xfs_rtgroup      *rtg;
+
+       /* XFS_RTGLOCK_* lock state if locked */
+       unsigned int            rtlock_flags;
+};
+
 struct xfs_scrub {
        /* General scrub state. */
        struct xfs_mount                *mp;
@@ -179,6 +189,9 @@ struct xfs_scrub {
 
        /* State tracking for single-AG operations. */
        struct xchk_ag                  sa;
+
+       /* State tracking for realtime operations. */
+       struct xchk_rt                  sr;
 };
 
 /* XCHK state flags grow up from zero, XREP state flags grown down from 2^31 */