xfs: allow internal RT devices for zoned mode

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 <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
This commit is contained in:
Christoph Hellwig 2024-11-17 08:53:10 +01:00
parent 2167eaabe2
commit bdc03eb5f9
8 changed files with 34 additions and 9 deletions

View file

@ -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

View file

@ -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;

View file

@ -1204,6 +1204,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;

View file

@ -150,7 +150,7 @@ xfs_file_fsync(
* ensure newly written file data make it to disk before logging the new
* inode size in case of an extending write.
*/
if (XFS_IS_REALTIME_INODE(ip))
if (XFS_IS_REALTIME_INODE(ip) && mp->m_rtdev_targp != mp->m_ddev_targp)
error = blkdev_issue_flush(mp->m_rtdev_targp->bt_bdev);
else if (mp->m_logdev_targp != mp->m_ddev_targp)
error = blkdev_issue_flush(mp->m_ddev_targp->bt_bdev);

View file

@ -308,6 +308,10 @@ xfs_growfs_data(
if (!mutex_trylock(&mp->m_growlock))
return -EWOULDBLOCK;
/* we can't grow the data section when an internal RT section exists */
if (in->newblocks != mp->m_sb.sb_dblocks && mp->m_sb.sb_rtstart)
return -EINVAL;
/* update imaxpct separately to the physical grow of the filesystem */
if (in->imaxpct != mp->m_sb.sb_imax_pct) {
error = xfs_growfs_imaxpct(mp, in->imaxpct);

View file

@ -103,6 +103,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;
};
struct xfs_freecounter {

View file

@ -1266,7 +1266,8 @@ xfs_rt_check_size(
return -EFBIG;
}
error = xfs_buf_read_uncached(mp->m_rtdev_targp, daddr,
error = xfs_buf_read_uncached(mp->m_rtdev_targp,
XFS_FSB_TO_BB(mp, mp->m_sb.sb_rtstart) + daddr,
XFS_FSB_TO_BB(mp, 1), 0, &bp, NULL);
if (error)
xfs_warn(mp, "cannot read last RT device sector (%lld)",

View file

@ -533,7 +533,15 @@ xfs_setup_devices(
if (error)
return error;
}
if (mp->m_rtdev_targp) {
if (mp->m_sb.sb_rtstart) {
if (mp->m_rtdev_targp) {
xfs_warn(mp,
"can't use internal and external rtdev at the same time");
return -EINVAL;
}
mp->m_rtdev_targp = mp->m_ddev_targp;
} else if (mp->m_rtname) {
error = xfs_setsize_buftarg(mp->m_rtdev_targp,
mp->m_sb.sb_sectsize);
if (error)
@ -757,7 +765,7 @@ xfs_mount_free(
{
if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
xfs_free_buftarg(mp->m_logdev_targp);
if (mp->m_rtdev_targp)
if (mp->m_rtdev_targp && mp->m_rtdev_targp != mp->m_ddev_targp)
xfs_free_buftarg(mp->m_rtdev_targp);
if (mp->m_ddev_targp)
xfs_free_buftarg(mp->m_ddev_targp);