Add two new fcntls: F_GET_WRITE_STREAM - to query the write-stream on inode F_SET_WRITE_STREAM - to set the write-stream on inode Application should query the available streams by calling F_GET_MAX_WRITE_STREAMS first. If returned value is N, applications can choose any value from 1 to N while setting the stream. Setting the value 0 is not flagged as an error as that implies no stream. But setting a larger value than available streams is rejected. Signed-off-by: Kanchan Joshi <joshi.k@xxxxxxxxxxx> --- fs/fcntl.c | 33 +++++++++++++++++++++++++++++++++ include/uapi/linux/fcntl.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/fs/fcntl.c b/fs/fcntl.c index 36ca833e9a0b..ce89393f8dbf 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -422,6 +422,33 @@ static long fcntl_get_max_write_streams(struct file *file) return vfs_user_write_streams(inode); } +static long fcntl_get_write_stream(struct file *file) +{ + struct inode *inode = file_inode(file); + + if (S_ISBLK(inode->i_mode)) + inode = file->f_mapping->host; + + return inode->i_write_stream; +} + +static long fcntl_set_write_stream(struct file *file, unsigned long arg) +{ + struct inode *inode = file_inode(file); + + if (!inode_owner_or_capable(file_mnt_idmap(file), inode)) + return -EPERM; + + if (S_ISBLK(inode->i_mode)) + inode = file->f_mapping->host; + + if (arg > vfs_user_write_streams(inode)) + return -EINVAL; + + WRITE_ONCE(inode->i_write_stream, arg); + return 0; +} + /* Is the file descriptor a dup of the file? */ static long f_dupfd_query(int fd, struct file *filp) { @@ -583,6 +610,12 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, case F_GET_MAX_WRITE_STREAMS: err = fcntl_get_max_write_streams(filp); break; + case F_GET_WRITE_STREAM: + err = fcntl_get_write_stream(filp); + break; + case F_SET_WRITE_STREAM: + err = fcntl_set_write_stream(filp, arg); + break; default: break; } diff --git a/include/uapi/linux/fcntl.h b/include/uapi/linux/fcntl.h index 87ec808d0f03..dd3c498515ce 100644 --- a/include/uapi/linux/fcntl.h +++ b/include/uapi/linux/fcntl.h @@ -65,6 +65,8 @@ * Query available write streams */ #define F_GET_MAX_WRITE_STREAMS (F_LINUX_SPECIFIC_BASE + 15) +#define F_GET_WRITE_STREAM (F_LINUX_SPECIFIC_BASE + 16) +#define F_SET_WRITE_STREAM (F_LINUX_SPECIFIC_BASE + 17) /* * Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be -- 2.25.1