linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Miklos Szeredi <mszeredi@redhat.com>
To: linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH 7/9] fuse: use mtime for readdir cache verification
Date: Fri, 28 Sep 2018 17:42:32 +0200	[thread overview]
Message-ID: <20180928154234.19270-8-mszeredi@redhat.com> (raw)
In-Reply-To: <20180928154234.19270-1-mszeredi@redhat.com>

Store the modification time of the directory in the cache, obtained before
starting to fill the cache.

When reading the cache, verify that the directory hasn't changed, by
checking if current modification time is the same as the one stored in the
cache.

This only needs to be done when the current file position is at the
beginning of the directory, as mandated by POSIX.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
 fs/fuse/fuse_i.h  |  3 +++
 fs/fuse/readdir.c | 38 ++++++++++++++++++++++++++++++++++----
 2 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index ef018ea5bcd9..e498f9edf01f 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -117,6 +117,9 @@ struct fuse_inode {
 		/** version of the cache */
 		u64 version;
 
+		/** modification time of directory when cache was started */
+		struct timespec64 mtime;
+
 		/** protects above fields */
 		spinlock_t lock;
 	} rdc;
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
index edb445c4cfbd..f96525cef518 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -397,8 +397,10 @@ static enum fuse_parse_result fuse_parse_cache(struct fuse_file *ff,
 	return res;
 }
 
-static void fuse_rdc_reset(struct fuse_inode *fi)
+static void fuse_rdc_reset(struct inode *inode)
 {
+	struct fuse_inode *fi = get_fuse_inode(inode);
+
 	fi->rdc.cached = false;
 	fi->rdc.version++;
 	fi->rdc.size = 0;
@@ -411,6 +413,7 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
 {
 	struct fuse_file *ff = file->private_data;
 	struct inode *inode = file_inode(file);
+	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_inode *fi = get_fuse_inode(inode);
 	enum fuse_parse_result res;
 	pgoff_t index;
@@ -424,12 +427,40 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
 		ff->readdir.cache_off = 0;
 	}
 
+	/*
+	 * We're just about to start reading into the cache or reading the
+	 * cache; both cases require an up-to-date mtime value.
+	 */
+	if (!ctx->pos && fc->auto_inval_data) {
+		int err = fuse_update_attributes(inode, file);
+
+		if (err)
+			return err;
+	}
+
 retry:
 	spin_lock(&fi->rdc.lock);
+retry_locked:
 	if (!fi->rdc.cached) {
+		/* Starting cache? Set cache mtime. */
+		if (!ctx->pos && !fi->rdc.size) {
+			fi->rdc.mtime = inode->i_mtime;
+		}
 		spin_unlock(&fi->rdc.lock);
 		return UNCACHED;
 	}
+	/*
+	 * When at the beginning of the directory (i.e. just after opendir(3) or
+	 * rewinddir(3)), then need to check whether directory contents have
+	 * changed, and reset the cache if so.
+	 */
+	if (!ctx->pos) {
+		if (!timespec64_equal(&fi->rdc.mtime, &inode->i_mtime)) {
+			fuse_rdc_reset(inode);
+			goto retry_locked;
+		}
+	}
+
 	/*
 	 * If cache version changed since the last getdents() call, then reset
 	 * the cache stream.
@@ -467,9 +498,8 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
 		 * Uh-oh: page gone missing, cache is useless
 		 */
 		if (fi->rdc.version == ff->readdir.version)
-			fuse_rdc_reset(fi);
-		spin_unlock(&fi->rdc.lock);
-		return UNCACHED;
+			fuse_rdc_reset(inode);
+		goto retry_locked;
 	}
 
 	/* Make sure it's still the same version after getting the page. */
-- 
2.14.3

  parent reply	other threads:[~2018-09-28 22:07 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-28 15:42 [PATCH 0/9] fuse: readdir caching Miklos Szeredi
2018-09-28 15:42 ` [PATCH 1/9] fuse: split out readdir.c Miklos Szeredi
2018-09-28 15:42 ` [PATCH 2/9] fuse: add FOPEN_CACHE_DIR Miklos Szeredi
2018-09-28 15:42 ` [PATCH 3/9] fuse: extract fuse_emit() helper Miklos Szeredi
2018-09-28 15:42 ` [PATCH 4/9] fuse: allow caching readdir Miklos Szeredi
2018-09-28 16:42   ` Matthew Wilcox
2018-09-28 15:42 ` [PATCH 5/9] fuse: allow using readdir cache Miklos Szeredi
2018-09-28 15:42 ` [PATCH 6/9] fuse: add readdir cache version Miklos Szeredi
2018-09-28 15:42 ` Miklos Szeredi [this message]
2018-09-28 15:42 ` [PATCH 8/9] fuse: use iversion for readdir cache verification Miklos Szeredi
2018-09-28 15:42 ` [PATCH 9/9] fuse: reduce size of struct fuse_inode Miklos Szeredi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180928154234.19270-8-mszeredi@redhat.com \
    --to=mszeredi@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).