diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2019-01-24 04:40:17 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2019-02-13 07:15:15 -0500 |
commit | 55752a3aba1387887afa024a0732f8ae52fb0645 (patch) | |
tree | 2c1297d1783cfaa428d303c758e1f843050ee82b | |
parent | d4136d60751a5f45f47f1c3a77f6e8bafa11be1f (diff) |
fuse: multiplex cached/direct_io file operations
This is cleanup, as well as allowing switching between I/O modes while the
file is open in the future.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r-- | fs/fuse/file.c | 71 |
1 files changed, 34 insertions, 37 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index c86266d4eac3..e5dfc5e4b999 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -19,8 +19,6 @@ | |||
19 | #include <linux/falloc.h> | 19 | #include <linux/falloc.h> |
20 | #include <linux/uio.h> | 20 | #include <linux/uio.h> |
21 | 21 | ||
22 | static const struct file_operations fuse_direct_io_file_operations; | ||
23 | |||
24 | static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | 22 | static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
25 | int opcode, struct fuse_open_out *outargp) | 23 | int opcode, struct fuse_open_out *outargp) |
26 | { | 24 | { |
@@ -174,8 +172,6 @@ void fuse_finish_open(struct inode *inode, struct file *file) | |||
174 | struct fuse_file *ff = file->private_data; | 172 | struct fuse_file *ff = file->private_data; |
175 | struct fuse_conn *fc = get_fuse_conn(inode); | 173 | struct fuse_conn *fc = get_fuse_conn(inode); |
176 | 174 | ||
177 | if (ff->open_flags & FOPEN_DIRECT_IO) | ||
178 | file->f_op = &fuse_direct_io_file_operations; | ||
179 | if (!(ff->open_flags & FOPEN_KEEP_CACHE)) | 175 | if (!(ff->open_flags & FOPEN_KEEP_CACHE)) |
180 | invalidate_inode_pages2(inode->i_mapping); | 176 | invalidate_inode_pages2(inode->i_mapping); |
181 | if (ff->open_flags & FOPEN_NONSEEKABLE) | 177 | if (ff->open_flags & FOPEN_NONSEEKABLE) |
@@ -929,7 +925,7 @@ out: | |||
929 | return err; | 925 | return err; |
930 | } | 926 | } |
931 | 927 | ||
932 | static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) | 928 | static ssize_t fuse_cache_read_iter(struct kiocb *iocb, struct iov_iter *to) |
933 | { | 929 | { |
934 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 930 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
935 | struct fuse_conn *fc = get_fuse_conn(inode); | 931 | struct fuse_conn *fc = get_fuse_conn(inode); |
@@ -1183,7 +1179,7 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, | |||
1183 | return res > 0 ? res : err; | 1179 | return res > 0 ? res : err; |
1184 | } | 1180 | } |
1185 | 1181 | ||
1186 | static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | 1182 | static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from) |
1187 | { | 1183 | { |
1188 | struct file *file = iocb->ki_filp; | 1184 | struct file *file = iocb->ki_filp; |
1189 | struct address_space *mapping = file->f_mapping; | 1185 | struct address_space *mapping = file->f_mapping; |
@@ -1486,6 +1482,26 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
1486 | return res; | 1482 | return res; |
1487 | } | 1483 | } |
1488 | 1484 | ||
1485 | static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) | ||
1486 | { | ||
1487 | struct fuse_file *ff = iocb->ki_filp->private_data; | ||
1488 | |||
1489 | if (!(ff->open_flags & FOPEN_DIRECT_IO)) | ||
1490 | return fuse_cache_read_iter(iocb, to); | ||
1491 | else | ||
1492 | return fuse_direct_read_iter(iocb, to); | ||
1493 | } | ||
1494 | |||
1495 | static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | ||
1496 | { | ||
1497 | struct fuse_file *ff = iocb->ki_filp->private_data; | ||
1498 | |||
1499 | if (!(ff->open_flags & FOPEN_DIRECT_IO)) | ||
1500 | return fuse_cache_write_iter(iocb, from); | ||
1501 | else | ||
1502 | return fuse_direct_write_iter(iocb, from); | ||
1503 | } | ||
1504 | |||
1489 | static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) | 1505 | static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req) |
1490 | { | 1506 | { |
1491 | int i; | 1507 | int i; |
@@ -2129,6 +2145,18 @@ static const struct vm_operations_struct fuse_file_vm_ops = { | |||
2129 | 2145 | ||
2130 | static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) | 2146 | static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) |
2131 | { | 2147 | { |
2148 | struct fuse_file *ff = file->private_data; | ||
2149 | |||
2150 | if (ff->open_flags & FOPEN_DIRECT_IO) { | ||
2151 | /* Can't provide the coherency needed for MAP_SHARED */ | ||
2152 | if (vma->vm_flags & VM_MAYSHARE) | ||
2153 | return -ENODEV; | ||
2154 | |||
2155 | invalidate_inode_pages2(file->f_mapping); | ||
2156 | |||
2157 | return generic_file_mmap(file, vma); | ||
2158 | } | ||
2159 | |||
2132 | if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) | 2160 | if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) |
2133 | fuse_link_write_file(file); | 2161 | fuse_link_write_file(file); |
2134 | 2162 | ||
@@ -2137,17 +2165,6 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
2137 | return 0; | 2165 | return 0; |
2138 | } | 2166 | } |
2139 | 2167 | ||
2140 | static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma) | ||
2141 | { | ||
2142 | /* Can't provide the coherency needed for MAP_SHARED */ | ||
2143 | if (vma->vm_flags & VM_MAYSHARE) | ||
2144 | return -ENODEV; | ||
2145 | |||
2146 | invalidate_inode_pages2(file->f_mapping); | ||
2147 | |||
2148 | return generic_file_mmap(file, vma); | ||
2149 | } | ||
2150 | |||
2151 | static int convert_fuse_file_lock(struct fuse_conn *fc, | 2168 | static int convert_fuse_file_lock(struct fuse_conn *fc, |
2152 | const struct fuse_file_lock *ffl, | 2169 | const struct fuse_file_lock *ffl, |
2153 | struct file_lock *fl) | 2170 | struct file_lock *fl) |
@@ -3164,26 +3181,6 @@ static const struct file_operations fuse_file_operations = { | |||
3164 | .copy_file_range = fuse_copy_file_range, | 3181 | .copy_file_range = fuse_copy_file_range, |
3165 | }; | 3182 | }; |
3166 | 3183 | ||
3167 | static const struct file_operations fuse_direct_io_file_operations = { | ||
3168 | .llseek = fuse_file_llseek, | ||
3169 | .read_iter = fuse_direct_read_iter, | ||
3170 | .write_iter = fuse_direct_write_iter, | ||
3171 | .mmap = fuse_direct_mmap, | ||
3172 | .open = fuse_open, | ||
3173 | .flush = fuse_flush, | ||
3174 | .release = fuse_release, | ||
3175 | .fsync = fuse_fsync, | ||
3176 | .lock = fuse_file_lock, | ||
3177 | .flock = fuse_file_flock, | ||
3178 | .splice_read = generic_file_splice_read, | ||
3179 | .splice_write = iter_file_splice_write, | ||
3180 | .unlocked_ioctl = fuse_file_ioctl, | ||
3181 | .compat_ioctl = fuse_file_compat_ioctl, | ||
3182 | .poll = fuse_file_poll, | ||
3183 | .fallocate = fuse_file_fallocate, | ||
3184 | .copy_file_range = fuse_copy_file_range, | ||
3185 | }; | ||
3186 | |||
3187 | static const struct address_space_operations fuse_file_aops = { | 3184 | static const struct address_space_operations fuse_file_aops = { |
3188 | .readpage = fuse_readpage, | 3185 | .readpage = fuse_readpage, |
3189 | .writepage = fuse_writepage, | 3186 | .writepage = fuse_writepage, |