fuse: multiplex cached/direct_io file operations
authorMiklos Szeredi <mszeredi@redhat.com>
Thu, 24 Jan 2019 09:40:17 +0000 (10:40 +0100)
committerMiklos Szeredi <mszeredi@redhat.com>
Wed, 13 Feb 2019 12:15:15 +0000 (13:15 +0100)
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>
fs/fuse/file.c

index c86266d..e5dfc5e 100644 (file)
@@ -19,8 +19,6 @@
 #include <linux/falloc.h>
 #include <linux/uio.h>
 
-static const struct file_operations fuse_direct_io_file_operations;
-
 static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
                          int opcode, struct fuse_open_out *outargp)
 {
@@ -174,8 +172,6 @@ void fuse_finish_open(struct inode *inode, struct file *file)
        struct fuse_file *ff = file->private_data;
        struct fuse_conn *fc = get_fuse_conn(inode);
 
-       if (ff->open_flags & FOPEN_DIRECT_IO)
-               file->f_op = &fuse_direct_io_file_operations;
        if (!(ff->open_flags & FOPEN_KEEP_CACHE))
                invalidate_inode_pages2(inode->i_mapping);
        if (ff->open_flags & FOPEN_NONSEEKABLE)
@@ -929,7 +925,7 @@ out:
        return err;
 }
 
-static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+static ssize_t fuse_cache_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
        struct inode *inode = iocb->ki_filp->f_mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
@@ -1183,7 +1179,7 @@ static ssize_t fuse_perform_write(struct kiocb *iocb,
        return res > 0 ? res : err;
 }
 
-static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
        struct file *file = iocb->ki_filp;
        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)
        return res;
 }
 
+static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+       struct fuse_file *ff = iocb->ki_filp->private_data;
+
+       if (!(ff->open_flags & FOPEN_DIRECT_IO))
+               return fuse_cache_read_iter(iocb, to);
+       else
+               return fuse_direct_read_iter(iocb, to);
+}
+
+static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+       struct fuse_file *ff = iocb->ki_filp->private_data;
+
+       if (!(ff->open_flags & FOPEN_DIRECT_IO))
+               return fuse_cache_write_iter(iocb, from);
+       else
+               return fuse_direct_write_iter(iocb, from);
+}
+
 static void fuse_writepage_free(struct fuse_conn *fc, struct fuse_req *req)
 {
        int i;
@@ -2129,6 +2145,18 @@ static const struct vm_operations_struct fuse_file_vm_ops = {
 
 static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
+       struct fuse_file *ff = file->private_data;
+
+       if (ff->open_flags & FOPEN_DIRECT_IO) {
+               /* Can't provide the coherency needed for MAP_SHARED */
+               if (vma->vm_flags & VM_MAYSHARE)
+                       return -ENODEV;
+
+               invalidate_inode_pages2(file->f_mapping);
+
+               return generic_file_mmap(file, vma);
+       }
+
        if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
                fuse_link_write_file(file);
 
@@ -2137,17 +2165,6 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       /* Can't provide the coherency needed for MAP_SHARED */
-       if (vma->vm_flags & VM_MAYSHARE)
-               return -ENODEV;
-
-       invalidate_inode_pages2(file->f_mapping);
-
-       return generic_file_mmap(file, vma);
-}
-
 static int convert_fuse_file_lock(struct fuse_conn *fc,
                                  const struct fuse_file_lock *ffl,
                                  struct file_lock *fl)
@@ -3164,26 +3181,6 @@ static const struct file_operations fuse_file_operations = {
        .copy_file_range = fuse_copy_file_range,
 };
 
-static const struct file_operations fuse_direct_io_file_operations = {
-       .llseek         = fuse_file_llseek,
-       .read_iter      = fuse_direct_read_iter,
-       .write_iter     = fuse_direct_write_iter,
-       .mmap           = fuse_direct_mmap,
-       .open           = fuse_open,
-       .flush          = fuse_flush,
-       .release        = fuse_release,
-       .fsync          = fuse_fsync,
-       .lock           = fuse_file_lock,
-       .flock          = fuse_file_flock,
-       .splice_read    = generic_file_splice_read,
-       .splice_write   = iter_file_splice_write,
-       .unlocked_ioctl = fuse_file_ioctl,
-       .compat_ioctl   = fuse_file_compat_ioctl,
-       .poll           = fuse_file_poll,
-       .fallocate      = fuse_file_fallocate,
-       .copy_file_range = fuse_copy_file_range,
-};
-
 static const struct address_space_operations fuse_file_aops  = {
        .readpage       = fuse_readpage,
        .writepage      = fuse_writepage,