@@ -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)
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@gmail.com> --- fs/fuse/passthrough.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)