ANDROID: fuse-bpf: Follow mounts in lookups
Bug: 292925770 Test: fuse_test run. The following steps on Android also now pass: Create /data/123 and /data/media/0/Android/data/45 directories Mount /data/123 directory to /data/media/0/Android/data/45 directory Create 1.txt under the /data/123 directory File 1.txt should appear in /storage/emulated/0/Android/data/45 Change-Id: I1fe27d743ca2981e624a9aa87d9ab6deb313aadc Signed-off-by: Paul Lawrence <paullawrence@google.com>
This commit is contained in:
parent
07775f9683
commit
613d8368e3
4 changed files with 85 additions and 6 deletions
|
|
@ -1117,7 +1117,6 @@ int fuse_lookup_backing(struct fuse_bpf_args *fa, struct inode *dir,
|
||||||
struct kstat stat;
|
struct kstat stat;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* TODO this will not handle lookups over mount points */
|
|
||||||
inode_lock_nested(dir_backing_inode, I_MUTEX_PARENT);
|
inode_lock_nested(dir_backing_inode, I_MUTEX_PARENT);
|
||||||
backing_entry = lookup_one_len(entry->d_name.name, dir_backing_entry,
|
backing_entry = lookup_one_len(entry->d_name.name, dir_backing_entry,
|
||||||
strlen(entry->d_name.name));
|
strlen(entry->d_name.name));
|
||||||
|
|
@ -1136,16 +1135,22 @@ int fuse_lookup_backing(struct fuse_bpf_args *fa, struct inode *dir,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = follow_down(&fuse_entry->backing_path);
|
||||||
|
if (err)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
err = vfs_getattr(&fuse_entry->backing_path, &stat,
|
err = vfs_getattr(&fuse_entry->backing_path, &stat,
|
||||||
STATX_BASIC_STATS, 0);
|
STATX_BASIC_STATS, 0);
|
||||||
if (err) {
|
if (err)
|
||||||
path_put_init(&fuse_entry->backing_path);
|
goto err_out;
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
fuse_stat_to_attr(get_fuse_conn(dir),
|
fuse_stat_to_attr(get_fuse_conn(dir),
|
||||||
backing_entry->d_inode, &stat, &feo->attr);
|
backing_entry->d_inode, &stat, &feo->attr);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
path_put_init(&fuse_entry->backing_path);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fuse_handle_backing(struct fuse_entry_bpf *feb, struct inode **backing_inode,
|
int fuse_handle_backing(struct fuse_entry_bpf *feb, struct inode **backing_inode,
|
||||||
|
|
|
||||||
|
|
@ -394,6 +394,29 @@ int s_rename(struct s oldpathname, struct s newpathname)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int s_mount(struct s source, struct s target, struct s filesystem,
|
||||||
|
unsigned long mountflags, struct s data)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = mount(source.s, target.s, filesystem.s, mountflags, data.s);
|
||||||
|
free(source.s);
|
||||||
|
free(target.s);
|
||||||
|
free(filesystem.s);
|
||||||
|
free(data.s);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int s_umount(struct s target)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = umount(target.s);
|
||||||
|
free(target.s);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int s_fuse_attr(struct s pathname, struct fuse_attr *fuse_attr_out)
|
int s_fuse_attr(struct s pathname, struct fuse_attr *fuse_attr_out)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -574,7 +597,10 @@ static int mount_fuse_maybe_init(const char *mount_dir, int bpf_fd, int dir_fd,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
*fuse_dev_ptr = fuse_dev;
|
if (fuse_dev_ptr)
|
||||||
|
*fuse_dev_ptr = fuse_dev;
|
||||||
|
else
|
||||||
|
TESTSYSCALL(close(fuse_dev));
|
||||||
fuse_dev = -1;
|
fuse_dev = -1;
|
||||||
result = TEST_SUCCESS;
|
result = TEST_SUCCESS;
|
||||||
out:
|
out:
|
||||||
|
|
|
||||||
|
|
@ -2114,6 +2114,50 @@ out:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that fuse passthrough correctly traverses a mount point on the lower fs
|
||||||
|
*/
|
||||||
|
static int bpf_test_follow_mounts(const char *mount_dir)
|
||||||
|
{
|
||||||
|
const char *bind_src = "bind_src";
|
||||||
|
const char *bind_dst = "bind_dst";
|
||||||
|
const char *file = "file";
|
||||||
|
int fd = -1;
|
||||||
|
int src_fd = -1;
|
||||||
|
int result = TEST_FAILURE;
|
||||||
|
|
||||||
|
TESTSYSCALL(s_mkdir(s_path(s(ft_src), s(bind_src)), 0777));
|
||||||
|
TESTSYSCALL(s_mkdir(s_path(s(ft_src), s(bind_dst)), 0777));
|
||||||
|
TEST(fd = s_creat(s_pathn(3, s(ft_src), s(bind_src), s(file)), 0777),
|
||||||
|
fd != -1);
|
||||||
|
TESTSYSCALL(close(fd));
|
||||||
|
fd = -1;
|
||||||
|
TESTSYSCALL(s_mount(s_path(s(ft_src), s(bind_src)),
|
||||||
|
s_path(s(ft_src), s(bind_dst)),
|
||||||
|
s(NULL), MS_BIND, s(NULL)));
|
||||||
|
TEST(src_fd = open(ft_src, O_DIRECTORY | O_RDONLY | O_CLOEXEC),
|
||||||
|
src_fd != -1);
|
||||||
|
TESTEQUAL(mount_fuse_no_init(mount_dir, -1, src_fd, NULL), 0);
|
||||||
|
TEST(fd = s_open(s_pathn(3, s(mount_dir), s(bind_src), s(file)),
|
||||||
|
O_RDONLY),
|
||||||
|
fd != -1);
|
||||||
|
TESTSYSCALL(close(fd));
|
||||||
|
fd = -1;
|
||||||
|
TEST(fd = s_open(s_pathn(3, s(mount_dir), s(bind_dst), s(file)),
|
||||||
|
O_RDONLY),
|
||||||
|
fd != -1);
|
||||||
|
TESTSYSCALL(close(fd));
|
||||||
|
fd = -1;
|
||||||
|
|
||||||
|
result = TEST_SUCCESS;
|
||||||
|
out:
|
||||||
|
umount(mount_dir);
|
||||||
|
close(src_fd);
|
||||||
|
s_umount(s_path(s(ft_src), s(bind_dst)));
|
||||||
|
close(fd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_range(const char *ranges, bool *run_test, size_t tests)
|
static void parse_range(const char *ranges, bool *run_test, size_t tests)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
@ -2244,6 +2288,7 @@ int main(int argc, char *argv[])
|
||||||
MAKE_TEST(bpf_test_create_and_remove_bpf),
|
MAKE_TEST(bpf_test_create_and_remove_bpf),
|
||||||
MAKE_TEST(bpf_test_mkdir_and_remove_bpf),
|
MAKE_TEST(bpf_test_mkdir_and_remove_bpf),
|
||||||
MAKE_TEST(bpf_test_readahead),
|
MAKE_TEST(bpf_test_readahead),
|
||||||
|
MAKE_TEST(bpf_test_follow_mounts),
|
||||||
};
|
};
|
||||||
#undef MAKE_TEST
|
#undef MAKE_TEST
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,9 @@ int s_setxattr(struct s pathname, const char name[], const void *value,
|
||||||
size_t size, int flags);
|
size_t size, int flags);
|
||||||
int s_removexattr(struct s pathname, const char name[]);
|
int s_removexattr(struct s pathname, const char name[]);
|
||||||
int s_rename(struct s oldpathname, struct s newpathname);
|
int s_rename(struct s oldpathname, struct s newpathname);
|
||||||
|
int s_mount(struct s source, struct s target, struct s filesystem,
|
||||||
|
unsigned long mountflags, struct s data);
|
||||||
|
int s_umount(struct s target);
|
||||||
|
|
||||||
struct s tracing_folder(void);
|
struct s tracing_folder(void);
|
||||||
int tracing_on(void);
|
int tracing_on(void);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue