From 82ef017ee42e0d91e9bfbcc2a364708dac15c741 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Sun, 11 Aug 2024 08:26:01 +0200 Subject: [PATCH] xfs: allow queued realtime intents to drain before scrubbing 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 Signed-off-by: Darrick J. Wong --- fs/xfs/scrub/common.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index 147af633d8b7..daa85708985a 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -753,10 +753,8 @@ xchk_rtgroup_lock( * assume that holding its ILOCK will suffice to coordinate * with any rt intent chains involving this inode. */ - if (sc->ip && !xfs_is_metadata_inode(sc->ip)) { - sr->rtlock_flags = rtglock_flags; - return 0; - } + if (sc->ip && !xfs_is_metadata_inode(sc->ip)) + break; /* * Decide if the rt group is quiet enough for all metadata to @@ -777,21 +775,23 @@ xchk_rtgroup_lock( * Obviously, this should be slanted against scrub and in favor * of runtime threads. */ - if (!xfs_rtgroup_intent_busy(sr->rtg)) { - sr->rtlock_flags = rtglock_flags; - return 0; - } + if (!xfs_rtgroup_intent_busy(sr->rtg)) + break; xfs_rtgroup_unlock(sr->rtg, rtglock_flags); if (!(sc->flags & XCHK_FSGATES_DRAIN)) return -ECHRNG; error = xfs_rtgroup_intent_drain(sr->rtg); - if (error == -ERESTARTSYS) - error = -EINTR; - } while (!error); + if (error) { + if (error == -ERESTARTSYS) + error = -EINTR; + return error; + } + } while (1); - return error; + sr->rtlock_flags = rtglock_flags; + return 0; } /* -- 2.50.1