Loading fs/fuse/file.c +27 −2 Original line number Diff line number Diff line Loading @@ -1723,6 +1723,31 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) return fuse_cache_write_iter(iocb, from); } static ssize_t fuse_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { struct fuse_file *ff = in->private_data; /* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */ if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO)) return fuse_passthrough_splice_read(in, ppos, pipe, len, flags); else return filemap_splice_read(in, ppos, pipe, len, flags); } static ssize_t fuse_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { struct fuse_file *ff = out->private_data; /* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */ if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO)) return fuse_passthrough_splice_write(pipe, out, ppos, len, flags); else return iter_file_splice_write(pipe, out, ppos, len, flags); } static void fuse_writepage_free(struct fuse_writepage_args *wpa) { struct fuse_args_pages *ap = &wpa->ia.ap; Loading Loading @@ -3303,8 +3328,8 @@ static const struct file_operations fuse_file_operations = { .lock = fuse_file_lock, .get_unmapped_area = thp_get_unmapped_area, .flock = fuse_file_flock, .splice_read = filemap_splice_read, .splice_write = iter_file_splice_write, .splice_read = fuse_splice_read, .splice_write = fuse_splice_write, .unlocked_ioctl = fuse_file_ioctl, .compat_ioctl = fuse_file_compat_ioctl, .poll = fuse_file_poll, Loading fs/fuse/fuse_i.h +6 −0 Original line number Diff line number Diff line Loading @@ -1468,5 +1468,11 @@ static inline struct file *fuse_file_passthrough(struct fuse_file *ff) ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *iter); ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *iter); ssize_t fuse_passthrough_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); ssize_t fuse_passthrough_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags); #endif /* _FS_FUSE_I_H */ fs/fuse/passthrough.c +45 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include <linux/file.h> #include <linux/backing-file.h> #include <linux/splice.h> static void fuse_file_accessed(struct file *file) { Loading Loading @@ -79,6 +80,50 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, return ret; } ssize_t fuse_passthrough_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { struct fuse_file *ff = in->private_data; struct file *backing_file = fuse_file_passthrough(ff); struct backing_file_ctx ctx = { .cred = ff->cred, .user_file = in, .accessed = fuse_file_accessed, }; pr_debug("%s: backing_file=0x%p, pos=%lld, len=%zu, flags=0x%x\n", __func__, backing_file, ppos ? *ppos : 0, len, flags); return backing_file_splice_read(backing_file, ppos, pipe, len, flags, &ctx); } ssize_t fuse_passthrough_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { struct fuse_file *ff = out->private_data; struct file *backing_file = fuse_file_passthrough(ff); struct inode *inode = file_inode(out); ssize_t ret; struct backing_file_ctx ctx = { .cred = ff->cred, .user_file = out, .end_write = fuse_file_modified, }; pr_debug("%s: backing_file=0x%p, pos=%lld, len=%zu, flags=0x%x\n", __func__, backing_file, ppos ? *ppos : 0, len, flags); inode_lock(inode); ret = backing_file_splice_write(pipe, backing_file, ppos, len, flags, &ctx); inode_unlock(inode); return ret; } struct fuse_backing *fuse_backing_get(struct fuse_backing *fb) { if (fb && refcount_inc_not_zero(&fb->count)) Loading Loading
fs/fuse/file.c +27 −2 Original line number Diff line number Diff line Loading @@ -1723,6 +1723,31 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from) return fuse_cache_write_iter(iocb, from); } static ssize_t fuse_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { struct fuse_file *ff = in->private_data; /* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */ if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO)) return fuse_passthrough_splice_read(in, ppos, pipe, len, flags); else return filemap_splice_read(in, ppos, pipe, len, flags); } static ssize_t fuse_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { struct fuse_file *ff = out->private_data; /* FOPEN_DIRECT_IO overrides FOPEN_PASSTHROUGH */ if (fuse_file_passthrough(ff) && !(ff->open_flags & FOPEN_DIRECT_IO)) return fuse_passthrough_splice_write(pipe, out, ppos, len, flags); else return iter_file_splice_write(pipe, out, ppos, len, flags); } static void fuse_writepage_free(struct fuse_writepage_args *wpa) { struct fuse_args_pages *ap = &wpa->ia.ap; Loading Loading @@ -3303,8 +3328,8 @@ static const struct file_operations fuse_file_operations = { .lock = fuse_file_lock, .get_unmapped_area = thp_get_unmapped_area, .flock = fuse_file_flock, .splice_read = filemap_splice_read, .splice_write = iter_file_splice_write, .splice_read = fuse_splice_read, .splice_write = fuse_splice_write, .unlocked_ioctl = fuse_file_ioctl, .compat_ioctl = fuse_file_compat_ioctl, .poll = fuse_file_poll, Loading
fs/fuse/fuse_i.h +6 −0 Original line number Diff line number Diff line Loading @@ -1468,5 +1468,11 @@ static inline struct file *fuse_file_passthrough(struct fuse_file *ff) ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *iter); ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *iter); ssize_t fuse_passthrough_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); ssize_t fuse_passthrough_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags); #endif /* _FS_FUSE_I_H */
fs/fuse/passthrough.c +45 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include <linux/file.h> #include <linux/backing-file.h> #include <linux/splice.h> static void fuse_file_accessed(struct file *file) { Loading Loading @@ -79,6 +80,50 @@ ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, return ret; } ssize_t fuse_passthrough_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { struct fuse_file *ff = in->private_data; struct file *backing_file = fuse_file_passthrough(ff); struct backing_file_ctx ctx = { .cred = ff->cred, .user_file = in, .accessed = fuse_file_accessed, }; pr_debug("%s: backing_file=0x%p, pos=%lld, len=%zu, flags=0x%x\n", __func__, backing_file, ppos ? *ppos : 0, len, flags); return backing_file_splice_read(backing_file, ppos, pipe, len, flags, &ctx); } ssize_t fuse_passthrough_splice_write(struct pipe_inode_info *pipe, struct file *out, loff_t *ppos, size_t len, unsigned int flags) { struct fuse_file *ff = out->private_data; struct file *backing_file = fuse_file_passthrough(ff); struct inode *inode = file_inode(out); ssize_t ret; struct backing_file_ctx ctx = { .cred = ff->cred, .user_file = out, .end_write = fuse_file_modified, }; pr_debug("%s: backing_file=0x%p, pos=%lld, len=%zu, flags=0x%x\n", __func__, backing_file, ppos ? *ppos : 0, len, flags); inode_lock(inode); ret = backing_file_splice_write(pipe, backing_file, ppos, len, flags, &ctx); inode_unlock(inode); return ret; } struct fuse_backing *fuse_backing_get(struct fuse_backing *fb) { if (fb && refcount_inc_not_zero(&fb->count)) Loading