]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_scrub: fix spacemap scan for internal rt devices
authorDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jun 2026 17:12:02 +0000 (10:12 -0700)
committerAndrey Albershteyn <aalbersh@kernel.org>
Wed, 8 Jul 2026 08:40:23 +0000 (10:40 +0200)
The scrub media scan on a filesystem with an internal rt volume still
fails with:

 # xfs_scrub -dTvnx /mnt
 Phase 6: Verify data file integrity.
 Error: dev 7:0 rtgroup 1 fsmap: Invalid argument. (spacemap.c line 162)
 Error: dev 7:0 rtgroup 0 fsmap: Invalid argument. (spacemap.c line 162)
 Info: /mnt: Scrub aborted after phase 6. (xfs_scrub.c line 522)

(this was from xfs/586)

When I tried to add support for internal rt devices in commit
37591ef3f4f14c ("xfs_scrub: support internal RT device"), I forgot that
fsmap reports physical offsets into the underlying block device, and
therefore expects the query keys to reflect that.  Put another way, to
scan a single rtgroup, one must add @rtstart to the fmr_physical field
of the query keys.

This hasn't been reported until now because we inadvertently also
disabled spacemap scans of internal rt volumes until commit
3e4bb144f657b1 ("xfs_scrub: handle media scans of internal rt devices
correctly").

Cc: <linux-xfs@vger.kernel.org> # v6.15.0
Fixes: 37591ef3f4f14c ("xfs_scrub: support internal RT device")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
[aalbersh: squashed with accidentally split patch]

scrub/spacemap.c

index 45ac61d0942ccb1e334a58771684a173f7e23001..26d05163bde9714ee475914a69c216b3ab9f269a 100644 (file)
@@ -111,6 +111,19 @@ scan_ag_rmaps(
        keys[1].fmr_offset = ULLONG_MAX;
        keys[1].fmr_flags = UINT_MAX;
 
+       /*
+        * fsmap for an internal rt volume treats physical ranges as offsets
+        * into the underlying block device.  Shift the query range up by
+        * @rtstart here to skip the synthetic "internal filesystem" fsmap.
+        */
+       if (ctx->mnt.fsgeom.rtstart) {
+               uint64_t        offset = ctx->mnt.fsgeom.rtstart *
+                                        ctx->mnt.fsgeom.blocksize;
+
+               keys[0].fmr_physical += offset;
+               keys[1].fmr_physical += offset;
+       }
+
        if (sbx->aborted)
                return;
 
@@ -148,6 +161,19 @@ scan_rtg_rmaps(
        keys[1].fmr_offset = ULLONG_MAX;
        keys[1].fmr_flags = UINT_MAX;
 
+       /*
+        * fsmap for an internal rt volume treats physical ranges as offsets
+        * into the underlying block device.  Shift the query range up by
+        * @rtstart here to skip the synthetic "internal filesystem" fsmap.
+        */
+       if (ctx->mnt.fsgeom.rtstart) {
+               uint64_t        offset = ctx->mnt.fsgeom.rtstart *
+                                        ctx->mnt.fsgeom.blocksize;
+
+               keys[0].fmr_physical += offset;
+               keys[1].fmr_physical += offset;
+       }
+
        if (sbx->aborted)
                return;