Revert commit 7b12e49669c9 ("fs: remove fs.f_write_hint") to enable testing write hint support with fio and direct I/O. Cc: Jeff Layton <jlayton@xxxxxxxxxx> Cc: Chuck Lever <chuck.lever@xxxxxxxxxx> Cc: Jens Axboe <axboe@xxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: Dave Chinner <dchinner@xxxxxxxxxx> Cc: Chaitanya Kulkarni <kch@xxxxxxxxxx> Signed-off-by: Bart Van Assche <bvanassche@xxxxxxx> --- fs/fcntl.c | 17 +++++++++++++++++ fs/open.c | 1 + include/linux/fs.h | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/fs/fcntl.c b/fs/fcntl.c index 891a9ebcdef1..fe80e19f1c1a 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -292,6 +292,21 @@ static long fcntl_rw_hint(struct file *file, unsigned int cmd, u64 hint; switch (cmd) { + case F_GET_FILE_RW_HINT: + hint = file_write_hint(file); + if (copy_to_user(argp, &hint, sizeof(*argp))) + return -EFAULT; + return 0; + case F_SET_FILE_RW_HINT: + if (copy_from_user(&hint, argp, sizeof(hint))) + return -EFAULT; + 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: hint = inode->i_write_hint; if (copy_to_user(argp, &hint, sizeof(*argp))) @@ -416,6 +431,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 02dc608d40d8..4c5c29541ac5 100644 --- a/fs/open.c +++ b/fs/open.c @@ -961,6 +961,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 a08014b68d6e..a6e0c4b5a72b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -989,6 +989,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; @@ -2162,6 +2163,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) {