[PATCH 5/6] xfs: adjust datadev sector count to reflect internal rt volumes
"Darrick J. Wong" <[email protected]> Wed, 29 Jul 2026 22:27:20 -0700
| Newsgroups | org.kernel.vger.linux-xfs,org.kernel.vger.stable |
|---|---|
| Message-ID | <178538912986.4070956.14205556423461124701.stgit@frogsfrogsfrogs> |
From: Darrick J. Wong <[email protected]> A media scan of a filesystem containing an internal rt volume produced an error in xfs_scrub phase 6 complaining about a truncated realtime device. The rt device wasn't truncated, but the media scan code thought we were trying to start a scan past the end of m_rtdev_targp. That in turn is an alias for m_ddev_targp, but in xfs_configure_buftarg we set nr_sectors to the size of the data section. Oops. On these filesystems, the internal rt section comes immediately after the data section. We need to set the sector count for the data device buftarg to the size of both sections. Without this, media scans don't work and media failure notifications from the kernel will be discarded silently. We also need to fix the superblock buffer recovery code to do the same. Cc: <[email protected]> # v6.15 Fixes: bdc03eb5f98f6f ("xfs: allow internal RT devices for zoned mode") Signed-off-by: "Darrick J. Wong" <[email protected]> --- fs/xfs/xfs_buf_item_recover.c | 12 ++++++++++-- fs/xfs/xfs_super.c | 11 ++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_buf_item_recover.c b/fs/xfs/xfs_buf_item_recover.c index 02b95b89d1b597..140b1c16ea15c3 100644 --- a/fs/xfs/xfs_buf_item_recover.c +++ b/fs/xfs/xfs_buf_item_recover.c @@ -720,6 +720,7 @@ xlog_recover_do_primary_sb_buffer( xfs_lsn_t current_lsn) { struct xfs_dsb *dsb = bp->b_addr; + xfs_rfsblock_t dblocks; xfs_agnumber_t orig_agcount = mp->m_sb.sb_agcount; xfs_rgnumber_t orig_rgcount = mp->m_sb.sb_rgcount; int error; @@ -738,9 +739,16 @@ xlog_recover_do_primary_sb_buffer( /* * Grow can change the device size. Mirror that into the buftarg. + * + * Internal rt volumes are placed immediately after the data device, + * so set the buftarg sector count to the end of the rt volume so that + * we can do media scans and handle media failure reports. */ - mp->m_ddev_targp->bt_nr_sectors = - XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); + if (mp->m_sb.sb_rtstart) + dblocks = mp->m_sb.sb_rtstart + mp->m_sb.sb_rblocks; + else + dblocks = mp->m_sb.sb_dblocks; + mp->m_ddev_targp->bt_nr_sectors = XFS_FSB_TO_BB(mp, dblocks); if (mp->m_rtdev_targp && mp->m_rtdev_targp != mp->m_ddev_targp) { mp->m_rtdev_targp->bt_nr_sectors = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks); diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 8531d526fc4409..9898cd9db0ada6 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -555,10 +555,19 @@ STATIC int xfs_setup_devices( struct xfs_mount *mp) { + xfs_rfsblock_t dblocks = mp->m_sb.sb_dblocks; int error; + /* + * Internal rt volumes are placed immediately after the data device, + * so set the buftarg sector count to the end of the rt volume so that + * we can do media scans and handle media failure reports. + */ + if (mp->m_sb.sb_rtstart) + dblocks = mp->m_sb.sb_rtstart + mp->m_sb.sb_rblocks; + error = xfs_configure_buftarg(mp->m_ddev_targp, mp->m_sb.sb_sectsize, - mp->m_sb.sb_dblocks); + dblocks); if (error) return error;