Restore support for F_GET_FILE_RW_HINT and F_SET_FILE_RW_HINT by reverting commit 7b12e49669c9 ("fs: remove fs.f_write_hint"). Cc: Christoph Hellwig <hch@xxxxxx> Cc: Dave Chinner <dchinner@xxxxxxxxxx> Signed-off-by: Bart Van Assche <bvanassche@xxxxxxx> --- fs/fcntl.c | 18 ++++++++++++++++++ fs/open.c | 1 + include/linux/fs.h | 9 +++++++++ 3 files changed, 28 insertions(+) diff --git a/fs/fcntl.c b/fs/fcntl.c index e871009f6c88..acaa49fb1a35 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -292,6 +292,22 @@ static long fcntl_rw_hint(struct file *file, unsigned int cmd, u64 h; switch (cmd) { + case F_GET_FILE_RW_HINT: + h = file_write_hint(file); + if (copy_to_user(argp, &h, sizeof(*argp))) + return -EFAULT; + return 0; + case F_SET_FILE_RW_HINT: + if (copy_from_user(&h, argp, sizeof(h))) + return -EFAULT; + hint = (enum rw_hint) h; + if (!rw_hint_valid(hint)) + return -EINVAL; + + spin_lock(&file->f_lock); + file->f_write_hint = hint; + spin_unlock(&file->f_lock); + return 0; case F_GET_RW_HINT: h = inode->i_write_hint; if (copy_to_user(argp, &h, sizeof(*argp))) @@ -417,6 +433,8 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, break; case F_GET_RW_HINT: case F_SET_RW_HINT: + case F_GET_FILE_RW_HINT: + case F_SET_FILE_RW_HINT: err = fcntl_rw_hint(filp, cmd, arg); break; default: diff --git a/fs/open.c b/fs/open.c index 98f6601fbac6..9e31b8c50cc4 100644 --- a/fs/open.c +++ b/fs/open.c @@ -942,6 +942,7 @@ static int do_dentry_open(struct file *f, if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO) f->f_mode |= FMODE_CAN_ODIRECT; + f->f_write_hint = WRITE_LIFE_NOT_SET; f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); f->f_iocb_flags = iocb_flags(f); diff --git a/include/linux/fs.h b/include/linux/fs.h index 4aeb3fa11927..ba2c5c90af6d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1001,6 +1001,7 @@ struct file { * Must not be taken from IRQ context. */ spinlock_t f_lock; + enum rw_hint f_write_hint; fmode_t f_mode; atomic_long_t f_count; struct mutex f_pos_lock; @@ -2134,6 +2135,14 @@ static inline bool HAS_UNMAPPED_ID(struct mnt_idmap *idmap, !vfsgid_valid(i_gid_into_vfsgid(idmap, inode)); } +static inline enum rw_hint file_write_hint(struct file *file) +{ + if (file->f_write_hint != WRITE_LIFE_NOT_SET) + return file->f_write_hint; + + return file_inode(file)->i_write_hint; +} + static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) { *kiocb = (struct kiocb) {