ANDROID: fuse-bpf: Add partial flock support

This adds passthrough support for flock on fuse-bpf files. It does not
give any control via a bpf filter. The flock will act as though it was
taken on the lower file.

Bug: 289882899
Test: fuse_test -t32 (flock_test)
Change-Id: Iba0b9630766cedbd3195532c5e929891593cfe30
Signed-off-by: Daniel Rosenberg <drosen@google.com>
This commit is contained in:
Daniel Rosenberg 2023-07-07 16:07:09 -07:00 committed by Todd Kjos
parent 9b655e9328
commit 6c695fad68
4 changed files with 68 additions and 1 deletions

View File

@ -966,6 +966,20 @@ void *fuse_file_write_iter_finalize(struct fuse_bpf_args *fa,
return ERR_PTR(fwio->ret);
}
int fuse_file_flock_backing(struct file *file, int cmd, struct file_lock *fl)
{
struct fuse_file *ff = file->private_data;
struct file *backing_file = ff->backing_file;
int error;
fl->fl_file = backing_file;
if (backing_file->f_op->flock)
error = backing_file->f_op->flock(backing_file, cmd, fl);
else
error = locks_lock_file_wait(backing_file, fl);
return error;
}
ssize_t fuse_backing_mmap(struct file *file, struct vm_area_struct *vma)
{
int ret;

View File

@ -2695,12 +2695,18 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
{
struct inode *inode = file_inode(file);
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
int err;
#ifdef CONFIG_FUSE_BPF
/* TODO - this is simply passthrough, not a proper BPF filter */
if (ff->backing_file)
return fuse_file_flock_backing(file, cmd, fl);
#endif
if (fc->no_flock) {
err = locks_lock_file_wait(file, fl);
} else {
struct fuse_file *ff = file->private_data;
/* emulate flock with POSIX locks */
ff->flock = true;

View File

@ -1664,6 +1664,7 @@ int fuse_file_write_iter_backing(struct fuse_bpf_args *fa,
void *fuse_file_write_iter_finalize(struct fuse_bpf_args *fa,
struct kiocb *iocb, struct iov_iter *from);
int fuse_file_flock_backing(struct file *file, int cmd, struct file_lock *fl);
ssize_t fuse_backing_mmap(struct file *file, struct vm_area_struct *vma);
int fuse_file_fallocate_initialize(struct fuse_bpf_args *fa,

View File

@ -12,6 +12,7 @@
#include <string.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/inotify.h>
#include <sys/mman.h>
#include <sys/mount.h>
@ -1336,6 +1337,50 @@ static int mmap_test(const char *mount_dir)
return result;
}
static int flock_test(const char *mount_dir)
{
const char *file = "file";
int result = TEST_FAILURE;
int src_fd = -1;
int fuse_dev = -1;
int fd = -1, fd2 = -1;
int backing_fd = -1;
char *addr = NULL;
TEST(src_fd = open(ft_src, O_DIRECTORY | O_RDONLY | O_CLOEXEC),
src_fd != -1);
TESTEQUAL(mount_fuse(mount_dir, -1, src_fd, &fuse_dev), 0);
TEST(fd = s_open(s_path(s(mount_dir), s(file)),
O_CREAT | O_RDWR | O_CLOEXEC, 0777),
fd != -1);
TEST(fd2 = s_open(s_path(s(mount_dir), s(file)),
O_RDWR | O_CLOEXEC, 0777),
fd2 != -1);
TESTSYSCALL(flock(fd, LOCK_EX | LOCK_NB));
TESTCONDERR((flock(fd2, LOCK_EX | LOCK_NB)) == -1);
TESTCOND(errno == EAGAIN);
TESTSYSCALL(flock(fd, LOCK_UN));
TESTSYSCALL(flock(fd2, LOCK_EX | LOCK_NB));
TEST(backing_fd = s_open(s_path(s(ft_src), s(file)),
O_RDONLY | O_CLOEXEC),
backing_fd != -1);
TESTCONDERR((flock(backing_fd, LOCK_EX | LOCK_NB)) == -1);
TESTCOND(errno == EAGAIN);
close(fd2);
fd2 = 0;
TESTSYSCALL(flock(backing_fd, LOCK_EX | LOCK_NB));
result = TEST_SUCCESS;
out:
close(fd);
close(fd2);
close(backing_fd);
umount(mount_dir);
close(fuse_dev);
close(src_fd);
return result;
}
static int readdir_perms_test(const char *mount_dir)
{
int result = TEST_FAILURE;
@ -2091,6 +2136,7 @@ int main(int argc, char *argv[])
MAKE_TEST(bpf_test_no_readdirplus_without_nodeid),
MAKE_TEST(bpf_test_revalidate_handle_backing_fd),
MAKE_TEST(bpf_test_lookup_postfilter),
MAKE_TEST(flock_test),
};
#undef MAKE_TEST