@@ -1936,6 +1936,46 @@ static inline void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatf
int __init fuse_bpf_init(void);
void __exit fuse_bpf_cleanup(void);
+static inline void fuse_bpf_set_in_ends(struct bpf_fuse_args *fa)
+{
+ int i;
+
+ for (i = 0; i < FUSE_MAX_ARGS_IN; i++)
+ fa->in_args[i].end_offset = (void *)
+ ((char *)fa->in_args[i].value
+ + fa->in_args[i].size);
+}
+
+static inline void fuse_bpf_set_in_immutable(struct bpf_fuse_args *fa)
+{
+ int i;
+
+ for (i = 0; i < FUSE_MAX_ARGS_IN; i++)
+ fa->in_args[i].flags |= BPF_FUSE_IMMUTABLE;
+}
+
+static inline void fuse_bpf_set_out_ends(struct bpf_fuse_args *fa)
+{
+ int i;
+
+ for (i = 0; i < FUSE_MAX_ARGS_OUT; i++)
+ fa->out_args[i].end_offset = (void *)
+ ((char *)fa->out_args[i].value
+ + fa->out_args[i].size);
+}
+
+static inline void fuse_bpf_free_alloced(struct bpf_fuse_args *fa)
+{
+ int i;
+
+ for (i = 0; i < FUSE_MAX_ARGS_IN; i++)
+ if (fa->in_args[i].flags & BPF_FUSE_ALLOCATED)
+ kfree(fa->in_args[i].value);
+ for (i = 0; i < FUSE_MAX_ARGS_OUT; i++)
+ if (fa->out_args[i].flags & BPF_FUSE_ALLOCATED)
+ kfree(fa->out_args[i].value);
+}
+
/*
* expression statement to wrap the backing filter logic
* struct inode *inode: inode with bpf and backing inode
@@ -1958,6 +1998,7 @@ void __exit fuse_bpf_cleanup(void);
bool initialized = false; \
bool handled = false; \
ssize_t res; \
+ int bpf_next; \
io feo = { 0 }; \
int error = 0; \
\
@@ -1969,17 +2010,47 @@ void __exit fuse_bpf_cleanup(void);
error = initialize_in(&fa, &feo, args); \
if (error) \
break; \
+ fuse_bpf_set_in_ends(&fa); \
+ \
+ fa.opcode |= FUSE_PREFILTER; \
+ bpf_next = fuse_inode->bpf ? \
+ bpf_prog_run(fuse_inode->bpf, &fa) : \
+ BPF_FUSE_CONTINUE; \
+ if (bpf_next < 0) { \
+ error = bpf_next; \
+ break; \
+ } \
+ \
+ fuse_bpf_set_in_immutable(&fa); \
\
error = initialize_out(&fa, &feo, args); \
if (error) \
break; \
+ fuse_bpf_set_out_ends(&fa); \
\
initialized = true; \
+ if (bpf_next == BPF_FUSE_USER) { \
+ handled = false; \
+ break; \
+ } \
+ \
+ fa.opcode &= ~FUSE_PREFILTER; \
\
error = backing(&fa, &out, args); \
if (error < 0) \
fa.error_in = error; \
\
+ if (bpf_next == BPF_FUSE_CONTINUE) \
+ break; \
+ \
+ fa.opcode |= FUSE_POSTFILTER; \
+ if (bpf_next == BPF_FUSE_POSTFILTER) \
+ bpf_next = bpf_prog_run(fuse_inode->bpf, &fa); \
+ if (bpf_next < 0) { \
+ error = bpf_next; \
+ break; \
+ } \
+ \
} while (false); \
\
if (initialized && handled) { \
@@ -1987,6 +2058,7 @@ void __exit fuse_bpf_cleanup(void);
if (res) \
error = res; \
} \
+ fuse_bpf_free_alloced(&fa); \
\
out = error ? _Generic((out), \
default : \