Keep the attached stream id in the VFS inode rather than the filesystem's own, so that fcntl_set_rw_hint() can see it. It is a u16 in the 32-bit hole after i_state, so struct inode does not grow. Suggested-by: Christoph Hellwig Suggested-by: Darrick J. Wong Signed-off-by: Kanchan Joshi Signed-off-by: Anuj Gupta --- fs/fcntl.c | 7 +++++++ fs/inode.c | 1 + include/linux/fs.h | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/fcntl.c b/fs/fcntl.c index c158f082f1da..a5439e076197 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -380,7 +380,14 @@ static long fcntl_set_rw_hint(struct file *file, unsigned long arg) if (!rw_hint_valid(hint)) return -EINVAL; + /* keep write stream and write life time hint mutually exclusive */ + spin_lock(&inode->i_lock); + if (hint != WRITE_LIFE_NOT_SET && READ_ONCE(inode->i_write_stream)) { + spin_unlock(&inode->i_lock); + return -EBUSY; + } WRITE_ONCE(inode->i_write_hint, hint); + spin_unlock(&inode->i_lock); /* * file->f_mapping->host may differ from inode. As an example, diff --git a/fs/inode.c b/fs/inode.c index ba7da39be4a3..50b91d449a38 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -246,6 +246,7 @@ int inode_init_always_gfp(struct super_block *sb, struct inode *inode, gfp_t gfp atomic_set(&inode->i_writecount, 0); inode->i_size = 0; inode->i_write_hint = WRITE_LIFE_NOT_SET; + inode->i_write_stream = 0; inode->i_blocks = 0; inode->i_bytes = 0; inode->i_generation = 0; diff --git a/include/linux/fs.h b/include/linux/fs.h index f9d1e05e8ae6..3d9ce4d30cd5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -812,7 +812,7 @@ struct inode { /* Misc */ struct inode_state_flags i_state; - /* 32-bit hole */ + u16 i_write_stream; struct rw_semaphore i_rwsem; unsigned long dirtied_when; /* jiffies of first dirtying */ -- 2.25.1