Even when the underlying block device does not advertise write streams, XFS can choose do so as write-stream based AG allocation can improve the concurrency and reduce interleaving of concurrent block allocation as well as logical fragmentation. Use a simple 3-tier (low/medium/high) AG count based heuristic to publish streams. This enables logical spatial isolation for standard storage, execluding rotational media and rtvolume. Signed-off-by: Kanchan Joshi --- fs/xfs/xfs_inode.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index e93141d2cd8b..6c26cf03a261 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -44,7 +44,7 @@ #include "xfs_xattr.h" #include "xfs_inode_util.h" #include "xfs_metafile.h" - +#define XFS_MAX_WRITE_STREAMS (32) struct kmem_cache *xfs_inode_cache; int @@ -53,6 +53,8 @@ xfs_inode_max_write_streams( { struct xfs_mount *mp = ip->i_mount; struct block_device *bdev; + int hw_streams, sw_streams; + xfs_agnumber_t nr_ags; if (XFS_IS_REALTIME_INODE(ip)) bdev = mp->m_rtdev_targp ? mp->m_rtdev_targp->bt_bdev : NULL; @@ -62,7 +64,22 @@ xfs_inode_max_write_streams( if (!bdev) return 0; - return bdev_max_write_streams(bdev); + hw_streams = bdev_max_write_streams(bdev); + if (hw_streams > 0) + return hw_streams; + /* fallback to software-only write streams, excluding some cases */ + if (bdev_rot(bdev) || XFS_IS_REALTIME_INODE(ip)) + return 0; + nr_ags = mp->m_sb.sb_agcount; + /* heuristic: 3-tier (large/mid/small) split of AGs into streams */ + if (nr_ags >= 32) + sw_streams = nr_ags / 4; + else if (nr_ags >= 8) + sw_streams = nr_ags / 2; + else + sw_streams = nr_ags; + + return min_t(int, sw_streams, XFS_MAX_WRITE_STREAMS); } uint8_t -- 2.25.1