diff mbox series

[v8,2/5] fs: optimize away some fine-grained timestamp updates

Message ID 20230922-ctime-v8-2-45f0c236ede1@kernel.org (mailing list archive)
State New, archived
Headers show
Series fs: multigrain timestamps for XFS's change_cookie | expand

Commit Message

Jeffrey Layton Sept. 22, 2023, 5:14 p.m. UTC
When updating the ctime and the QUERIED bit is set, we can still use the
coarse-grained clock if the next coarse time tick has already happened.
Only use the fine grained clock if the coarse grained one is equal to or
earlier than the old ctime.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
 fs/inode.c | 33 +++++++++++++++++++++++----------
 1 file changed, 23 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/fs/inode.c b/fs/inode.c
index f3d68e4b8df7..293f9ba623d1 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2587,26 +2587,35 @@  EXPORT_SYMBOL(current_time);
  */
 struct timespec64 inode_set_ctime_current(struct inode *inode)
 {
-	struct timespec64 now;
+	struct timespec64 now = current_time(inode);
 	struct timespec64 ctime;
+	bool queried;
+	int tscomp;
 
+	/* Just copy it into place if it's not multigrain */
+	if (!is_mgtime(inode)) {
+		inode_set_ctime_to_ts(inode, now);
+		return now;
+	}
+
+	ctime.tv_sec = inode->__i_ctime.tv_sec;
 	ctime.tv_nsec = READ_ONCE(inode->__i_ctime.tv_nsec);
-	if (!(ctime.tv_nsec & I_CTIME_QUERIED)) {
-		now = current_time(inode);
+	queried = ctime.tv_nsec & I_CTIME_QUERIED;
+	ctime.tv_nsec &= ~I_CTIME_QUERIED;
 
-		/* Just copy it into place if it's not multigrain */
-		if (!is_mgtime(inode)) {
-			inode_set_ctime_to_ts(inode, now);
-			return now;
-		}
+	tscomp = timespec64_compare(&ctime, &now);
 
+	/*
+	 * We can use a coarse-grained timestamp if no one has queried for it,
+	 * or coarse time is already later than the existing ctime.
+	 */
+	if (!queried || tscomp < 0) {
 		/*
 		 * If we've recently updated with a fine-grained timestamp,
 		 * then the coarse-grained one may still be earlier than the
 		 * existing ctime. Just keep the existing value if so.
 		 */
-		ctime.tv_sec = inode->__i_ctime.tv_sec;
-		if (timespec64_compare(&ctime, &now) > 0) {
+		if (tscomp > 0) {
 			struct timespec64	limit = now;
 
 			/*
@@ -2620,6 +2629,10 @@  struct timespec64 inode_set_ctime_current(struct inode *inode)
 				return ctime;
 		}
 
+		/* Put back the queried bit if we stripped it before */
+		if (queried)
+			ctime.tv_nsec |= I_CTIME_QUERIED;
+
 		/*
 		 * Ctime updates are usually protected by the inode_lock, but
 		 * we can still race with someone setting the QUERIED flag.