ANDROID: fuse-bpf: Support fuse_splice_read/write fully

Need to support fuse_splice_read and fuse_splice_write in both fuse bpf
and fuse passthrough modes.

Bug: 349258571
Test: fuse_test
Change-Id: I641b917d3decc4be1eea7ea39fac2b1f50c7e41b
Signed-off-by: Paul Lawrence <paullawrence@google.com>
This commit is contained in:
Paul Lawrence
2024-07-02 12:11:06 -07:00
parent 9b1c948200
commit 41d9adb6ec
4 changed files with 81 additions and 1 deletions
+16
View File
@@ -1001,6 +1001,22 @@ ssize_t fuse_splice_read_backing(struct file *in, loff_t *ppos,
return ret;
}
ssize_t fuse_splice_write_backing(struct pipe_inode_info *pipe,
struct file *out, loff_t *ppos, size_t len, unsigned long flags)
{
ssize_t ret;
struct fuse_file *ff = out->private_data;
inode_lock(file_inode(out));
file_start_write(ff->backing_file);
ret = iter_file_splice_write(pipe, ff->backing_file, ppos, len, flags);
file_end_write(ff->backing_file);
if (ret > 0)
fuse_copyattr(out, ff->backing_file);
inode_unlock(file_inode(out));
return ret;
}
long fuse_backing_ioctl(struct file *file, unsigned int command, unsigned long arg, int flags)
{
struct fuse_file *ff = file->private_data;
+8 -1
View File
@@ -15,6 +15,7 @@
#include <linux/sched.h>
#include <linux/sched/signal.h>
#include <linux/module.h>
#include <linux/splice.h>
#include <linux/swap.h>
#include <linux/falloc.h>
#include <linux/uio.h>
@@ -1843,9 +1844,9 @@ static ssize_t fuse_splice_read(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len,
unsigned int flags)
{
#ifdef CONFIG_FUSE_BPF
struct fuse_file *ff = in->private_data;
#ifdef CONFIG_FUSE_BPF
/* TODO - this is simply passthrough, not a proper BPF filter */
if (ff->backing_file)
return fuse_splice_read_backing(in, ppos, pipe, len, flags);
@@ -1863,6 +1864,12 @@ static ssize_t fuse_splice_write(struct pipe_inode_info *pipe, struct file *out,
{
struct fuse_file *ff = out->private_data;
#ifdef CONFIG_FUSE_BPF
/* TODO - this is simply passthrough, not a proper BPF filter */
if (ff->backing_file)
return fuse_splice_write_backing(pipe, out, ppos, len, flags);
#endif
/* 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);
+2
View File
@@ -1815,6 +1815,8 @@ void *fuse_file_write_iter_finalize(struct fuse_bpf_args *fa,
ssize_t fuse_splice_read_backing(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len, unsigned long flags);
ssize_t fuse_splice_write_backing(struct pipe_inode_info *pipe,
struct file *out, loff_t *ppos, size_t len, unsigned long flags);
long fuse_backing_ioctl(struct file *file, unsigned int command, unsigned long arg, int flags);
@@ -2114,6 +2114,60 @@ out:
return result;
}
static int splice_test(const char *mount_dir)
{
const char *in_name = "in";
const char *out_name = "out";
const int splice_size = 4096;
int result = TEST_FAILURE;
int file_fd = -1;
int src_fd = -1;
int fuse_dev = -1;
int in_fd = -1;
int out_fd = -1;
int pipefd[2] = {-1, -1};
TEST(file_fd = s_creat(s_path(s(ft_src), s(in_name)), 0777),
file_fd != -1);
TESTSYSCALL(fallocate(file_fd, 0, 0, splice_size));
TESTSYSCALL(close(file_fd));
file_fd = -1;
TEST(src_fd = open(ft_src, O_DIRECTORY | O_RDONLY | O_CLOEXEC),
src_fd != -1);
TEST(fuse_dev = open("/dev/fuse", O_RDWR | O_CLOEXEC), fuse_dev != -1);
TESTEQUAL(mount_fuse(mount_dir, -1, src_fd, &fuse_dev), 0);
TESTSYSCALL(pipe(pipefd));
TEST(in_fd = s_open(s_path(s(mount_dir), s(in_name)), O_RDONLY),
in_fd != -1);
TEST(out_fd = s_creat(s_path(s(mount_dir), s(out_name)), 0777),
out_fd != -1);
TESTEQUAL(splice(in_fd, NULL, pipefd[1], NULL, splice_size, 0),
splice_size);
TESTEQUAL(splice(pipefd[0], NULL, out_fd, NULL, splice_size, 0),
splice_size);
TESTSYSCALL(close(in_fd));
in_fd = -1;
TESTSYSCALL(close(out_fd));
out_fd = -1;
TESTSYSCALL(close(pipefd[0]));
pipefd[0] = -1;
TESTSYSCALL(close(pipefd[1]));
pipefd[1] = -1;
result = TEST_SUCCESS;
out:
umount(mount_dir);
close(fuse_dev);
close(src_fd);
close(in_fd);
close(out_fd);
close(pipefd[0]);
close(pipefd[1]);
return result;
}
/**
* Test that fuse passthrough correctly traverses a mount point on the lower fs
*/
@@ -2288,6 +2342,7 @@ int main(int argc, char *argv[])
MAKE_TEST(bpf_test_create_and_remove_bpf),
MAKE_TEST(bpf_test_mkdir_and_remove_bpf),
MAKE_TEST(bpf_test_readahead),
MAKE_TEST(splice_test),
MAKE_TEST(bpf_test_follow_mounts),
};
#undef MAKE_TEST