From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Alessio Balsini Date: Thu, 27 Jan 2022 14:44:24 +0000 Subject: ANDROID: fs/fuse: Use extended init flags for FUSE_PASSTHROUGH Starting with FUSE 7.36, all the fields for the 32-bit FUSE init flags have been allocated, so commit 53db28933e952 ("fuse: extend init flags") introduces the new 32-bit flags2 field in fuse_init_in and fuse_init_out. That change also adds the FUSE_INIT_RESERVED flag that doesn't have any specific purpose yet, is just reserved and should not be used, and (un)fortunately collides with FUSE_PASSTHROUGH. This change fixes the conflict by simply setting the FUSE_PASSTHROUGH value to the next, latest unused fuse2 bit. Although this is not the best design choice, userspace will know what FUSE_PASSTHROUGH bit to choose based on the FUSE major and minor version for FUSE version: - < 7.36: FUSE_PASSTHROUGH is the 31st bit of flags; - otherwise: FUSE_PASSTHROUGH is the 31st bit of flags2. Test: launch_cvd (both android-mainline and android13-5.10) \ `logcat FuseDaemon:V \*:S` shows no FUSE passthrough errors Bug: 215310351 Signed-off-by: Alessio Balsini Change-Id: I85d7582008b8c093b3172b3f41c6cdf09863dd45 Signed-off-by: Lee Jones --- fs/fuse/inode.c | 2 ++ fs/fuse/passthrough.c | 32 ++++++++++++++++++++++++++++++++ include/uapi/linux/fuse.h | 12 ++++++++++++ 3 files changed, 46 insertions(+) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -1295,6 +1295,8 @@ void fuse_send_init(struct fuse_mount *fm) if (fm->fc->auto_submounts) flags |= FUSE_SUBMOUNTS; + flags |= FUSE_PASSTHROUGH; + ia->in.flags = flags; ia->in.flags2 = flags >> 32; diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -15,11 +15,43 @@ struct fuse_aio_req { struct kiocb *iocb_fuse; }; +static void fuse_file_accessed(struct file *dst_file, struct file *src_file) +{ + struct inode *dst_inode; + struct inode *src_inode; + struct timespec64 dst_ctime_ts; + struct timespec64 src_ctime_ts; + struct timespec64 dst_mtime_ts; + struct timespec64 src_mtime_ts; + + if (dst_file->f_flags & O_NOATIME) + return; + + dst_inode = file_inode(dst_file); + src_inode = file_inode(src_file); + dst_ctime_ts = inode_get_ctime(dst_inode); + src_ctime_ts = inode_get_ctime(src_inode); + dst_mtime_ts = inode_get_mtime(dst_inode); + src_mtime_ts = inode_get_mtime(src_inode); + + + if ((!timespec64_equal(&dst_mtime_ts, &src_mtime_ts) || + !timespec64_equal(&dst_ctime_ts, &src_ctime_ts))) { + inode_set_mtime_to_ts(dst_inode, inode_get_mtime(src_inode)); + inode_set_ctime_to_ts(dst_inode, inode_get_ctime(src_inode)); + } + + touch_atime(&dst_file->f_path); +} + static void fuse_copyattr(struct file *dst_file, struct file *src_file) { struct inode *dst = file_inode(dst_file); struct inode *src = file_inode(src_file); + inode_set_atime_to_ts(dst, inode_get_atime(src)); + inode_set_mtime_to_ts(dst, inode_get_mtime(src)); + inode_set_ctime_to_ts(dst, inode_get_ctime(src)); i_size_write(dst, i_size_read(src)); } diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -451,6 +451,18 @@ struct fuse_file_lock { #define FUSE_HAS_EXPIRE_ONLY (1ULL << 35) #define FUSE_DIRECT_IO_RELAX (1ULL << 36) +/* + * For FUSE < 7.36 FUSE_PASSTHROUGH has value (1 << 31). + * This condition check is not really required, but would prevent having a + * broken commit in the tree. + */ +#if FUSE_KERNEL_VERSION > 7 || \ + (FUSE_KERNEL_VERSION == 7 && FUSE_KERNEL_MINOR_VERSION >= 36) +#define FUSE_PASSTHROUGH (1ULL << 63) +#else +#define FUSE_PASSTHROUGH (1 << 31) +#endif + /** * CUSE INIT request/reply flags *