[PATCH v3 6/8] fs: check a fine-grained time before clamping a delegated ctime

From: Jeff Layton

Date: Mon Nov 09 2026 - 15:44:41 EST


inode_set_ctime_deleg() clamps an update later than the coarse time
(or mg floor) to that time. An NFS client holding a timestamp delegation
stamps at least 1ns after the fine-grained ctime the server last
reported. If the delegation comes back within the same coarse tick,
that stamp looks like it's in the future: ctime is clamped back, and
the ctime the client reported while holding the delegation changes
after DELEGRETURN.

When the update is past the coarse time, take a fine-grained time with
ktime_get_real_ts64_mg() and clamp only if the update is past that too.
That also raises the floor to at least the update, so later coarse
stamps can't land before it. This works for non-multigrain filesystems
too: their stamps also read the floor.

Fixes: 7f2c86cba3c5 ("fs: handle delegated timestamps in setattr_copy_mgtime")
Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx>
---
fs/inode.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/fs/inode.c b/fs/inode.c
index f63535ee3629..dc744fa39b75 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2991,9 +2991,19 @@ struct timespec64 inode_set_ctime_deleg(struct inode *inode, struct timespec64 u

ktime_get_coarse_real_ts64_mg(&now);

- /* Clamp the update to "now" if it's in the future */
- if (timespec64_compare(&update, &now) > 0)
- update = now;
+ /*
+ * Clamp the update to "now" if it's in the future. The coarse time
+ * can trail an update just past a fine-grained ctime handed out in
+ * the current tick, so check a fine-grained time before clamping.
+ * That also raises the floor past the update, so later coarse
+ * stamps can't land before it.
+ */
+ if (timespec64_compare(&update, &now) > 0) {
+ ktime_get_real_ts64_mg(&now);
+ mgtime_counter_inc(mg_fine_stamps);
+ if (timespec64_compare(&update, &now) > 0)
+ update = now;
+ }

update = timestamp_truncate(update, inode);


--
2.56.0