From 9840f7e09e2f6c2f263eade74ed6f6d64cf7e689 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 14 Apr 2025 07:35:55 +0200 Subject: [PATCH] xfs: allow internal RT devices for zoned mode Source kernel commit: bdc03eb5f98f6f1ae4bd5e020d1582a23efb7799 Allow creating an RT subvolume on the same device as the main data device. This is mostly used for SMR HDDs where the conventional zones are used for the data device and the sequential write required zones for the zoned RT section. Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Christoph Hellwig --- include/libxfs.h | 6 ++++++ include/xfs_mount.h | 7 +++++++ libxfs/init.c | 13 +++++++++---- libxfs/rdwr.c | 2 ++ libxfs/xfs_group.h | 6 ++++-- libxfs/xfs_rtgroup.h | 8 +++++--- libxfs/xfs_sb.c | 1 + repair/agheader.c | 4 +++- 8 files changed, 37 insertions(+), 10 deletions(-) diff --git a/include/libxfs.h b/include/libxfs.h index 82b34b9d..b968a2b8 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -293,4 +293,10 @@ static inline bool xfs_sb_version_hassparseinodes(struct xfs_sb *sbp) xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_SPINODES); } +static inline bool xfs_sb_version_haszoned(struct xfs_sb *sbp) +{ + return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && + xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_ZONED); +} + #endif /* __LIBXFS_H__ */ diff --git a/include/xfs_mount.h b/include/xfs_mount.h index 7856acfb..bf9ebc25 100644 --- a/include/xfs_mount.h +++ b/include/xfs_mount.h @@ -53,6 +53,13 @@ struct xfs_groups { * rtgroup, so this mask must be 64-bit. */ uint64_t blkmask; + + /* + * Start of the first group in the device. This is used to support a + * RT device following the data device on the same block device for + * SMR hard drives. + */ + xfs_fsblock_t start_fsb; }; /* diff --git a/libxfs/init.c b/libxfs/init.c index 5b45ed34..a186369f 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -560,7 +560,7 @@ libxfs_buftarg_init( progname); exit(1); } - if (xi->rt.dev && + if ((xi->rt.dev || xi->rt.dev == xi->data.dev) && (mp->m_rtdev_targp->bt_bdev != xi->rt.dev || mp->m_rtdev_targp->bt_mount != mp)) { fprintf(stderr, @@ -577,7 +577,11 @@ libxfs_buftarg_init( else mp->m_logdev_targp = libxfs_buftarg_alloc(mp, xi, &xi->log, lfail); - mp->m_rtdev_targp = libxfs_buftarg_alloc(mp, xi, &xi->rt, rfail); + if (!xi->rt.dev || xi->rt.dev == xi->data.dev) + mp->m_rtdev_targp = mp->m_ddev_targp; + else + mp->m_rtdev_targp = libxfs_buftarg_alloc(mp, xi, &xi->rt, + rfail); } /* Compute maximum possible height for per-AG btree types for this fs. */ @@ -978,7 +982,7 @@ libxfs_flush_mount( error = err2; } - if (mp->m_rtdev_targp) { + if (mp->m_rtdev_targp && mp->m_rtdev_targp != mp->m_ddev_targp) { err2 = libxfs_flush_buftarg(mp->m_rtdev_targp, _("realtime device")); if (!error) @@ -1031,7 +1035,8 @@ libxfs_umount( free(mp->m_fsname); mp->m_fsname = NULL; - libxfs_buftarg_free(mp->m_rtdev_targp); + if (mp->m_rtdev_targp != mp->m_ddev_targp) + libxfs_buftarg_free(mp->m_rtdev_targp); if (mp->m_logdev_targp != mp->m_ddev_targp) libxfs_buftarg_free(mp->m_logdev_targp); libxfs_buftarg_free(mp->m_ddev_targp); diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c index 35be785c..f06763b3 100644 --- a/libxfs/rdwr.c +++ b/libxfs/rdwr.c @@ -175,6 +175,8 @@ libxfs_getrtsb( if (!mp->m_rtdev_targp->bt_bdev) return NULL; + ASSERT(!mp->m_sb.sb_rtstart); + error = libxfs_buf_read_uncached(mp->m_rtdev_targp, XFS_RTSB_DADDR, XFS_FSB_TO_BB(mp, 1), 0, &bp, &xfs_rtsb_buf_ops); if (error) diff --git a/libxfs/xfs_group.h b/libxfs/xfs_group.h index 242b0562..a7009611 100644 --- a/libxfs/xfs_group.h +++ b/libxfs/xfs_group.h @@ -107,9 +107,11 @@ xfs_gbno_to_daddr( xfs_agblock_t gbno) { struct xfs_mount *mp = xg->xg_mount; - uint32_t blocks = mp->m_groups[xg->xg_type].blocks; + struct xfs_groups *g = &mp->m_groups[xg->xg_type]; + xfs_fsblock_t fsbno; - return XFS_FSB_TO_BB(mp, (xfs_fsblock_t)xg->xg_gno * blocks + gbno); + fsbno = (xfs_fsblock_t)xg->xg_gno * g->blocks + gbno; + return XFS_FSB_TO_BB(mp, g->start_fsb + fsbno); } static inline uint32_t diff --git a/libxfs/xfs_rtgroup.h b/libxfs/xfs_rtgroup.h index 9c7e03f9..e35d1d79 100644 --- a/libxfs/xfs_rtgroup.h +++ b/libxfs/xfs_rtgroup.h @@ -230,7 +230,8 @@ xfs_rtb_to_daddr( xfs_rgnumber_t rgno = xfs_rtb_to_rgno(mp, rtbno); uint64_t start_bno = (xfs_rtblock_t)rgno * g->blocks; - return XFS_FSB_TO_BB(mp, start_bno + (rtbno & g->blkmask)); + return XFS_FSB_TO_BB(mp, + g->start_fsb + start_bno + (rtbno & g->blkmask)); } static inline xfs_rtblock_t @@ -238,10 +239,11 @@ xfs_daddr_to_rtb( struct xfs_mount *mp, xfs_daddr_t daddr) { - xfs_rfsblock_t bno = XFS_BB_TO_FSBT(mp, daddr); + struct xfs_groups *g = &mp->m_groups[XG_TYPE_RTG]; + xfs_rfsblock_t bno; + bno = XFS_BB_TO_FSBT(mp, daddr) - g->start_fsb; if (xfs_has_rtgroups(mp)) { - struct xfs_groups *g = &mp->m_groups[XG_TYPE_RTG]; xfs_rgnumber_t rgno; uint32_t rgbno; diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index bc84792c..a95d7123 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -1201,6 +1201,7 @@ xfs_sb_mount_rextsize( rgs->blocks = sbp->sb_rgextents * sbp->sb_rextsize; rgs->blklog = mp->m_sb.sb_rgblklog; rgs->blkmask = xfs_mask32lo(mp->m_sb.sb_rgblklog); + rgs->start_fsb = mp->m_sb.sb_rtstart; } else { rgs->blocks = 0; rgs->blklog = 0; diff --git a/repair/agheader.c b/repair/agheader.c index 327ba041..048e6c31 100644 --- a/repair/agheader.c +++ b/repair/agheader.c @@ -485,7 +485,9 @@ secondary_sb_whack( * * size is the size of data which is valid for this sb. */ - if (xfs_sb_version_hasmetadir(sb)) + if (xfs_sb_version_haszoned(sb)) + size = offsetofend(struct xfs_dsb, sb_rtreserved); + else if (xfs_sb_version_hasmetadir(sb)) size = offsetofend(struct xfs_dsb, sb_pad); else if (xfs_sb_version_hasmetauuid(sb)) size = offsetofend(struct xfs_dsb, sb_meta_uuid); -- 2.47.2