This adds a backing implementation for mapping, but is not currently hooked into the infrastructure that will call the bpf programs. Signed-off-by: Daniel Rosenberg <drosen@xxxxxxxxxx> Signed-off-by: Paul Lawrence <paullawrence@xxxxxxxxxx> --- fs/fuse/backing.c | 41 +++++++++++++++++++++++++++++++++++++++++ fs/fuse/file.c | 6 ++++++ fs/fuse/fuse_i.h | 4 +++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/fs/fuse/backing.c b/fs/fuse/backing.c index a94d99ff9862..331b3f23ef78 100644 --- a/fs/fuse/backing.c +++ b/fs/fuse/backing.c @@ -210,6 +210,47 @@ static void fuse_stat_to_attr(struct fuse_conn *fc, struct inode *inode, attr->blksize = 1 << blkbits; } +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); + struct timespec64 mtime, bmtime, ctime, bctime; + + 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; + + mtime = inode_get_mtime(fuse_inode); + bmtime = inode_get_mtime(backing_inode); + ctime = inode_get_ctime(fuse_inode); + bctime = inode_get_ctime(backing_inode); + if ((!timespec64_equal(&mtime, &bmtime) || + !timespec64_equal(&ctime, &bctime))) { + inode_set_mtime_to_ts(fuse_inode, bmtime); + inode_set_ctime_to_ts(fuse_inode, bctime); + } + touch_atime(&file->f_path); + + return ret; +} + /******************************************************************************* * Directory operations after here * ******************************************************************************/ diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 41a2e88e8646..b15a0c30fec8 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -2486,6 +2486,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->open_flags & FOPEN_DIRECT_IO) { /* Can't provide the coherency needed for MAP_SHARED * if FUSE_DIRECT_IO_ALLOW_MMAP isn't set. diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 08ee98b7bb95..5f76ba3c1e4b 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1455,7 +1455,9 @@ static inline int fuse_bpf_access(int *out, struct inode *inode, int mask) #endif // CONFIG_FUSE_BPF -int fuse_handle_backing(struct fuse_bpf_entry *feb, struct path *backing_path); +ssize_t fuse_backing_mmap(struct file *file, struct vm_area_struct *vma); + +int fuse_handle_backing(struct fuse_bpf_entry *fbe, struct path *backing_path); int fuse_revalidate_backing(struct dentry *entry, unsigned int flags); -- 2.44.0.478.gd926399ef9-goog