mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
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
This commit is contained in:
commit
e253d98f5b
6
fs/aio.c
6
fs/aio.c
@ -1606,12 +1606,6 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
|
||||
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);
|
||||
if (unlikely(ret)) {
|
||||
pr_debug("EFAULT: aio_key\n");
|
||||
|
@ -1740,6 +1740,8 @@ static int blkdev_open(struct inode * inode, struct file * filp)
|
||||
*/
|
||||
filp->f_flags |= O_LARGEFILE;
|
||||
|
||||
filp->f_mode |= FMODE_NOWAIT;
|
||||
|
||||
if (filp->f_flags & O_NDELAY)
|
||||
filp->f_mode |= FMODE_NDELAY;
|
||||
if (filp->f_flags & O_EXCL)
|
||||
@ -1892,6 +1894,9 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (iocb->ki_pos >= size)
|
||||
return -ENOSPC;
|
||||
|
||||
if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
iov_iter_truncate(from, size - iocb->ki_pos);
|
||||
|
||||
blk_start_plug(&plug);
|
||||
|
@ -1886,6 +1886,10 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
|
||||
loff_t oldsize;
|
||||
int clean_page = 0;
|
||||
|
||||
if (!(iocb->ki_flags & IOCB_DIRECT) &&
|
||||
(iocb->ki_flags & IOCB_NOWAIT))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!inode_trylock(inode)) {
|
||||
if (iocb->ki_flags & IOCB_NOWAIT)
|
||||
return -EAGAIN;
|
||||
@ -3112,7 +3116,7 @@ out:
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -223,6 +223,8 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
if (IS_DAX(inode))
|
||||
return ext4_dax_write_iter(iocb, from);
|
||||
#endif
|
||||
if (!o_direct && (iocb->ki_flags & IOCB_NOWAIT))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!inode_trylock(inode)) {
|
||||
if (iocb->ki_flags & IOCB_NOWAIT)
|
||||
@ -431,9 +433,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set the flags to support nowait AIO */
|
||||
filp->f_mode |= FMODE_AIO_NOWAIT;
|
||||
|
||||
filp->f_mode |= FMODE_NOWAIT;
|
||||
return dquot_file_open(inode, filp);
|
||||
}
|
||||
|
||||
|
@ -259,7 +259,11 @@ xfs_file_buffered_aio_read(
|
||||
|
||||
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);
|
||||
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
||||
|
||||
@ -636,6 +640,9 @@ xfs_file_buffered_aio_write(
|
||||
int enospc = 0;
|
||||
int iolock;
|
||||
|
||||
if (iocb->ki_flags & IOCB_NOWAIT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
write_retry:
|
||||
iolock = XFS_IOLOCK_EXCL;
|
||||
xfs_ilock(ip, iolock);
|
||||
@ -912,7 +919,7 @@ xfs_file_open(
|
||||
return -EFBIG;
|
||||
if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb)))
|
||||
return -EIO;
|
||||
file->f_mode |= FMODE_AIO_NOWAIT;
|
||||
file->f_mode |= FMODE_NOWAIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
#define FMODE_NONOTIFY ((__force fmode_t)0x4000000)
|
||||
|
||||
/* File is capable of returning -EAGAIN if AIO will block */
|
||||
#define FMODE_AIO_NOWAIT ((__force fmode_t)0x8000000)
|
||||
/* File is capable of returning -EAGAIN if I/O will block */
|
||||
#define FMODE_NOWAIT ((__force fmode_t)0x8000000)
|
||||
|
||||
/*
|
||||
* 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)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (flags & RWF_NOWAIT) {
|
||||
if (!(ki->ki_filp->f_mode & FMODE_AIO_NOWAIT))
|
||||
if (!(ki->ki_filp->f_mode & FMODE_NOWAIT))
|
||||
return -EOPNOTSUPP;
|
||||
ki->ki_flags |= IOCB_NOWAIT;
|
||||
}
|
||||
|
24
mm/filemap.c
24
mm/filemap.c
@ -1917,9 +1917,8 @@ static void shrink_readahead_size_eio(struct file *filp,
|
||||
}
|
||||
|
||||
/**
|
||||
* do_generic_file_read - generic file read routine
|
||||
* @filp: the file to read
|
||||
* @ppos: current file position
|
||||
* generic_file_buffered_read - generic file read routine
|
||||
* @iocb: the iocb to read
|
||||
* @iter: data destination
|
||||
* @written: already copied
|
||||
*
|
||||
@ -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
|
||||
* 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 file *filp = iocb->ki_filp;
|
||||
struct address_space *mapping = filp->f_mapping;
|
||||
struct inode *inode = mapping->host;
|
||||
struct file_ra_state *ra = &filp->f_ra;
|
||||
loff_t *ppos = &iocb->ki_pos;
|
||||
pgoff_t index;
|
||||
pgoff_t last_index;
|
||||
pgoff_t prev_index;
|
||||
@ -1967,6 +1968,8 @@ find_page:
|
||||
|
||||
page = find_get_page(mapping, index);
|
||||
if (!page) {
|
||||
if (iocb->ki_flags & IOCB_NOWAIT)
|
||||
goto would_block;
|
||||
page_cache_sync_readahead(mapping,
|
||||
ra, filp,
|
||||
index, last_index - index);
|
||||
@ -1980,6 +1983,11 @@ find_page:
|
||||
index, last_index - index);
|
||||
}
|
||||
if (!PageUptodate(page)) {
|
||||
if (iocb->ki_flags & IOCB_NOWAIT) {
|
||||
put_page(page);
|
||||
goto would_block;
|
||||
}
|
||||
|
||||
/*
|
||||
* See comment in do_read_cache_page on why
|
||||
* wait_on_page_locked is used to avoid unnecessarily
|
||||
@ -2161,6 +2169,8 @@ no_cached_page:
|
||||
goto readpage;
|
||||
}
|
||||
|
||||
would_block:
|
||||
error = -EAGAIN;
|
||||
out:
|
||||
ra->prev_pos = prev_index;
|
||||
ra->prev_pos <<= PAGE_SHIFT;
|
||||
@ -2182,14 +2192,14 @@ out:
|
||||
ssize_t
|
||||
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);
|
||||
ssize_t retval = 0;
|
||||
|
||||
if (!count)
|
||||
goto out; /* skip atime */
|
||||
|
||||
if (iocb->ki_flags & IOCB_DIRECT) {
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct address_space *mapping = file->f_mapping;
|
||||
struct inode *inode = mapping->host;
|
||||
loff_t size;
|
||||
@ -2230,7 +2240,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = do_generic_file_read(file, &iocb->ki_pos, iter, retval);
|
||||
retval = generic_file_buffered_read(iocb, iter, retval);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user