Commit e253d98f authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.read_write' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull nowait read support from Al Viro:
 "Support IOCB_NOWAIT for buffered reads and block devices"

* 'work.read_write' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  block_dev: support RFW_NOWAIT on block device nodes
  fs: support RWF_NOWAIT for buffered reads
  fs: support IOCB_NOWAIT in generic_file_buffered_read
  fs: pass iocb to do_generic_file_read
parents 0f0d1272 c35fc7a5
...@@ -1606,12 +1606,6 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, ...@@ -1606,12 +1606,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");
......
...@@ -1740,6 +1740,8 @@ static int blkdev_open(struct inode * inode, struct file * filp) ...@@ -1740,6 +1740,8 @@ static int blkdev_open(struct inode * inode, struct file * filp)
*/ */
filp->f_flags |= O_LARGEFILE; filp->f_flags |= O_LARGEFILE;
filp->f_mode |= FMODE_NOWAIT;
if (filp->f_flags & O_NDELAY) if (filp->f_flags & O_NDELAY)
filp->f_mode |= FMODE_NDELAY; filp->f_mode |= FMODE_NDELAY;
if (filp->f_flags & O_EXCL) if (filp->f_flags & O_EXCL)
...@@ -1892,6 +1894,9 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -1892,6 +1894,9 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (iocb->ki_pos >= size) if (iocb->ki_pos >= size)
return -ENOSPC; return -ENOSPC;
if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT)
return -EOPNOTSUPP;
iov_iter_truncate(from, size - iocb->ki_pos); iov_iter_truncate(from, size - iocb->ki_pos);
blk_start_plug(&plug); blk_start_plug(&plug);
......
...@@ -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;
...@@ -3112,7 +3116,7 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int whence) ...@@ -3112,7 +3116,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)
...@@ -431,9 +433,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) ...@@ -431,9 +433,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;
} }
......
...@@ -148,8 +148,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, ...@@ -148,8 +148,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
...@@ -3194,7 +3194,7 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t flags) ...@@ -3194,7 +3194,7 @@ static inline int kiocb_set_rw_flags(struct kiocb *ki, rwf_t 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;
} }
......
...@@ -1917,9 +1917,8 @@ static void shrink_readahead_size_eio(struct file *filp, ...@@ -1917,9 +1917,8 @@ static void shrink_readahead_size_eio(struct file *filp,
} }
/** /**
* do_generic_file_read - generic file read routine * generic_file_buffered_read - generic file read routine
* @filp: the file to read * @iocb: the iocb to read
* @ppos: current file position
* @iter: data destination * @iter: data destination
* @written: already copied * @written: already copied
* *
...@@ -1929,12 +1928,14 @@ static void shrink_readahead_size_eio(struct file *filp, ...@@ -1929,12 +1928,14 @@ static void shrink_readahead_size_eio(struct file *filp,
* This is really ugly. But the goto's actually try to clarify some * This is really ugly. But the goto's actually try to clarify some
* of the logic when it comes to error handling etc. * of the logic when it comes to error handling etc.
*/ */
static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos, static ssize_t generic_file_buffered_read(struct kiocb *iocb,
struct iov_iter *iter, ssize_t written) struct iov_iter *iter, ssize_t written)
{ {
struct file *filp = iocb->ki_filp;
struct address_space *mapping = filp->f_mapping; struct address_space *mapping = filp->f_mapping;
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
struct file_ra_state *ra = &filp->f_ra; struct file_ra_state *ra = &filp->f_ra;
loff_t *ppos = &iocb->ki_pos;
pgoff_t index; pgoff_t index;
pgoff_t last_index; pgoff_t last_index;
pgoff_t prev_index; pgoff_t prev_index;
...@@ -1967,6 +1968,8 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos, ...@@ -1967,6 +1968,8 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
page = find_get_page(mapping, index); page = find_get_page(mapping, index);
if (!page) { if (!page) {
if (iocb->ki_flags & IOCB_NOWAIT)
goto would_block;
page_cache_sync_readahead(mapping, page_cache_sync_readahead(mapping,
ra, filp, ra, filp,
index, last_index - index); index, last_index - index);
...@@ -1980,6 +1983,11 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos, ...@@ -1980,6 +1983,11 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
index, last_index - index); index, last_index - index);
} }
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
if (iocb->ki_flags & IOCB_NOWAIT) {
put_page(page);
goto would_block;
}
/* /*
* See comment in do_read_cache_page on why * See comment in do_read_cache_page on why
* wait_on_page_locked is used to avoid unnecessarily * wait_on_page_locked is used to avoid unnecessarily
...@@ -2161,6 +2169,8 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos, ...@@ -2161,6 +2169,8 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
goto readpage; goto readpage;
} }
would_block:
error = -EAGAIN;
out: out:
ra->prev_pos = prev_index; ra->prev_pos = prev_index;
ra->prev_pos <<= PAGE_SHIFT; ra->prev_pos <<= PAGE_SHIFT;
...@@ -2182,14 +2192,14 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos, ...@@ -2182,14 +2192,14 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos,
ssize_t ssize_t
generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
{ {
struct file *file = iocb->ki_filp;
ssize_t retval = 0;
size_t count = iov_iter_count(iter); size_t count = iov_iter_count(iter);
ssize_t retval = 0;
if (!count) if (!count)
goto out; /* skip atime */ goto out; /* skip atime */
if (iocb->ki_flags & IOCB_DIRECT) { if (iocb->ki_flags & IOCB_DIRECT) {
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping; struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
loff_t size; loff_t size;
...@@ -2230,7 +2240,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) ...@@ -2230,7 +2240,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
goto out; goto out;
} }
retval = do_generic_file_read(file, &iocb->ki_pos, iter, retval); retval = generic_file_buffered_read(iocb, iter, retval);
out: out:
return retval; return retval;
} }
......
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