diff mbox series

[v13,09/10] fuse: invalidate atime after passthrough read/mmap

Message ID 20230519125705.598234-10-amir73il@gmail.com (mailing list archive)
State New, archived
Headers show
Series fuse: Add support for passthrough read/write | expand

Commit Message

Amir Goldstein May 19, 2023, 12:57 p.m. UTC
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(+)
diff mbox series

Patch

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)