[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <175279461828.716436.6399243218938406982.stgit@frogsfrogsfrogs>
Date: Thu, 17 Jul 2025 16:46:57 -0700
From: "Darrick J. Wong" <djwong@...nel.org>
To: tytso@....edu
Cc: joannelkoong@...il.com, miklos@...redi.hu, John@...ves.net,
linux-fsdevel@...r.kernel.org, bernd@...ernd.com, linux-ext4@...r.kernel.org,
neal@...pa.dev
Subject: [PATCH 06/10] fuse2fs: use coarse timestamps for iomap mode
From: Darrick J. Wong <djwong@...nel.org>
In iomap mode, the kernel is responsible for maintaining timestamps
because file writes don't upcall to fuse2fs. The kernel's predicate for
deciding if [cm]time should be updated bases its decisions off [cm]time
being an exact match for the coarse clock (instead of checking that
[cm]time < coarse_clock) which means that fuse2fs setting a fine-grained
timestamp that is slightly ahead of the coarse clock can result in
timestamps appearing to go backwards. generic/423 doesn't like seeing
btime > ctime from statx, so we'll use the coarse clock in iomap mode.
Signed-off-by: "Darrick J. Wong" <djwong@...nel.org>
---
misc/fuse2fs.c | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index ddc647f32c5df6..54f501b36d808b 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -575,8 +575,24 @@ static inline void fuse2fs_dump_extents(struct fuse2fs *ff, ext2_ino_t ino,
ext2fs_extent_free(extents);
}
-static void get_now(struct timespec *now)
+static void fuse2fs_get_now(struct fuse2fs *ff, struct timespec *now)
{
+#ifdef CLOCK_REALTIME_COARSE
+ /*
+ * In iomap mode, the kernel is responsible for maintaining timestamps
+ * because file writes don't upcall to fuse2fs. The kernel's predicate
+ * for deciding if [cm]time should be updated bases its decisions off
+ * [cm]time being an exact match for the coarse clock (instead of
+ * checking that [cm]time < coarse_clock) which means that fuse2fs
+ * setting a fine-grained timestamp that is slightly ahead of the
+ * coarse clock can result in timestamps appearing to go backwards.
+ * generic/423 doesn't like seeing btime > ctime from statx, so we'll
+ * use the coarse clock in iomap mode.
+ */
+ if (fuse2fs_iomap_does_fileio(ff) &&
+ !clock_gettime(CLOCK_REALTIME_COARSE, now))
+ return;
+#endif
#ifdef CLOCK_REALTIME
if (!clock_gettime(CLOCK_REALTIME, now))
return;
@@ -604,7 +620,7 @@ static void fuse2fs_init_timestamps(struct fuse2fs *ff, ext2_ino_t ino,
{
struct timespec now;
- get_now(&now);
+ fuse2fs_get_now(ff, &now);
EXT4_INODE_SET_XTIME(i_atime, &now, inode);
EXT4_INODE_SET_XTIME(i_ctime, &now, inode);
EXT4_INODE_SET_XTIME(i_mtime, &now, inode);
@@ -623,7 +639,7 @@ static int fuse2fs_update_ctime(struct fuse2fs *ff, ext2_ino_t ino,
struct timespec now;
struct ext2_inode_large inode;
- get_now(&now);
+ fuse2fs_get_now(ff, &now);
/* If user already has a inode buffer, just update that */
if (pinode) {
@@ -669,7 +685,7 @@ static int fuse2fs_update_atime(struct fuse2fs *ff, ext2_ino_t ino)
pinode = &inode;
EXT4_INODE_GET_XTIME(i_atime, &atime, pinode);
EXT4_INODE_GET_XTIME(i_mtime, &mtime, pinode);
- get_now(&now);
+ fuse2fs_get_now(ff, &now);
datime = atime.tv_sec + ((double)atime.tv_nsec / NSEC_PER_SEC);
dmtime = mtime.tv_sec + ((double)mtime.tv_nsec / NSEC_PER_SEC);
@@ -704,7 +720,7 @@ static int fuse2fs_update_mtime(struct fuse2fs *ff, ext2_ino_t ino,
struct timespec now;
if (pinode) {
- get_now(&now);
+ fuse2fs_get_now(ff, &now);
EXT4_INODE_SET_XTIME(i_mtime, &now, pinode);
EXT4_INODE_SET_XTIME(i_ctime, &now, pinode);
increment_version(pinode);
@@ -719,7 +735,7 @@ static int fuse2fs_update_mtime(struct fuse2fs *ff, ext2_ino_t ino,
if (err)
return translate_error(fs, ino, err);
- get_now(&now);
+ fuse2fs_get_now(ff, &now);
EXT4_INODE_SET_XTIME(i_mtime, &now, &inode);
EXT4_INODE_SET_XTIME(i_ctime, &now, &inode);
increment_version(&inode);
@@ -4380,9 +4396,9 @@ static int op_utimens(const char *path, const struct timespec ctv[2]
tv[1] = ctv[1];
#ifdef UTIME_NOW
if (tv[0].tv_nsec == UTIME_NOW)
- get_now(tv);
+ fuse2fs_get_now(ff, tv);
if (tv[1].tv_nsec == UTIME_NOW)
- get_now(tv + 1);
+ fuse2fs_get_now(ff, tv + 1);
#endif /* UTIME_NOW */
#ifdef UTIME_OMIT
if (tv[0].tv_nsec != UTIME_OMIT)
@@ -6917,7 +6933,7 @@ static int __translate_error(ext2_filsys fs, ext2_ino_t ino, errcode_t err,
error_message(err), func, line);
/* Make a note in the error log */
- get_now(&now);
+ fuse2fs_get_now(ff, &now);
ext2fs_set_tstamp(fs->super, s_last_error_time, now.tv_sec);
fs->super->s_last_error_ino = ino;
fs->super->s_last_error_line = line;
Powered by blists - more mailing lists