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 fuse-objs := dev.o dir.o file.o inode.o control.o shortcircuit.o fs/fuse/dev.c +3 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ */ #include "fuse_i.h" #include "fuse_shortcircuit.h" #include <linux/init.h> #include <linux/module.h> Loading Loading @@ -1867,6 +1868,8 @@ static ssize_t fuse_dev_do_write(struct fuse_conn *fc, err = copy_out_args(cs, &req->out, nbytes); fuse_copy_finish(cs); fuse_setup_shortcircuit(fc, req); spin_lock(&fc->lock); req->locked = 0; if (!err) { Loading fs/fuse/dir.c +3 −0 Original line number Diff line number Diff line Loading @@ -460,6 +460,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, if (err) goto out_free_ff; if (req->private_lower_rw_file != NULL) ff->rw_lower_file = req->private_lower_rw_file; err = -EIO; if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) goto out_free_ff; Loading fs/fuse/file.c +30 −3 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ */ #include "fuse_i.h" #include "fuse_shortcircuit.h" #include <linux/pagemap.h> #include <linux/slab.h> Loading @@ -21,7 +22,8 @@ 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 **lower_file) { struct fuse_open_in inarg; struct fuse_req *req; Loading @@ -45,6 +47,10 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, req->out.args[0].value = outargp; fuse_request_send(fc, req); err = req->out.h.error; if (!err && req->private_lower_rw_file != NULL) *lower_file = req->private_lower_rw_file; fuse_put_request(fc, req); return err; Loading @@ -58,6 +64,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) if (unlikely(!ff)) return NULL; ff->rw_lower_file = NULL; ff->fc = fc; ff->reserved_req = fuse_request_alloc(0); if (unlikely(!ff->reserved_req)) { Loading Loading @@ -165,7 +172,8 @@ 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, &(ff->rw_lower_file)); if (!err) { ff->fh = outarg.fh; ff->open_flags = outarg.open_flags; Loading Loading @@ -288,6 +296,8 @@ void fuse_release_common(struct file *file, int opcode) if (unlikely(!ff)) return; fuse_shortcircuit_release(ff); req = ff->reserved_req; fuse_prepare_release(ff, file->f_flags, opcode); Loading Loading @@ -935,8 +945,10 @@ out: 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 @@ -951,7 +963,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->rw_lower_file) ret_val = fuse_shortcircuit_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 @@ -1184,6 +1201,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct address_space *mapping = file->f_mapping; struct fuse_file *ff = file->private_data; size_t count = iov_iter_count(from); ssize_t written = 0; ssize_t written_buffered = 0; Loading @@ -1192,6 +1210,15 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) loff_t endbyte = 0; loff_t pos = iocb->ki_pos; if (ff && ff->rw_lower_file) { /* Update size (EOF optimization) and mode (SUID clearing) */ err = fuse_update_attributes(mapping->host, NULL, file, NULL); if (err) return err; return fuse_shortcircuit_write_iter(iocb, from); } if (get_fuse_conn(inode)->writeback_cache) { /* Update size (EOF optimization) and mode (SUID clearing) */ err = fuse_update_attributes(mapping->host, NULL, file, NULL); Loading fs/fuse/fuse_i.h +9 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,9 @@ struct fuse_file { /** Has flock been performed on this file? */ bool flock:1; /* the read write file */ struct file *rw_lower_file; }; /** One input argument of a request */ Loading Loading @@ -362,6 +365,9 @@ struct fuse_req { /** Request is stolen from fuse_file->reserved_req */ struct file *stolen_file; /** fuse shortcircuit file */ struct file *private_lower_rw_file; }; /** Loading Loading @@ -483,6 +489,9 @@ struct fuse_conn { /** write-back cache policy (default is write-through) */ unsigned writeback_cache:1; /** Shortcircuited IO. */ unsigned shortcircuit_io: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 fuse-objs := dev.o dir.o file.o inode.o control.o shortcircuit.o
fs/fuse/dev.c +3 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ */ #include "fuse_i.h" #include "fuse_shortcircuit.h" #include <linux/init.h> #include <linux/module.h> Loading Loading @@ -1867,6 +1868,8 @@ static ssize_t fuse_dev_do_write(struct fuse_conn *fc, err = copy_out_args(cs, &req->out, nbytes); fuse_copy_finish(cs); fuse_setup_shortcircuit(fc, req); spin_lock(&fc->lock); req->locked = 0; if (!err) { Loading
fs/fuse/dir.c +3 −0 Original line number Diff line number Diff line Loading @@ -460,6 +460,9 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, if (err) goto out_free_ff; if (req->private_lower_rw_file != NULL) ff->rw_lower_file = req->private_lower_rw_file; err = -EIO; if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) goto out_free_ff; Loading
fs/fuse/file.c +30 −3 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ */ #include "fuse_i.h" #include "fuse_shortcircuit.h" #include <linux/pagemap.h> #include <linux/slab.h> Loading @@ -21,7 +22,8 @@ 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 **lower_file) { struct fuse_open_in inarg; struct fuse_req *req; Loading @@ -45,6 +47,10 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, req->out.args[0].value = outargp; fuse_request_send(fc, req); err = req->out.h.error; if (!err && req->private_lower_rw_file != NULL) *lower_file = req->private_lower_rw_file; fuse_put_request(fc, req); return err; Loading @@ -58,6 +64,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) if (unlikely(!ff)) return NULL; ff->rw_lower_file = NULL; ff->fc = fc; ff->reserved_req = fuse_request_alloc(0); if (unlikely(!ff->reserved_req)) { Loading Loading @@ -165,7 +172,8 @@ 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, &(ff->rw_lower_file)); if (!err) { ff->fh = outarg.fh; ff->open_flags = outarg.open_flags; Loading Loading @@ -288,6 +296,8 @@ void fuse_release_common(struct file *file, int opcode) if (unlikely(!ff)) return; fuse_shortcircuit_release(ff); req = ff->reserved_req; fuse_prepare_release(ff, file->f_flags, opcode); Loading Loading @@ -935,8 +945,10 @@ out: 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 @@ -951,7 +963,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->rw_lower_file) ret_val = fuse_shortcircuit_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 @@ -1184,6 +1201,7 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct address_space *mapping = file->f_mapping; struct fuse_file *ff = file->private_data; size_t count = iov_iter_count(from); ssize_t written = 0; ssize_t written_buffered = 0; Loading @@ -1192,6 +1210,15 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) loff_t endbyte = 0; loff_t pos = iocb->ki_pos; if (ff && ff->rw_lower_file) { /* Update size (EOF optimization) and mode (SUID clearing) */ err = fuse_update_attributes(mapping->host, NULL, file, NULL); if (err) return err; return fuse_shortcircuit_write_iter(iocb, from); } if (get_fuse_conn(inode)->writeback_cache) { /* Update size (EOF optimization) and mode (SUID clearing) */ err = fuse_update_attributes(mapping->host, NULL, file, NULL); Loading
fs/fuse/fuse_i.h +9 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,9 @@ struct fuse_file { /** Has flock been performed on this file? */ bool flock:1; /* the read write file */ struct file *rw_lower_file; }; /** One input argument of a request */ Loading Loading @@ -362,6 +365,9 @@ struct fuse_req { /** Request is stolen from fuse_file->reserved_req */ struct file *stolen_file; /** fuse shortcircuit file */ struct file *private_lower_rw_file; }; /** Loading Loading @@ -483,6 +489,9 @@ struct fuse_conn { /** write-back cache policy (default is write-through) */ unsigned writeback_cache:1; /** Shortcircuited IO. */ unsigned shortcircuit_io:1; /* * The following bitfields are only for optimization purposes * and hence races in setting them will not cause malfunction Loading