Similar to invalidate atime in fuse_readpages_end(). To minimize requests to server, invalidate atime only if the backing inode atime has changed during the operation. Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> --- fs/fuse/passthrough.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/fs/fuse/passthrough.c b/fs/fuse/passthrough.c index 8352d6b91e0e..2b745b6b2364 100644 --- a/fs/fuse/passthrough.c +++ b/fs/fuse/passthrough.c @@ -12,6 +12,7 @@ struct fuse_aio_req { struct kiocb iocb; struct kiocb *iocb_fuse; + struct timespec64 pre_atime; }; static void fuse_file_start_write(struct file *fuse_file, @@ -40,6 +41,21 @@ static void fuse_file_end_write(struct file *fuse_file, clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); } +static void fuse_file_start_read(struct file *backing_file, + struct timespec64 *pre_atime) +{ + *pre_atime = file_inode(backing_file)->i_atime; +} + +static void fuse_file_end_read(struct file *fuse_file, + struct file *backing_file, + struct timespec64 *pre_atime) +{ + /* Mimic atime update policy of passthrough inode, not the value */ + if (!timespec64_equal(&file_inode(backing_file)->i_atime, pre_atime)) + fuse_invalidate_atime(file_inode(fuse_file)); +} + static void fuse_aio_cleanup_handler(struct fuse_aio_req *aio_req, long res) { struct kiocb *iocb = &aio_req->iocb; @@ -50,6 +66,8 @@ static void fuse_aio_cleanup_handler(struct fuse_aio_req *aio_req, long res) if (iocb->ki_flags & IOCB_WRITE) { __sb_writers_acquired(file_inode(filp)->i_sb, SB_FREEZE_WRITE); fuse_file_end_write(fuse_filp, filp, iocb->ki_pos, res); + } else { + fuse_file_end_read(fuse_filp, filp, &aio_req->pre_atime); } iocb_fuse->ki_pos = iocb->ki_pos; @@ -81,9 +99,13 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, old_cred = override_creds(ff->passthrough->cred); if (is_sync_kiocb(iocb_fuse)) { + struct timespec64 pre_atime; + rwf = iocb_to_rw_flags(iocb_fuse->ki_flags, FUSE_IOCB_MASK); + fuse_file_start_read(passthrough_filp, &pre_atime); ret = vfs_iter_read(passthrough_filp, iter, &iocb_fuse->ki_pos, rwf); + fuse_file_end_read(fuse_filp, passthrough_filp, &pre_atime); } else { struct fuse_aio_req *aio_req; @@ -94,6 +116,7 @@ ssize_t fuse_passthrough_read_iter(struct kiocb *iocb_fuse, } aio_req->iocb_fuse = iocb_fuse; + fuse_file_start_read(passthrough_filp, &aio_req->pre_atime); kiocb_clone(&aio_req->iocb, iocb_fuse, passthrough_filp); aio_req->iocb.ki_complete = fuse_aio_rw_complete; ret = call_read_iter(passthrough_filp, &aio_req->iocb, iter); @@ -166,6 +189,7 @@ ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma) const struct cred *old_cred; struct fuse_file *ff = file->private_data; struct file *passthrough_filp = ff->passthrough->filp; + struct timespec64 pre_atime; if (!passthrough_filp->f_op->mmap) return -ENODEV; @@ -176,7 +200,9 @@ ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma) vma->vm_file = get_file(passthrough_filp); old_cred = override_creds(ff->passthrough->cred); + fuse_file_start_read(passthrough_filp, &pre_atime); ret = call_mmap(vma->vm_file, vma); + fuse_file_end_read(file, passthrough_filp, &pre_atime); revert_creds(old_cred); if (ret) -- 2.34.1