Signed-off-by: Daniel Rosenberg <drosen@xxxxxxxxxx> Signed-off-by: Paul Lawrence <paullawrence@xxxxxxxxxx> --- fs/fuse/backing.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++ fs/fuse/dir.c | 8 ++++ fs/fuse/file.c | 17 +++++++ fs/fuse/fuse_i.h | 21 +++++++++ 4 files changed, 163 insertions(+) diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c index a31199064dc7..4fd7442c94a1 100644 --- a/fs/fuse/backing.c +++ b/fs/fuse/backing.c @@ -436,6 +436,49 @@ int fuse_release_finalize(struct bpf_fuse_args *fa, int *out, return 0; } +int fuse_flush_initialize_in(struct bpf_fuse_args *fa, struct fuse_flush_in *ffi, + struct file *file, fl_owner_t id) +{ + struct fuse_file *fuse_file = file->private_data; + + *ffi = (struct fuse_flush_in) { + .fh = fuse_file->fh, + }; + + *fa = (struct bpf_fuse_args) { + .nodeid = get_node_id(file->f_inode), + .opcode = FUSE_FLUSH, + .in_numargs = 1, + .in_args[0].size = sizeof(*ffi), + .in_args[0].value = ffi, + .flags = FUSE_BPF_FORCE, + }; + + return 0; +} + +int fuse_flush_initialize_out(struct bpf_fuse_args *fa, struct fuse_flush_in *ffi, + struct file *file, fl_owner_t id) +{ + return 0; +} + +int fuse_flush_backing(struct bpf_fuse_args *fa, int *out, struct file *file, fl_owner_t id) +{ + struct fuse_file *fuse_file = file->private_data; + struct file *backing_file = fuse_file->backing_file; + + *out = 0; + if (backing_file->f_op->flush) + *out = backing_file->f_op->flush(backing_file, id); + return *out; +} + +int fuse_flush_finalize(struct bpf_fuse_args *fa, int *out, struct file *file, fl_owner_t id) +{ + return 0; +} + int fuse_lseek_initialize_in(struct bpf_fuse_args *fa, struct fuse_lseek_io *flio, struct file *file, loff_t offset, int whence) { @@ -510,6 +553,80 @@ int fuse_lseek_finalize(struct bpf_fuse_args *fa, loff_t *out, return 0; } +int fuse_fsync_initialize_in(struct bpf_fuse_args *fa, struct fuse_fsync_in *ffi, + struct file *file, loff_t start, loff_t end, int datasync) +{ + struct fuse_file *fuse_file = file->private_data; + + *ffi = (struct fuse_fsync_in) { + .fh = fuse_file->fh, + .fsync_flags = datasync ? FUSE_FSYNC_FDATASYNC : 0, + }; + + *fa = (struct bpf_fuse_args) { + .nodeid = get_fuse_inode(file->f_inode)->nodeid, + .opcode = FUSE_FSYNC, + .in_numargs = 1, + .in_args[0].size = sizeof(*ffi), + .in_args[0].value = ffi, + .flags = FUSE_BPF_FORCE, + }; + + return 0; +} + +int fuse_fsync_initialize_out(struct bpf_fuse_args *fa, struct fuse_fsync_in *ffi, + struct file *file, loff_t start, loff_t end, int datasync) +{ + return 0; +} + +int fuse_fsync_backing(struct bpf_fuse_args *fa, int *out, + struct file *file, loff_t start, loff_t end, int datasync) +{ + struct fuse_file *fuse_file = file->private_data; + struct file *backing_file = fuse_file->backing_file; + const struct fuse_fsync_in *ffi = fa->in_args[0].value; + int new_datasync = (ffi->fsync_flags & FUSE_FSYNC_FDATASYNC) ? 1 : 0; + + *out = vfs_fsync(backing_file, new_datasync); + return 0; +} + +int fuse_fsync_finalize(struct bpf_fuse_args *fa, int *out, + struct file *file, loff_t start, loff_t end, int datasync) +{ + return 0; +} + +int fuse_dir_fsync_initialize_in(struct bpf_fuse_args *fa, struct fuse_fsync_in *ffi, + struct file *file, loff_t start, loff_t end, int datasync) +{ + struct fuse_file *fuse_file = file->private_data; + + *ffi = (struct fuse_fsync_in) { + .fh = fuse_file->fh, + .fsync_flags = datasync ? FUSE_FSYNC_FDATASYNC : 0, + }; + + *fa = (struct bpf_fuse_args) { + .nodeid = get_fuse_inode(file->f_inode)->nodeid, + .opcode = FUSE_FSYNCDIR, + .in_numargs = 1, + .in_args[0].size = sizeof(*ffi), + .in_args[0].value = ffi, + .flags = FUSE_BPF_FORCE, + }; + + return 0; +} + +int fuse_dir_fsync_initialize_out(struct bpf_fuse_args *fa, struct fuse_fsync_in *ffi, + struct file *file, loff_t start, loff_t end, int datasync) +{ + return 0; +} + static inline void fuse_bpf_aio_put(struct fuse_bpf_aio_req *aio_req) { if (refcount_dec_and_test(&aio_req->ref)) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index d8237b7a23f2..f159b9a6d305 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1638,6 +1638,14 @@ static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, if (fuse_is_bad(inode)) return -EIO; +#ifdef CONFIG_FUSE_BPF + if (fuse_bpf_backing(inode, struct fuse_fsync_in, err, + fuse_dir_fsync_initialize_in, fuse_dir_fsync_initialize_out, + fuse_fsync_backing, fuse_fsync_finalize, + file, start, end, datasync)) + return err; +#endif + if (fc->no_fsyncdir) return 0; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 443f1af8a431..fc8f8e3a06b3 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -513,6 +513,15 @@ static int fuse_flush(struct file *file, fl_owner_t id) FUSE_ARGS(args); int err; +#ifdef CONFIG_FUSE_BPF + if (fuse_bpf_backing(file->f_inode, struct fuse_flush_in, err, + fuse_flush_initialize_in, fuse_flush_initialize_out, + fuse_flush_backing, + fuse_flush_finalize, + file, id)) + return err; +#endif + if (fuse_is_bad(inode)) return -EIO; @@ -588,6 +597,14 @@ static int fuse_fsync(struct file *file, loff_t start, loff_t end, struct fuse_conn *fc = get_fuse_conn(inode); int err; +#ifdef CONFIG_FUSE_BPF + if (fuse_bpf_backing(inode, struct fuse_fsync_in, err, + fuse_fsync_initialize_in, fuse_fsync_initialize_out, + fuse_fsync_backing, fuse_fsync_finalize, + file, start, end, datasync)) + return err; +#endif + if (fuse_is_bad(inode)) return -EIO; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 8780a50be244..db769dd0a2e4 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1489,6 +1489,14 @@ int fuse_release_backing(struct bpf_fuse_args *fa, int *out, int fuse_release_finalize(struct bpf_fuse_args *fa, int *out, struct inode *inode, struct file *file); +int fuse_flush_initialize_in(struct bpf_fuse_args *fa, struct fuse_flush_in *ffi, + struct file *file, fl_owner_t id); +int fuse_flush_initialize_out(struct bpf_fuse_args *fa, struct fuse_flush_in *ffi, + struct file *file, fl_owner_t id); +int fuse_flush_backing(struct bpf_fuse_args *fa, int *out, struct file *file, fl_owner_t id); +int fuse_flush_finalize(struct bpf_fuse_args *fa, int *out, + struct file *file, fl_owner_t id); + struct fuse_lseek_io { struct fuse_lseek_in fli; struct fuse_lseek_out flo; @@ -1503,6 +1511,19 @@ int fuse_lseek_backing(struct bpf_fuse_args *fa, loff_t *out, struct file *file, int fuse_lseek_finalize(struct bpf_fuse_args *fa, loff_t *out, struct file *file, loff_t offset, int whence); +int fuse_fsync_initialize_in(struct bpf_fuse_args *fa, struct fuse_fsync_in *ffi, + struct file *file, loff_t start, loff_t end, int datasync); +int fuse_fsync_initialize_out(struct bpf_fuse_args *fa, struct fuse_fsync_in *ffi, + struct file *file, loff_t start, loff_t end, int datasync); +int fuse_fsync_backing(struct bpf_fuse_args *fa, int *out, + struct file *file, loff_t start, loff_t end, int datasync); +int fuse_fsync_finalize(struct bpf_fuse_args *fa, int *out, + struct file *file, loff_t start, loff_t end, int datasync); +int fuse_dir_fsync_initialize_in(struct bpf_fuse_args *fa, struct fuse_fsync_in *ffi, + struct file *file, loff_t start, loff_t end, int datasync); +int fuse_dir_fsync_initialize_out(struct bpf_fuse_args *fa, struct fuse_fsync_in *ffi, + struct file *file, loff_t start, loff_t end, int datasync); + struct fuse_read_iter_out { uint64_t ret; }; -- 2.37.3.998.g577e59143f-goog