diff options
author | Goldwyn Rodrigues <rgoldwyn@suse.com> | 2017-06-20 08:05:49 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2017-06-20 09:12:03 -0400 |
commit | edf064e7c6fec3646b06c944a8e35d1a3de5c2c3 (patch) | |
tree | 861835f7c0ae787598be8e18eac67f623d90658e | |
parent | 29a5d29ec181ebdc98a26cedbd76ce9870248892 (diff) |
btrfs: nowait aio support
Return EAGAIN if any of the following checks fail
+ i_rwsem is not lockable
+ NODATACOW or PREALLOC is not set
+ Cannot nocow at the desired location
+ Writing beyond end of file which is not allocated
Acked-by: David Sterba <dsterba@suse.com>
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | fs/btrfs/file.c | 33 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 3 |
2 files changed, 30 insertions, 6 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index da1096eb1a40..59e2dccdf75b 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1875,12 +1875,29 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, | |||
1875 | ssize_t num_written = 0; | 1875 | ssize_t num_written = 0; |
1876 | bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); | 1876 | bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host); |
1877 | ssize_t err; | 1877 | ssize_t err; |
1878 | loff_t pos; | 1878 | loff_t pos = iocb->ki_pos; |
1879 | size_t count; | 1879 | size_t count = iov_iter_count(from); |
1880 | loff_t oldsize; | 1880 | loff_t oldsize; |
1881 | int clean_page = 0; | 1881 | int clean_page = 0; |
1882 | 1882 | ||
1883 | inode_lock(inode); | 1883 | if ((iocb->ki_flags & IOCB_NOWAIT) && |
1884 | (iocb->ki_flags & IOCB_DIRECT)) { | ||
1885 | /* Don't sleep on inode rwsem */ | ||
1886 | if (!inode_trylock(inode)) | ||
1887 | return -EAGAIN; | ||
1888 | /* | ||
1889 | * We will allocate space in case nodatacow is not set, | ||
1890 | * so bail | ||
1891 | */ | ||
1892 | if (!(BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW | | ||
1893 | BTRFS_INODE_PREALLOC)) || | ||
1894 | check_can_nocow(BTRFS_I(inode), pos, &count) <= 0) { | ||
1895 | inode_unlock(inode); | ||
1896 | return -EAGAIN; | ||
1897 | } | ||
1898 | } else | ||
1899 | inode_lock(inode); | ||
1900 | |||
1884 | err = generic_write_checks(iocb, from); | 1901 | err = generic_write_checks(iocb, from); |
1885 | if (err <= 0) { | 1902 | if (err <= 0) { |
1886 | inode_unlock(inode); | 1903 | inode_unlock(inode); |
@@ -1914,8 +1931,6 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb, | |||
1914 | */ | 1931 | */ |
1915 | update_time_for_write(inode); | 1932 | update_time_for_write(inode); |
1916 | 1933 | ||
1917 | pos = iocb->ki_pos; | ||
1918 | count = iov_iter_count(from); | ||
1919 | start_pos = round_down(pos, fs_info->sectorsize); | 1934 | start_pos = round_down(pos, fs_info->sectorsize); |
1920 | oldsize = i_size_read(inode); | 1935 | oldsize = i_size_read(inode); |
1921 | if (start_pos > oldsize) { | 1936 | if (start_pos > oldsize) { |
@@ -3071,13 +3086,19 @@ out: | |||
3071 | return offset; | 3086 | return offset; |
3072 | } | 3087 | } |
3073 | 3088 | ||
3089 | static int btrfs_file_open(struct inode *inode, struct file *filp) | ||
3090 | { | ||
3091 | filp->f_mode |= FMODE_AIO_NOWAIT; | ||
3092 | return generic_file_open(inode, filp); | ||
3093 | } | ||
3094 | |||
3074 | const struct file_operations btrfs_file_operations = { | 3095 | const struct file_operations btrfs_file_operations = { |
3075 | .llseek = btrfs_file_llseek, | 3096 | .llseek = btrfs_file_llseek, |
3076 | .read_iter = generic_file_read_iter, | 3097 | .read_iter = generic_file_read_iter, |
3077 | .splice_read = generic_file_splice_read, | 3098 | .splice_read = generic_file_splice_read, |
3078 | .write_iter = btrfs_file_write_iter, | 3099 | .write_iter = btrfs_file_write_iter, |
3079 | .mmap = btrfs_file_mmap, | 3100 | .mmap = btrfs_file_mmap, |
3080 | .open = generic_file_open, | 3101 | .open = btrfs_file_open, |
3081 | .release = btrfs_release_file, | 3102 | .release = btrfs_release_file, |
3082 | .fsync = btrfs_sync_file, | 3103 | .fsync = btrfs_sync_file, |
3083 | .fallocate = btrfs_fallocate, | 3104 | .fallocate = btrfs_fallocate, |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index f942293dd7e7..556c93060606 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -8754,6 +8754,9 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) | |||
8754 | dio_data.overwrite = 1; | 8754 | dio_data.overwrite = 1; |
8755 | inode_unlock(inode); | 8755 | inode_unlock(inode); |
8756 | relock = true; | 8756 | relock = true; |
8757 | } else if (iocb->ki_flags & IOCB_NOWAIT) { | ||
8758 | ret = -EAGAIN; | ||
8759 | goto out; | ||
8757 | } | 8760 | } |
8758 | ret = btrfs_delalloc_reserve_space(inode, offset, count); | 8761 | ret = btrfs_delalloc_reserve_space(inode, offset, count); |
8759 | if (ret) | 8762 | if (ret) |