From: Anuj Gupta Enable write streams on non-zoned realtime volumes that have realtime groups, partitioning RTGs among the streams as the AG side does. Stream based RTG selection applies to the first allocation of a file; later ones keep using the adjacent-allocation hint so the file stays contiguous. Signed-off-by: Anuj Gupta Signed-off-by: Kanchan Joshi --- fs/xfs/xfs_inode.c | 4 ++-- fs/xfs/xfs_ioctl.c | 3 ++- fs/xfs/xfs_rtalloc.c | 27 +++++++++++++++++++++++++++ fs/xfs/xfs_super.c | 7 +++++++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index df0a37c4d68a..c3503fe870ba 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -57,7 +57,7 @@ xfs_inode_max_write_streams( if (xfs_inode_is_filestream(ip)) return 0; - if (XFS_IS_REALTIME_INODE(ip)) + if (XFS_IS_REALTIME_INODE(ip) && xfs_has_zoned(ip->i_mount)) return 0; return write_stream_pool_count(&xfs_inode_buftarg(ip)->bt_stream_pool); } @@ -75,7 +75,7 @@ xfs_inode_set_write_stream( if (!fd_file(f)) return -EBADF; xfs_ilock(ip, XFS_ILOCK_EXCL); - if (XFS_IS_REALTIME_INODE(ip)) { + if (XFS_IS_REALTIME_INODE(ip) && xfs_has_zoned(ip->i_mount)) { error = -EINVAL; goto out_unlock; } diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index bc6957ad06cb..4c0aff34e3c3 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -559,7 +559,8 @@ xfs_ioctl_setattr_xflags( /* refuse a filestream/realtime flag change while a stream is attached */ if (READ_ONCE(VFS_I(ip)->i_write_stream) && - ((fa->fsx_xflags & FS_XFLAG_FILESTREAM) || rtflag)) + ((fa->fsx_xflags & FS_XFLAG_FILESTREAM) || + rtflag != XFS_IS_REALTIME_INODE(ip))) return -EINVAL; if (rtflag != XFS_IS_REALTIME_INODE(ip)) { diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 84efe5a8fb11..a291f1aca6eb 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -2160,6 +2160,28 @@ xfs_rtallocate_align( return 0; } +static xfs_rtblock_t +xfs_bmap_write_stream_rtbno( + struct xfs_inode *ip, + unsigned int stream_id) +{ + struct xfs_mount *mp = ip->i_mount; + unsigned int nr_rtgs = mp->m_sb.sb_rgcount; + unsigned int nr_streams = + write_stream_pool_count(&mp->m_rtdev_targp->bt_stream_pool); + unsigned int set_size = nr_rtgs / nr_streams; + xfs_rgnumber_t start_rgno, target_rgno; + + stream_id -= 1; /* convert from 1-based to 0-based */ + start_rgno = stream_id * set_size; + if (stream_id == nr_streams - 1) + set_size = nr_rtgs - start_rgno; + target_rgno = start_rgno + I_INO(ip) % set_size; + + return (xfs_rtblock_t)target_rgno << + mp->m_groups[XG_TYPE_RTG].blklog; +} + int xfs_bmap_rtalloc( struct xfs_bmalloca *ap) @@ -2174,10 +2196,13 @@ xfs_bmap_rtalloc( bool noalign = false; bool initial_user_data = ap->datatype & XFS_ALLOC_INITIAL_USER_DATA; + unsigned int stream_id; int error; ASSERT(!xfs_has_zoned(ap->tp->t_mountp)); + stream_id = READ_ONCE(VFS_I(ap->ip)->i_write_stream); + retry: error = xfs_rtallocate_align(ap, &ralen, &raminlen, &prod, &noalign); if (error) @@ -2185,6 +2210,8 @@ xfs_bmap_rtalloc( if (xfs_bmap_adjacent(ap)) bno_hint = ap->blkno; + else if (stream_id && xfs_has_rtgroups(ap->ip->i_mount)) + bno_hint = xfs_bmap_write_stream_rtbno(ap->ip, stream_id); if (xfs_has_rtgroups(ap->ip->i_mount)) { error = xfs_rtallocate_rtgs(ap->tp, bno_hint, raminlen, ralen, diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 443b3d847150..5c92f8ebd8a7 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -637,6 +637,13 @@ xfs_setup_devices( if (error) return error; xfs_update_bdi_rahead(mp); + + if (xfs_has_rtgroups(mp) && !xfs_has_zoned(mp)) { + error = xfs_buftarg_init_streams(mp->m_rtdev_targp, + mp->m_sb.sb_rgcount); + if (error) + return error; + } } return 0; -- 2.25.1