Add new fcntl F_GET_MAX_WRITE_STREAMS. This returns the numbers of streams that are available for userspace. And for that, use ->user_write_streams() callback when the involved filesystem provides it. In absence of such callback, use 'max_write_streams' queue limit of the underlying block device. Signed-off-by: Kanchan Joshi <joshi.k@xxxxxxxxxxx> --- fs/fcntl.c | 31 +++++++++++++++++++++++++++++++ include/uapi/linux/fcntl.h | 5 +++++ 2 files changed, 36 insertions(+) diff --git a/fs/fcntl.c b/fs/fcntl.c index 5598e4d57422..36ca833e9a0b 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -27,6 +27,7 @@ #include <linux/compat.h> #include <linux/mount.h> #include <linux/rw_hint.h> +#include <linux/blkdev.h> #include <linux/poll.h> #include <asm/siginfo.h> @@ -394,6 +395,33 @@ static long fcntl_set_rw_hint(struct file *file, unsigned int cmd, return 0; } +static u8 vfs_user_write_streams(struct inode *inode) +{ + struct super_block *sb; + + if (S_ISBLK(inode->i_mode)) + return bdev_max_write_streams(I_BDEV(inode)); + + sb = inode->i_sb; + /* If available, use per-mount/fs policy */ + if (sb->s_op && sb->s_op->user_write_streams) + return sb->s_op->user_write_streams(sb); + /* otherwise, fallback to queue limit */ + if (sb->s_bdev) + return bdev_max_write_streams(sb->s_bdev); + return 0; +} + +static long fcntl_get_max_write_streams(struct file *file) +{ + struct inode *inode = file_inode(file); + + if (S_ISBLK(inode->i_mode)) + inode = file->f_mapping->host; + + return vfs_user_write_streams(inode); +} + /* Is the file descriptor a dup of the file? */ static long f_dupfd_query(int fd, struct file *filp) { @@ -552,6 +580,9 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, case F_SET_RW_HINT: err = fcntl_set_rw_hint(filp, cmd, arg); break; + case F_GET_MAX_WRITE_STREAMS: + err = fcntl_get_max_write_streams(filp); + break; default: break; } diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h index f291ab4f94eb..87ec808d0f03 100644 --- a/include/uapi/linux/fcntl.h +++ b/include/uapi/linux/fcntl.h @@ -61,6 +61,11 @@ #define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13) #define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14) +/* + * Query available write streams + */ +#define F_GET_MAX_WRITE_STREAMS (F_LINUX_SPECIFIC_BASE + 15) + /* * Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be * used to clear any hints previously set. -- 2.25.1