From 595da2719e1511c76c40418c07d8d720005af598 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Thu, 16 Dec 2021 18:16:18 +0000 Subject: [PATCH] UPSTREAM: ANDROID: fuse-bpf: Partial fix for mmap'd files This will simply pass all mapping operations to the backing file if it exists. This is sufficient for our needs in Android13, but must be extended in the future. Signed-off-by: Paul Lawrence Bug: 202785178 Test: fuse_test passes Change-Id: I3c51ef62415633ff0db039f25bfed1adf14e1e80 --- fs/fuse/backing.c | 38 ++++++++++++++++++++++++++++++++++++++ fs/fuse/file.c | 6 ++++++ fs/fuse/fuse_i.h | 2 ++ 3 files changed, 46 insertions(+) diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c index f30fe8ef5c05..bc7258d78878 100644 --- a/fs/fuse/backing.c +++ b/fs/fuse/backing.c @@ -750,6 +750,44 @@ void *fuse_file_write_iter_finalize(struct fuse_args *fa, return ERR_PTR(fwo->size); } +ssize_t fuse_backing_mmap(struct file *file, struct vm_area_struct *vma) +{ + int ret; + struct fuse_file *ff = file->private_data; + struct inode *fuse_inode = file_inode(file); + struct file *backing_file = ff->backing_file; + struct inode *backing_inode = file_inode(backing_file); + + if (!backing_file->f_op->mmap) + return -ENODEV; + + if (WARN_ON(file != vma->vm_file)) + return -EIO; + + vma->vm_file = get_file(backing_file); + + ret = call_mmap(vma->vm_file, vma); + + if (ret) + fput(backing_file); + else + fput(file); + + if (file->f_flags & O_NOATIME) + return ret; + + if ((!timespec64_equal(&fuse_inode->i_mtime, + &backing_inode->i_mtime) || + !timespec64_equal(&fuse_inode->i_ctime, + &backing_inode->i_ctime))) { + fuse_inode->i_mtime = backing_inode->i_mtime; + fuse_inode->i_ctime = backing_inode->i_ctime; + } + touch_atime(&file->f_path); + + return ret; +} + int fuse_file_fallocate_initialize(struct fuse_args *fa, struct fuse_fallocate_in *ffi, struct file *file, int mode, loff_t offset, loff_t length) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index b5ff5d34ac65..c3346b090954 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -2525,6 +2525,12 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) if (FUSE_IS_DAX(file_inode(file))) return fuse_dax_mmap(file, vma); +#ifdef CONFIG_FUSE_BPF + /* TODO - this is simply passthrough, not a proper BPF filter */ + if (ff->backing_file) + return fuse_backing_mmap(file, vma); +#endif + if (ff->passthrough.filp) return fuse_passthrough_mmap(file, vma); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index eb8e6c78c128..7adb8f4a6224 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1495,6 +1495,8 @@ int fuse_file_write_iter_backing(struct fuse_args *fa, void *fuse_file_write_iter_finalize(struct fuse_args *fa, struct kiocb *iocb, struct iov_iter *from); +ssize_t fuse_backing_mmap(struct file *file, struct vm_area_struct *vma); + int fuse_file_fallocate_initialize(struct fuse_args *fa, struct fuse_fallocate_in *ffi, struct file *file, int mode, loff_t offset, loff_t length);