From: Darrick J. Wong Date: Tue, 30 Jun 2026 17:12:02 +0000 (-0700) Subject: xfs_scrub: fix spacemap scan for internal rt devices X-Git-Tag: v7.1.0~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=074c18165ea339a9dc81ecf73413c5c7ba3608d3;p=xfsprogs-dev.git xfs_scrub: fix spacemap scan for internal rt devices 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: # v6.15.0 Fixes: 37591ef3f4f14c ("xfs_scrub: support internal RT device") Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig [aalbersh: squashed with accidentally split patch] --- diff --git a/scrub/spacemap.c b/scrub/spacemap.c index 45ac61d0..26d05163 100644 --- a/scrub/spacemap.c +++ b/scrub/spacemap.c @@ -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;