Loading fs/fuse/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -5,4 +5,4 @@ obj-$(CONFIG_FUSE_FS) += fuse.o obj-$(CONFIG_CUSE) += cuse.o fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o passthrough.o fs/fuse/dev.c +12 −3 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ */ #include "fuse_i.h" #include "fuse_passthrough.h" #include <linux/init.h> #include <linux/module.h> Loading Loading @@ -550,10 +551,15 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) args->out.numargs * sizeof(struct fuse_arg)); fuse_request_send(fc, req); ret = req->out.h.error; if (!ret && args->out.argvar) { BUG_ON(args->out.numargs != 1); if (!ret) { if (args->out.argvar) { WARN_ON(args->out.numargs != 1); ret = req->out.args[0].size; } if (req->passthrough_filp != NULL) args->out.passthrough_filp = req->passthrough_filp; } fuse_put_request(fc, req); return ret; Loading Loading @@ -1890,6 +1896,9 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, } fuse_copy_finish(cs); fuse_setup_passthrough(fc, req); spin_lock(&fpq->lock); clear_bit(FR_LOCKED, &req->flags); if (!fpq->connected) Loading fs/fuse/dir.c +3 −0 Original line number Diff line number Diff line Loading @@ -491,6 +491,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, args.out.args[0].value = &outentry; args.out.args[1].size = sizeof(outopen); args.out.args[1].value = &outopen; args.out.passthrough_filp = NULL; err = fuse_simple_request(fc, &args); if (err) goto out_free_ff; Loading @@ -502,6 +503,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, ff->fh = outopen.fh; ff->nodeid = outentry.nodeid; ff->open_flags = outopen.open_flags; if (args.out.passthrough_filp != NULL) ff->passthrough_filp = args.out.passthrough_filp; inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, &outentry.attr, entry_attr_timeout(&outentry), 0); if (!inode) { Loading fs/fuse/file.c +42 −5 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ */ #include "fuse_i.h" #include "fuse_passthrough.h" #include <linux/pagemap.h> #include <linux/slab.h> Loading @@ -21,8 +22,10 @@ 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) int opcode, struct fuse_open_out *outargp, struct file **passthrough_filpp) { int ret_val; struct fuse_open_in inarg; FUSE_ARGS(args); Loading @@ -38,8 +41,14 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, args.out.numargs = 1; args.out.args[0].size = sizeof(*outargp); args.out.args[0].value = outargp; args.out.passthrough_filp = NULL; return fuse_simple_request(fc, &args); ret_val = fuse_simple_request(fc, &args); if (args.out.passthrough_filp != NULL) *passthrough_filpp = args.out.passthrough_filp; return ret_val; } struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) Loading @@ -50,6 +59,11 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) if (unlikely(!ff)) return NULL; ff->passthrough_filp = NULL; ff->passthrough_enabled = 0; if (fc->passthrough) ff->passthrough_enabled = 1; ff->fc = fc; ff->reserved_req = fuse_request_alloc(0); if (unlikely(!ff->reserved_req)) { Loading Loading @@ -118,6 +132,7 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, bool isdir) { struct fuse_file *ff; struct file *passthrough_filp = NULL; int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; ff = fuse_file_alloc(fc); Loading @@ -130,11 +145,12 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, struct fuse_open_out outarg; int err; err = fuse_send_open(fc, nodeid, file, opcode, &outarg); err = fuse_send_open(fc, nodeid, file, opcode, &outarg, &(passthrough_filp)); if (!err) { ff->fh = outarg.fh; ff->open_flags = outarg.open_flags; ff->passthrough_filp = passthrough_filp; } else if (err != -ENOSYS || isdir) { fuse_file_free(ff); return err; Loading Loading @@ -253,6 +269,8 @@ void fuse_release_common(struct file *file, int opcode) if (unlikely(!ff)) return; fuse_passthrough_release(ff); req = ff->reserved_req; fuse_prepare_release(ff, file->f_flags, opcode); Loading Loading @@ -917,8 +935,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { ssize_t ret_val; struct inode *inode = iocb->ki_filp->f_mapping->host; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_file *ff = iocb->ki_filp->private_data; /* * In auto invalidate mode, always update attributes on read. Loading @@ -933,7 +953,12 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) return err; } return generic_file_read_iter(iocb, to); if (ff && ff->passthrough_enabled && ff->passthrough_filp) ret_val = fuse_passthrough_read_iter(iocb, to); else ret_val = generic_file_read_iter(iocb, to); return ret_val; } static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, Loading Loading @@ -1165,6 +1190,7 @@ static ssize_t fuse_perform_write(struct file *file, static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct fuse_file *ff = file->private_data; struct address_space *mapping = file->f_mapping; ssize_t written = 0; ssize_t written_buffered = 0; Loading Loading @@ -1198,6 +1224,11 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (err) goto out; if (ff && ff->passthrough_enabled && ff->passthrough_filp) { written = fuse_passthrough_write_iter(iocb, from); goto out; } if (iocb->ki_flags & IOCB_DIRECT) { loff_t pos = iocb->ki_pos; written = generic_file_direct_write(iocb, from); Loading Loading @@ -2069,6 +2100,9 @@ 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; ff->passthrough_enabled = 0; if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) fuse_link_write_file(file); Loading @@ -2079,6 +2113,9 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma) { struct fuse_file *ff = file->private_data; ff->passthrough_enabled = 0; /* Can't provide the coherency needed for MAP_SHARED */ if (vma->vm_flags & VM_MAYSHARE) return -ENODEV; Loading fs/fuse/fuse_i.h +11 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,10 @@ struct fuse_file { /** Has flock been performed on this file? */ bool flock:1; /* the read write file */ struct file *passthrough_filp; bool passthrough_enabled; }; /** One input argument of a request */ Loading Loading @@ -232,6 +236,7 @@ struct fuse_args { unsigned argvar:1; unsigned numargs; struct fuse_arg args[2]; struct file *passthrough_filp; } out; }; Loading Loading @@ -382,6 +387,9 @@ struct fuse_req { /** Request is stolen from fuse_file->reserved_req */ struct file *stolen_file; /** fuse passthrough file */ struct file *passthrough_filp; }; struct fuse_iqueue { Loading Loading @@ -542,6 +550,9 @@ struct fuse_conn { /** handle fs handles killing suid/sgid/cap on write/chown/trunc */ unsigned handle_killpriv:1; /** passthrough IO. */ unsigned passthrough:1; /* * The following bitfields are only for optimization purposes * and hence races in setting them will not cause malfunction Loading Loading
fs/fuse/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -5,4 +5,4 @@ obj-$(CONFIG_FUSE_FS) += fuse.o obj-$(CONFIG_CUSE) += cuse.o fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o passthrough.o
fs/fuse/dev.c +12 −3 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ */ #include "fuse_i.h" #include "fuse_passthrough.h" #include <linux/init.h> #include <linux/module.h> Loading Loading @@ -550,10 +551,15 @@ ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) args->out.numargs * sizeof(struct fuse_arg)); fuse_request_send(fc, req); ret = req->out.h.error; if (!ret && args->out.argvar) { BUG_ON(args->out.numargs != 1); if (!ret) { if (args->out.argvar) { WARN_ON(args->out.numargs != 1); ret = req->out.args[0].size; } if (req->passthrough_filp != NULL) args->out.passthrough_filp = req->passthrough_filp; } fuse_put_request(fc, req); return ret; Loading Loading @@ -1890,6 +1896,9 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, } fuse_copy_finish(cs); fuse_setup_passthrough(fc, req); spin_lock(&fpq->lock); clear_bit(FR_LOCKED, &req->flags); if (!fpq->connected) Loading
fs/fuse/dir.c +3 −0 Original line number Diff line number Diff line Loading @@ -491,6 +491,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, args.out.args[0].value = &outentry; args.out.args[1].size = sizeof(outopen); args.out.args[1].value = &outopen; args.out.passthrough_filp = NULL; err = fuse_simple_request(fc, &args); if (err) goto out_free_ff; Loading @@ -502,6 +503,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, ff->fh = outopen.fh; ff->nodeid = outentry.nodeid; ff->open_flags = outopen.open_flags; if (args.out.passthrough_filp != NULL) ff->passthrough_filp = args.out.passthrough_filp; inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, &outentry.attr, entry_attr_timeout(&outentry), 0); if (!inode) { Loading
fs/fuse/file.c +42 −5 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ */ #include "fuse_i.h" #include "fuse_passthrough.h" #include <linux/pagemap.h> #include <linux/slab.h> Loading @@ -21,8 +22,10 @@ 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) int opcode, struct fuse_open_out *outargp, struct file **passthrough_filpp) { int ret_val; struct fuse_open_in inarg; FUSE_ARGS(args); Loading @@ -38,8 +41,14 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, args.out.numargs = 1; args.out.args[0].size = sizeof(*outargp); args.out.args[0].value = outargp; args.out.passthrough_filp = NULL; return fuse_simple_request(fc, &args); ret_val = fuse_simple_request(fc, &args); if (args.out.passthrough_filp != NULL) *passthrough_filpp = args.out.passthrough_filp; return ret_val; } struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) Loading @@ -50,6 +59,11 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) if (unlikely(!ff)) return NULL; ff->passthrough_filp = NULL; ff->passthrough_enabled = 0; if (fc->passthrough) ff->passthrough_enabled = 1; ff->fc = fc; ff->reserved_req = fuse_request_alloc(0); if (unlikely(!ff->reserved_req)) { Loading Loading @@ -118,6 +132,7 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, bool isdir) { struct fuse_file *ff; struct file *passthrough_filp = NULL; int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; ff = fuse_file_alloc(fc); Loading @@ -130,11 +145,12 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, struct fuse_open_out outarg; int err; err = fuse_send_open(fc, nodeid, file, opcode, &outarg); err = fuse_send_open(fc, nodeid, file, opcode, &outarg, &(passthrough_filp)); if (!err) { ff->fh = outarg.fh; ff->open_flags = outarg.open_flags; ff->passthrough_filp = passthrough_filp; } else if (err != -ENOSYS || isdir) { fuse_file_free(ff); return err; Loading Loading @@ -253,6 +269,8 @@ void fuse_release_common(struct file *file, int opcode) if (unlikely(!ff)) return; fuse_passthrough_release(ff); req = ff->reserved_req; fuse_prepare_release(ff, file->f_flags, opcode); Loading Loading @@ -917,8 +935,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { ssize_t ret_val; struct inode *inode = iocb->ki_filp->f_mapping->host; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_file *ff = iocb->ki_filp->private_data; /* * In auto invalidate mode, always update attributes on read. Loading @@ -933,7 +953,12 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to) return err; } return generic_file_read_iter(iocb, to); if (ff && ff->passthrough_enabled && ff->passthrough_filp) ret_val = fuse_passthrough_read_iter(iocb, to); else ret_val = generic_file_read_iter(iocb, to); return ret_val; } static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, Loading Loading @@ -1165,6 +1190,7 @@ static ssize_t fuse_perform_write(struct file *file, static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct fuse_file *ff = file->private_data; struct address_space *mapping = file->f_mapping; ssize_t written = 0; ssize_t written_buffered = 0; Loading Loading @@ -1198,6 +1224,11 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (err) goto out; if (ff && ff->passthrough_enabled && ff->passthrough_filp) { written = fuse_passthrough_write_iter(iocb, from); goto out; } if (iocb->ki_flags & IOCB_DIRECT) { loff_t pos = iocb->ki_pos; written = generic_file_direct_write(iocb, from); Loading Loading @@ -2069,6 +2100,9 @@ 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; ff->passthrough_enabled = 0; if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) fuse_link_write_file(file); Loading @@ -2079,6 +2113,9 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma) { struct fuse_file *ff = file->private_data; ff->passthrough_enabled = 0; /* Can't provide the coherency needed for MAP_SHARED */ if (vma->vm_flags & VM_MAYSHARE) return -ENODEV; Loading
fs/fuse/fuse_i.h +11 −0 Original line number Diff line number Diff line Loading @@ -153,6 +153,10 @@ struct fuse_file { /** Has flock been performed on this file? */ bool flock:1; /* the read write file */ struct file *passthrough_filp; bool passthrough_enabled; }; /** One input argument of a request */ Loading Loading @@ -232,6 +236,7 @@ struct fuse_args { unsigned argvar:1; unsigned numargs; struct fuse_arg args[2]; struct file *passthrough_filp; } out; }; Loading Loading @@ -382,6 +387,9 @@ struct fuse_req { /** Request is stolen from fuse_file->reserved_req */ struct file *stolen_file; /** fuse passthrough file */ struct file *passthrough_filp; }; struct fuse_iqueue { Loading Loading @@ -542,6 +550,9 @@ struct fuse_conn { /** handle fs handles killing suid/sgid/cap on write/chown/trunc */ unsigned handle_killpriv:1; /** passthrough IO. */ unsigned passthrough:1; /* * The following bitfields are only for optimization purposes * and hence races in setting them will not cause malfunction Loading