]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: allow queued realtime intents to drain before scrubbing
authorDarrick J. Wong <djwong@kernel.org>
Thu, 15 Aug 2024 18:57:34 +0000 (11:57 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 16 Aug 2024 21:57:40 +0000 (14:57 -0700)
Source kernel commit: 77b81645574605ea0c0199ec32fc4a9cdc87bc53

When a writer thread executes a chain of log intent items for the
realtime volume, the ILOCKs taken during each step are for each rt
metadata file, not the entire rt volume itself.  Although scrub takes
all rt metadata ILOCKs, this isn't sufficient to guard against scrub
checking the rt volume while that writer thread is in the middle of
finishing a chain because there's no higher level locking primitive
guarding the realtime volume.

When there's a collision, cross-referencing between data structures
(e.g. rtrmapbt and rtrefcountbt) yields false corruption events; if
repair is running, this results in incorrect repairs, which is
catastrophic.

Fix this by adding to the mount structure the same drain that we use to
protect scrub against concurrent AG updates, but this time for the
realtime volume.

[Contains a few cleanups from hch]

Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
libxfs/xfs_rtgroup.c
libxfs/xfs_rtgroup.h

index b16e1467ac58976b2207b9f22fca77706c74c327..5b24e0614fd704f05753b41ca1654d0b4415ecf5 100644 (file)
@@ -142,6 +142,7 @@ xfs_rtgroup_alloc(
        /* Place kernel structure only init below this point. */
        spin_lock_init(&rtg->rtg_state_lock);
        init_waitqueue_head(&rtg->rtg_active_wq);
+       xfs_defer_drain_init(&rtg->rtg_intents_drain);
 #endif /* __KERNEL__ */
 
        /* Active ref owned by mount indicates rtgroup is online. */
@@ -169,6 +170,10 @@ xfs_rtgroup_free(
 
        XFS_IS_CORRUPT(mp, atomic_read(&rtg->rtg_ref) != 0);
 
+#ifdef __KERNEL__
+       xfs_defer_drain_free(&rtg->rtg_intents_drain);
+#endif
+
        /* drop the mount's active reference */
        xfs_rtgroup_rele(rtg);
        XFS_IS_CORRUPT(mp, atomic_read(&rtg->rtg_active_ref) != 0);
index c2addd4e109eae3d5e9e9b6055a1d6c8fb3a1dfc..aad16b0ec28ad248836d21aaaeced8ff44fb3cfe 100644 (file)
@@ -56,6 +56,15 @@ struct xfs_rtgroup {
 #ifdef __KERNEL__
        /* -- kernel only structures below this line -- */
        spinlock_t              rtg_state_lock;
+
+       /*
+        * We use xfs_drain to track the number of deferred log intent items
+        * that have been queued (but not yet processed) so that waiters (e.g.
+        * scrub) will not lock resources when other threads are in the middle
+        * of processing a chain of intent items only to find momentary
+        * inconsistencies.
+        */
+       struct xfs_defer_drain  rtg_intents_drain;
 #endif /* __KERNEL__ */
 };