From: Darrick J. Wong <djwong@xxxxxxxxxx> When we're running in iomap mode, allow the kernel to cache the access timestamp to further reduce the number of roundtrips to the fuse server. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> --- fs/fuse/dir.c | 5 +++++ fs/fuse/inode.c | 19 ++++++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index d2f9bcccd776f0..a3ea50b99054ff 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -2030,6 +2030,11 @@ int fuse_flush_times(struct inode *inode, struct fuse_file *ff) inarg.ctime = inode_get_ctime_sec(inode); inarg.ctimensec = inode_get_ctime_nsec(inode); } + if (fuse_has_iomap(inode)) { + inarg.valid |= FATTR_ATIME; + inarg.atime = inode_get_atime_sec(inode); + inarg.atimensec = inode_get_atime_nsec(inode); + } if (ff) { inarg.valid |= FATTR_FH; inarg.fh = ff->fh; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index b1793df3cbbd1a..91143845c615c4 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -264,7 +264,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, attr->mtimensec = min_t(u32, attr->mtimensec, NSEC_PER_SEC - 1); attr->ctimensec = min_t(u32, attr->ctimensec, NSEC_PER_SEC - 1); - inode_set_atime(inode, attr->atime, attr->atimensec); + if (!(cache_mask & STATX_ATIME)) + inode_set_atime(inode, attr->atime, attr->atimensec); /* mtime from server may be stale due to local buffered write */ if (!(cache_mask & STATX_MTIME)) { inode_set_mtime(inode, attr->mtime, attr->mtimensec); @@ -331,8 +332,12 @@ u32 fuse_get_cache_mask(struct inode *inode) { struct fuse_conn *fc = get_fuse_conn(inode); - if (S_ISREG(inode->i_mode) && - (fuse_inode_has_iomap(inode) || fc->writeback_cache)) + if (!S_ISREG(inode->i_mode)) + return 0; + + if (fuse_inode_has_iomap(inode)) + return STATX_MTIME | STATX_CTIME | STATX_ATIME | STATX_SIZE; + if (fc->writeback_cache) return STATX_MTIME | STATX_CTIME | STATX_SIZE; return 0; @@ -451,6 +456,14 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr, new_decode_dev(attr->rdev)); } else BUG(); + + /* + * iomap caches atime too, so we must load it from the fuse server + * at instantiation time. + */ + if (fuse_has_iomap(inode)) + inode_set_atime(inode, attr->atime, attr->atimensec); + /* * Ensure that we don't cache acls for daemons without FUSE_POSIX_ACL * so they see the exact same behavior as before.