Commit 91f9943e authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Al Viro

fs: support RWF_NOWAIT for buffered reads

This is based on the old idea and code from Milosz Tanski.  With the aio
nowait code it becomes mostly trivial now.  Buffered writes continue to
return -EOPNOTSUPP if RWF_NOWAIT is passed.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 3239d834
...@@ -1593,12 +1593,6 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, ...@@ -1593,12 +1593,6 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
goto out_put_req; goto out_put_req;
} }
if ((req->common.ki_flags & IOCB_NOWAIT) &&
!(req->common.ki_flags & IOCB_DIRECT)) {
ret = -EOPNOTSUPP;
goto out_put_req;
}
ret = put_user(KIOCB_KEY, &user_iocb->aio_key); ret = put_user(KIOCB_KEY, &user_iocb->aio_key);
if (unlikely(ret)) { if (unlikely(ret)) {
pr_debug("EFAULT: aio_key\n"); pr_debug("EFAULT: aio_key\n");
......
...@@ -1886,6 +1886,10 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, ...@@ -1886,6 +1886,10 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
loff_t oldsize; loff_t oldsize;
int clean_page = 0; int clean_page = 0;
if (!(iocb->ki_flags & IOCB_DIRECT) &&
(iocb->ki_flags & IOCB_NOWAIT))
return -EOPNOTSUPP;
if (!inode_trylock(inode)) { if (!inode_trylock(inode)) {
if (iocb->ki_flags & IOCB_NOWAIT) if (iocb->ki_flags & IOCB_NOWAIT)
return -EAGAIN; return -EAGAIN;
...@@ -3105,7 +3109,7 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence) ...@@ -3105,7 +3109,7 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence)
static int btrfs_file_open(struct inode *inode, struct file *filp) static int btrfs_file_open(struct inode *inode, struct file *filp)
{ {
filp->f_mode |= FMODE_AIO_NOWAIT; filp->f_mode |= FMODE_NOWAIT;
return generic_file_open(inode, filp); return generic_file_open(inode, filp);
} }
......
...@@ -223,6 +223,8 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -223,6 +223,8 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (IS_DAX(inode)) if (IS_DAX(inode))
return ext4_dax_write_iter(iocb, from); return ext4_dax_write_iter(iocb, from);
#endif #endif
if (!o_direct && (iocb->ki_flags & IOCB_NOWAIT))
return -EOPNOTSUPP;
if (!inode_trylock(inode)) { if (!inode_trylock(inode)) {
if (iocb->ki_flags & IOCB_NOWAIT) if (iocb->ki_flags & IOCB_NOWAIT)
...@@ -448,9 +450,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) ...@@ -448,9 +450,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
return ret; return ret;
} }
/* Set the flags to support nowait AIO */ filp->f_mode |= FMODE_NOWAIT;
filp->f_mode |= FMODE_AIO_NOWAIT;
return dquot_file_open(inode, filp); return dquot_file_open(inode, filp);
} }
......
...@@ -259,7 +259,11 @@ xfs_file_buffered_aio_read( ...@@ -259,7 +259,11 @@ xfs_file_buffered_aio_read(
trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos);
xfs_ilock(ip, XFS_IOLOCK_SHARED); if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
if (iocb->ki_flags & IOCB_NOWAIT)
return -EAGAIN;
xfs_ilock(ip, XFS_IOLOCK_SHARED);
}
ret = generic_file_read_iter(iocb, to); ret = generic_file_read_iter(iocb, to);
xfs_iunlock(ip, XFS_IOLOCK_SHARED); xfs_iunlock(ip, XFS_IOLOCK_SHARED);
...@@ -636,6 +640,9 @@ xfs_file_buffered_aio_write( ...@@ -636,6 +640,9 @@ xfs_file_buffered_aio_write(
int enospc = 0; int enospc = 0;
int iolock; int iolock;
if (iocb->ki_flags & IOCB_NOWAIT)
return -EOPNOTSUPP;
write_retry: write_retry:
iolock = XFS_IOLOCK_EXCL; iolock = XFS_IOLOCK_EXCL;
xfs_ilock(ip, iolock); xfs_ilock(ip, iolock);
...@@ -912,7 +919,7 @@ xfs_file_open( ...@@ -912,7 +919,7 @@ xfs_file_open(
return -EFBIG; return -EFBIG;
if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb))) if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb)))
return -EIO; return -EIO;
file->f_mode |= FMODE_AIO_NOWAIT; file->f_mode |= FMODE_NOWAIT;
return 0; return 0;
} }
......
...@@ -146,8 +146,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, ...@@ -146,8 +146,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
/* File was opened by fanotify and shouldn't generate fanotify events */ /* File was opened by fanotify and shouldn't generate fanotify events */
#define FMODE_NONOTIFY ((__force fmode_t)0x4000000) #define FMODE_NONOTIFY ((__force fmode_t)0x4000000)
/* File is capable of returning -EAGAIN if AIO will block */ /* File is capable of returning -EAGAIN if I/O will block */
#define FMODE_AIO_NOWAIT ((__force fmode_t)0x8000000) #define FMODE_NOWAIT ((__force fmode_t)0x8000000)
/* /*
* Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector
...@@ -3149,7 +3149,7 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, int flags) ...@@ -3149,7 +3149,7 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, int flags)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (flags & RWF_NOWAIT) { if (flags & RWF_NOWAIT) {
if (!(ki->ki_filp->f_mode & FMODE_AIO_NOWAIT)) if (!(ki->ki_filp->f_mode & FMODE_NOWAIT))
return -EOPNOTSUPP; return -EOPNOTSUPP;
ki->ki_flags |= IOCB_NOWAIT; ki->ki_flags |= IOCB_NOWAIT;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment