diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-14 22:29:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-14 22:29:55 -0400 |
commit | e253d98f5babbec7e6ced810f7335b265a7f7e83 (patch) | |
tree | cd688c4ba8d43edb12bbeb523393879f7c212b65 | |
parent | 0f0d12728e56c94d3289c6831243b6faeae8a19d (diff) | |
parent | c35fc7a5abae9c154dd6f8c0b288462342facd45 (diff) |
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
-rw-r--r-- | fs/aio.c | 6 | ||||
-rw-r--r-- | fs/block_dev.c | 5 | ||||
-rw-r--r-- | fs/btrfs/file.c | 6 | ||||
-rw-r--r-- | fs/ext4/file.c | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 11 | ||||
-rw-r--r-- | include/linux/fs.h | 6 | ||||
-rw-r--r-- | mm/filemap.c | 24 |
7 files changed, 42 insertions, 22 deletions
@@ -1606,12 +1606,6 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, | |||
1606 | goto out_put_req; | 1606 | goto out_put_req; |
1607 | } | 1607 | } |
1608 | 1608 | ||
1609 | if ((req->common.ki_flags & IOCB_NOWAIT) && | ||
1610 | !(req->common.ki_flags & IOCB_DIRECT)) { | ||
1611 | ret = -EOPNOTSUPP; | ||
1612 | goto out_put_req; | ||
1613 | } | ||
1614 | |||
1615 | ret = put_user(KIOCB_KEY, &user_iocb->aio_key); | 1609 | ret = put_user(KIOCB_KEY, &user_iocb->aio_key); |
1616 | if (unlikely(ret)) { | 1610 | if (unlikely(ret)) { |
1617 | pr_debug("EFAULT: aio_key\n"); | 1611 | pr_debug("EFAULT: aio_key\n"); |
diff --git a/fs/block_dev.c b/fs/block_dev.c index bb715b2fcfb8..93d088ffc05c 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -1740,6 +1740,8 @@ static int blkdev_open(struct inode * inode, struct file * filp) | |||
1740 | */ | 1740 | */ |
1741 | filp->f_flags |= O_LARGEFILE; | 1741 | filp->f_flags |= O_LARGEFILE; |
1742 | 1742 | ||
1743 | filp->f_mode |= FMODE_NOWAIT; | ||
1744 | |||
1743 | if (filp->f_flags & O_NDELAY) | 1745 | if (filp->f_flags & O_NDELAY) |
1744 | filp->f_mode |= FMODE_NDELAY; | 1746 | filp->f_mode |= FMODE_NDELAY; |
1745 | if (filp->f_flags & O_EXCL) | 1747 | if (filp->f_flags & O_EXCL) |
@@ -1892,6 +1894,9 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1892 | if (iocb->ki_pos >= size) | 1894 | if (iocb->ki_pos >= size) |
1893 | return -ENOSPC; | 1895 | return -ENOSPC; |
1894 | 1896 | ||
1897 | if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT) | ||
1898 | return -EOPNOTSUPP; | ||
1899 | |||
1895 | iov_iter_truncate(from, size - iocb->ki_pos); | 1900 | iov_iter_truncate(from, size - iocb->ki_pos); |
1896 | 1901 | ||
1897 | blk_start_plug(&plug); | 1902 | blk_start_plug(&plug); |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 74fd7756cff3..aafcc785f840 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1886,6 +1886,10 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, | |||
1886 | loff_t oldsize; | 1886 | loff_t oldsize; |
1887 | int clean_page = 0; | 1887 | int clean_page = 0; |
1888 | 1888 | ||
1889 | if (!(iocb->ki_flags & IOCB_DIRECT) && | ||
1890 | (iocb->ki_flags & IOCB_NOWAIT)) | ||
1891 | return -EOPNOTSUPP; | ||
1892 | |||
1889 | if (!inode_trylock(inode)) { | 1893 | if (!inode_trylock(inode)) { |
1890 | if (iocb->ki_flags & IOCB_NOWAIT) | 1894 | if (iocb->ki_flags & IOCB_NOWAIT) |
1891 | return -EAGAIN; | 1895 | return -EAGAIN; |
@@ -3112,7 +3116,7 @@ out: | |||
3112 | 3116 | ||
3113 | static int btrfs_file_open(struct inode *inode, struct file *filp) | 3117 | static int btrfs_file_open(struct inode *inode, struct file *filp) |
3114 | { | 3118 | { |
3115 | filp->f_mode |= FMODE_AIO_NOWAIT; | 3119 | filp->f_mode |= FMODE_NOWAIT; |
3116 | return generic_file_open(inode, filp); | 3120 | return generic_file_open(inode, filp); |
3117 | } | 3121 | } |
3118 | 3122 | ||
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index da9c6948ad25..b1da660ac3bc 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -223,6 +223,8 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
223 | if (IS_DAX(inode)) | 223 | if (IS_DAX(inode)) |
224 | return ext4_dax_write_iter(iocb, from); | 224 | return ext4_dax_write_iter(iocb, from); |
225 | #endif | 225 | #endif |
226 | if (!o_direct && (iocb->ki_flags & IOCB_NOWAIT)) | ||
227 | return -EOPNOTSUPP; | ||
226 | 228 | ||
227 | if (!inode_trylock(inode)) { | 229 | if (!inode_trylock(inode)) { |
228 | if (iocb->ki_flags & IOCB_NOWAIT) | 230 | if (iocb->ki_flags & IOCB_NOWAIT) |
@@ -431,9 +433,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
431 | return ret; | 433 | return ret; |
432 | } | 434 | } |
433 | 435 | ||
434 | /* Set the flags to support nowait AIO */ | 436 | filp->f_mode |= FMODE_NOWAIT; |
435 | filp->f_mode |= FMODE_AIO_NOWAIT; | ||
436 | |||
437 | return dquot_file_open(inode, filp); | 437 | return dquot_file_open(inode, filp); |
438 | } | 438 | } |
439 | 439 | ||
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index ec3e44fcf771..ebdd0bd2b261 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -259,7 +259,11 @@ xfs_file_buffered_aio_read( | |||
259 | 259 | ||
260 | trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); | 260 | trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); |
261 | 261 | ||
262 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 262 | if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) { |
263 | if (iocb->ki_flags & IOCB_NOWAIT) | ||
264 | return -EAGAIN; | ||
265 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | ||
266 | } | ||
263 | ret = generic_file_read_iter(iocb, to); | 267 | ret = generic_file_read_iter(iocb, to); |
264 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 268 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
265 | 269 | ||
@@ -636,6 +640,9 @@ xfs_file_buffered_aio_write( | |||
636 | int enospc = 0; | 640 | int enospc = 0; |
637 | int iolock; | 641 | int iolock; |
638 | 642 | ||
643 | if (iocb->ki_flags & IOCB_NOWAIT) | ||
644 | return -EOPNOTSUPP; | ||
645 | |||
639 | write_retry: | 646 | write_retry: |
640 | iolock = XFS_IOLOCK_EXCL; | 647 | iolock = XFS_IOLOCK_EXCL; |
641 | xfs_ilock(ip, iolock); | 648 | xfs_ilock(ip, iolock); |
@@ -912,7 +919,7 @@ xfs_file_open( | |||
912 | return -EFBIG; | 919 | return -EFBIG; |
913 | if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb))) | 920 | if (XFS_FORCED_SHUTDOWN(XFS_M(inode->i_sb))) |
914 | return -EIO; | 921 | return -EIO; |
915 | file->f_mode |= FMODE_AIO_NOWAIT; | 922 | file->f_mode |= FMODE_NOWAIT; |
916 | return 0; | 923 | return 0; |
917 | } | 924 | } |
918 | 925 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index b4ae080f41a6..bc475dfeb4ce 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -148,8 +148,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, | |||
148 | /* File was opened by fanotify and shouldn't generate fanotify events */ | 148 | /* File was opened by fanotify and shouldn't generate fanotify events */ |
149 | #define FMODE_NONOTIFY ((__force fmode_t)0x4000000) | 149 | #define FMODE_NONOTIFY ((__force fmode_t)0x4000000) |
150 | 150 | ||
151 | /* File is capable of returning -EAGAIN if AIO will block */ | 151 | /* File is capable of returning -EAGAIN if I/O will block */ |
152 | #define FMODE_AIO_NOWAIT ((__force fmode_t)0x8000000) | 152 | #define FMODE_NOWAIT ((__force fmode_t)0x8000000) |
153 | 153 | ||
154 | /* | 154 | /* |
155 | * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector | 155 | * 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 | return -EOPNOTSUPP; | 3194 | return -EOPNOTSUPP; |
3195 | 3195 | ||
3196 | if (flags & RWF_NOWAIT) { | 3196 | if (flags & RWF_NOWAIT) { |
3197 | if (!(ki->ki_filp->f_mode & FMODE_AIO_NOWAIT)) | 3197 | if (!(ki->ki_filp->f_mode & FMODE_NOWAIT)) |
3198 | return -EOPNOTSUPP; | 3198 | return -EOPNOTSUPP; |
3199 | ki->ki_flags |= IOCB_NOWAIT; | 3199 | ki->ki_flags |= IOCB_NOWAIT; |
3200 | } | 3200 | } |
diff --git a/mm/filemap.c b/mm/filemap.c index 8c88e186a773..870971e20967 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -1917,9 +1917,8 @@ static void shrink_readahead_size_eio(struct file *filp, | |||
1917 | } | 1917 | } |
1918 | 1918 | ||
1919 | /** | 1919 | /** |
1920 | * do_generic_file_read - generic file read routine | 1920 | * generic_file_buffered_read - generic file read routine |
1921 | * @filp: the file to read | 1921 | * @iocb: the iocb to read |
1922 | * @ppos: current file position | ||
1923 | * @iter: data destination | 1922 | * @iter: data destination |
1924 | * @written: already copied | 1923 | * @written: already copied |
1925 | * | 1924 | * |
@@ -1929,12 +1928,14 @@ static void shrink_readahead_size_eio(struct file *filp, | |||
1929 | * This is really ugly. But the goto's actually try to clarify some | 1928 | * This is really ugly. But the goto's actually try to clarify some |
1930 | * of the logic when it comes to error handling etc. | 1929 | * of the logic when it comes to error handling etc. |
1931 | */ | 1930 | */ |
1932 | static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos, | 1931 | static ssize_t generic_file_buffered_read(struct kiocb *iocb, |
1933 | struct iov_iter *iter, ssize_t written) | 1932 | struct iov_iter *iter, ssize_t written) |
1934 | { | 1933 | { |
1934 | struct file *filp = iocb->ki_filp; | ||
1935 | struct address_space *mapping = filp->f_mapping; | 1935 | struct address_space *mapping = filp->f_mapping; |
1936 | struct inode *inode = mapping->host; | 1936 | struct inode *inode = mapping->host; |
1937 | struct file_ra_state *ra = &filp->f_ra; | 1937 | struct file_ra_state *ra = &filp->f_ra; |
1938 | loff_t *ppos = &iocb->ki_pos; | ||
1938 | pgoff_t index; | 1939 | pgoff_t index; |
1939 | pgoff_t last_index; | 1940 | pgoff_t last_index; |
1940 | pgoff_t prev_index; | 1941 | pgoff_t prev_index; |
@@ -1967,6 +1968,8 @@ find_page: | |||
1967 | 1968 | ||
1968 | page = find_get_page(mapping, index); | 1969 | page = find_get_page(mapping, index); |
1969 | if (!page) { | 1970 | if (!page) { |
1971 | if (iocb->ki_flags & IOCB_NOWAIT) | ||
1972 | goto would_block; | ||
1970 | page_cache_sync_readahead(mapping, | 1973 | page_cache_sync_readahead(mapping, |
1971 | ra, filp, | 1974 | ra, filp, |
1972 | index, last_index - index); | 1975 | index, last_index - index); |
@@ -1980,6 +1983,11 @@ find_page: | |||
1980 | index, last_index - index); | 1983 | index, last_index - index); |
1981 | } | 1984 | } |
1982 | if (!PageUptodate(page)) { | 1985 | if (!PageUptodate(page)) { |
1986 | if (iocb->ki_flags & IOCB_NOWAIT) { | ||
1987 | put_page(page); | ||
1988 | goto would_block; | ||
1989 | } | ||
1990 | |||
1983 | /* | 1991 | /* |
1984 | * See comment in do_read_cache_page on why | 1992 | * See comment in do_read_cache_page on why |
1985 | * wait_on_page_locked is used to avoid unnecessarily | 1993 | * wait_on_page_locked is used to avoid unnecessarily |
@@ -2161,6 +2169,8 @@ no_cached_page: | |||
2161 | goto readpage; | 2169 | goto readpage; |
2162 | } | 2170 | } |
2163 | 2171 | ||
2172 | would_block: | ||
2173 | error = -EAGAIN; | ||
2164 | out: | 2174 | out: |
2165 | ra->prev_pos = prev_index; | 2175 | ra->prev_pos = prev_index; |
2166 | ra->prev_pos <<= PAGE_SHIFT; | 2176 | ra->prev_pos <<= PAGE_SHIFT; |
@@ -2182,14 +2192,14 @@ out: | |||
2182 | ssize_t | 2192 | ssize_t |
2183 | generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) | 2193 | generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) |
2184 | { | 2194 | { |
2185 | struct file *file = iocb->ki_filp; | ||
2186 | ssize_t retval = 0; | ||
2187 | size_t count = iov_iter_count(iter); | 2195 | size_t count = iov_iter_count(iter); |
2196 | ssize_t retval = 0; | ||
2188 | 2197 | ||
2189 | if (!count) | 2198 | if (!count) |
2190 | goto out; /* skip atime */ | 2199 | goto out; /* skip atime */ |
2191 | 2200 | ||
2192 | if (iocb->ki_flags & IOCB_DIRECT) { | 2201 | if (iocb->ki_flags & IOCB_DIRECT) { |
2202 | struct file *file = iocb->ki_filp; | ||
2193 | struct address_space *mapping = file->f_mapping; | 2203 | struct address_space *mapping = file->f_mapping; |
2194 | struct inode *inode = mapping->host; | 2204 | struct inode *inode = mapping->host; |
2195 | loff_t size; | 2205 | loff_t size; |
@@ -2230,7 +2240,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) | |||
2230 | goto out; | 2240 | goto out; |
2231 | } | 2241 | } |
2232 | 2242 | ||
2233 | retval = do_generic_file_read(file, &iocb->ki_pos, iter, retval); | 2243 | retval = generic_file_buffered_read(iocb, iter, retval); |
2234 | out: | 2244 | out: |
2235 | return retval; | 2245 | return retval; |
2236 | } | 2246 | } |