ANDROID: fuse-bpf: Add bpf to negative fuse_dentry

Store the results of a negative lookup in the fuse_dentry so later
opcodes can use them to create files

Bug: 291705489
Test: fuse_test passes
Signed-off-by: Paul Lawrence <paullawrence@google.com>
Change-Id: I725e714a1d6ce43f24431d07c24e96349ef1a55c
This commit is contained in:
Paul Lawrence 2023-07-25 11:18:38 -07:00
parent 6aef06abba
commit 74d9daa59a
3 changed files with 43 additions and 32 deletions

View File

@ -1240,60 +1240,60 @@ int fuse_handle_bpf_prog(struct fuse_entry_bpf *feb, struct inode *parent,
struct dentry *fuse_lookup_finalize(struct fuse_bpf_args *fa, struct inode *dir,
struct dentry *entry, unsigned int flags)
{
struct fuse_dentry *fd;
struct dentry *bd;
struct fuse_dentry *fuse_entry;
struct dentry *backing_entry;
struct inode *inode = NULL, *backing_inode;
struct inode *d_inode = entry->d_inode;
struct inode *entry_inode = entry->d_inode;
struct fuse_entry_out *feo = fa->out_args[0].value;
struct fuse_entry_bpf_out *febo = fa->out_args[1].value;
struct fuse_entry_bpf *feb = container_of(febo, struct fuse_entry_bpf, out);
struct fuse_entry_bpf *feb = container_of(febo, struct fuse_entry_bpf,
out);
int error = -1;
u64 target_nodeid = 0;
struct dentry *ret;
struct dentry *ret = NULL;
fd = get_fuse_dentry(entry);
if (!fd) {
fuse_entry = get_fuse_dentry(entry);
if (!fuse_entry) {
ret = ERR_PTR(-EIO);
goto out;
}
bd = fd->backing_path.dentry;
if (!bd) {
backing_entry = fuse_entry->backing_path.dentry;
if (!backing_entry) {
ret = ERR_PTR(-ENOENT);
goto out;
}
backing_inode = bd->d_inode;
if (!backing_inode) {
ret = 0;
goto out;
}
if (entry_inode)
target_nodeid = get_fuse_inode(entry_inode)->nodeid;
if (d_inode)
target_nodeid = get_fuse_inode(d_inode)->nodeid;
backing_inode = backing_entry->d_inode;
if (backing_inode)
inode = fuse_iget_backing(dir->i_sb, target_nodeid,
backing_inode);
inode = fuse_iget_backing(dir->i_sb, target_nodeid, backing_inode);
if (!inode) {
ret = ERR_PTR(-EIO);
goto out;
}
error = fuse_handle_bpf_prog(feb, dir, &get_fuse_inode(inode)->bpf);
error = inode ?
fuse_handle_bpf_prog(feb, dir, &get_fuse_inode(inode)->bpf) :
fuse_handle_bpf_prog(feb, dir, &fuse_entry->bpf);
if (error) {
ret = ERR_PTR(error);
goto out;
}
error = fuse_handle_backing(feb, &get_fuse_inode(inode)->backing_inode, &fd->backing_path);
if (error) {
ret = ERR_PTR(error);
goto out;
}
if (inode) {
error = fuse_handle_backing(feb,
&get_fuse_inode(inode)->backing_inode,
&fuse_entry->backing_path);
if (error) {
ret = ERR_PTR(error);
goto out;
}
get_fuse_inode(inode)->nodeid = feo->nodeid;
ret = d_splice_alias(inode, entry);
if (!IS_ERR(ret))
inode = NULL;
get_fuse_inode(inode)->nodeid = feo->nodeid;
ret = d_splice_alias(inode, entry);
if (!IS_ERR(ret))
inode = NULL;
}
out:
iput(inode);
if (feb->backing_file)

View File

@ -364,9 +364,14 @@ static void fuse_dentry_release(struct dentry *dentry)
{
struct fuse_dentry *fd = dentry->d_fsdata;
#ifdef CONFIG_FUSE_BPF
if (fd && fd->backing_path.dentry)
path_put(&fd->backing_path);
if (fd && fd->bpf)
bpf_prog_put(fd->bpf);
#endif
kfree_rcu(fd, rcu);
}
#endif

View File

@ -76,7 +76,13 @@ struct fuse_dentry {
u64 time;
struct rcu_head rcu;
};
#ifdef CONFIG_FUSE_BPF
struct path backing_path;
/* bpf program *only* set for negative dentries */
struct bpf_prog *bpf;
#endif
};
static inline struct fuse_dentry *get_fuse_dentry(const struct dentry *entry)