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 56ef73dd58e3b6..33a375a21b2da1 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1936,6 +1936,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 84f68dc37db64f..19d51a44793e0c 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); @@ -328,8 +329,12 @@ u32 fuse_get_cache_mask(struct inode *inode) { struct fuse_conn *fc = get_fuse_conn(inode); - if (S_ISREG(inode->i_mode) && - (fuse_has_iomap_fileio(inode) || fc->writeback_cache)) + if (!S_ISREG(inode->i_mode)) + return 0; + + if (fuse_has_iomap_fileio(inode)) + return STATX_MTIME | STATX_CTIME | STATX_ATIME | STATX_SIZE; + if (fc->writeback_cache) return STATX_MTIME | STATX_CTIME | STATX_SIZE; return 0; @@ -448,6 +453,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.