public inbox for io-uring@vger.kernel.org
 help / color / mirror / Atom feed
* re-enable IOCB_NOWAIT writes to files v4
@ 2025-12-23  0:37 Christoph Hellwig
  2025-12-23  0:37 ` [PATCH 01/11] fs: remove inode_update_time Christoph Hellwig
                   ` (12 more replies)
  0 siblings, 13 replies; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

Hi all,

commit 66fa3cedf16a ("fs: Add async write file modification handling.")
effectively disabled IOCB_NOWAIT writes as timestamp updates currently
always require blocking, and the modern timestamp resolution means we
always update timestamps.  This leads to a lot of context switches from
applications using io_uring to submit file writes, making it often worse
than using the legacy aio code that is not using IOCB_NOWAIT.

This series allows non-blocking updates for lazytime if the file system
supports it, and adds that support for XFS.

Changes since v3:
 - fix was_dirty_time handling in __mark_inode_dirty for the racy flag
   update case
 - refactor inode_update_timestamps to make the lazytime vs blocking
   logical more clear
 - allow non-blocking timestamp updates for fat

Changes since v2:
 - drop patches merged upstream
 - adjust for the inode state accesors
 - keep a check in __writeback_single_inode instead of exercising
   potentially undefined behavior
 - more spelling fixes

Changes since v1:
 - more regular numbering of the S_* flags
 - fix XFS to actually not block
 - don't ignore the generic_update_time return value in
   file_update_time_flags
 - fix the sync_lazytime return value
 - fix an out of data comment in btrfs
 - fix a race that would update i_version before returning -EAGAIN in XFS

Diffstat:
 Documentation/filesystems/locking.rst |    2 
 Documentation/filesystems/vfs.rst     |    6 +
 fs/btrfs/inode.c                      |    8 +-
 fs/fs-writeback.c                     |   33 +++++++---
 fs/gfs2/inode.c                       |    6 +
 fs/inode.c                            |  111 +++++++++++++++++++++-------------
 fs/internal.h                         |    3 
 fs/nfs/inode.c                        |    4 -
 fs/orangefs/inode.c                   |    5 +
 fs/overlayfs/inode.c                  |    2 
 fs/sync.c                             |    4 -
 fs/ubifs/file.c                       |   13 ++-
 fs/xfs/xfs_iops.c                     |   34 +++++++++-
 fs/xfs/xfs_super.c                    |   29 --------
 include/linux/fs.h                    |   27 ++++++--
 include/trace/events/writeback.h      |    6 -
 16 files changed, 182 insertions(+), 111 deletions(-)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 01/11] fs: remove inode_update_time
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  0:37 ` [PATCH 02/11] fs: allow error returns from generic_update_time Christoph Hellwig
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs,
	Chaitanya Kulkarni

The only external user is gone now, open code it in the two VFS
callers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
---
 fs/inode.c         | 23 ++++++++---------------
 include/linux/fs.h |  1 -
 2 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/fs/inode.c b/fs/inode.c
index 521383223d8a..07effa0cb999 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2157,19 +2157,6 @@ int generic_update_time(struct inode *inode, int flags)
 }
 EXPORT_SYMBOL(generic_update_time);
 
-/*
- * This does the actual work of updating an inodes time or version.  Must have
- * had called mnt_want_write() before calling this.
- */
-int inode_update_time(struct inode *inode, int flags)
-{
-	if (inode->i_op->update_time)
-		return inode->i_op->update_time(inode, flags);
-	generic_update_time(inode, flags);
-	return 0;
-}
-EXPORT_SYMBOL(inode_update_time);
-
 /**
  *	atime_needs_update	-	update the access time
  *	@path: the &struct path to update
@@ -2237,7 +2224,10 @@ void touch_atime(const struct path *path)
 	 * We may also fail on filesystems that have the ability to make parts
 	 * of the fs read only, e.g. subvolumes in Btrfs.
 	 */
-	inode_update_time(inode, S_ATIME);
+	if (inode->i_op->update_time)
+		inode->i_op->update_time(inode, S_ATIME);
+	else
+		generic_update_time(inode, S_ATIME);
 	mnt_put_write_access(mnt);
 skip_update:
 	sb_end_write(inode->i_sb);
@@ -2392,7 +2382,10 @@ static int file_update_time_flags(struct file *file, unsigned int flags)
 
 	if (mnt_get_write_access_file(file))
 		return 0;
-	ret = inode_update_time(inode, sync_mode);
+	if (inode->i_op->update_time)
+		ret = inode->i_op->update_time(inode, sync_mode);
+	else
+		ret = generic_update_time(inode, sync_mode);
 	mnt_put_write_access_file(file);
 	return ret;
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f5c9cf28c4dc..ee623c16d835 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2246,7 +2246,6 @@ enum file_time_flags {
 
 extern bool atime_needs_update(const struct path *, struct inode *);
 extern void touch_atime(const struct path *);
-int inode_update_time(struct inode *inode, int flags);
 
 static inline void file_accessed(struct file *file)
 {
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 02/11] fs: allow error returns from generic_update_time
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
  2025-12-23  0:37 ` [PATCH 01/11] fs: remove inode_update_time Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  0:37 ` [PATCH 03/11] fs: exit early in generic_update_time when there is no work Christoph Hellwig
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs,
	Chaitanya Kulkarni

Now that no caller looks at the updated flags, switch generic_update_time
to the same calling convention as the ->update_time method and return 0
or a negative errno.

This prepares for adding non-blocking timestamp updates that could return
-EAGAIN.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
---
 fs/gfs2/inode.c    | 3 +--
 fs/inode.c         | 4 ++--
 fs/ubifs/file.c    | 6 ++----
 fs/xfs/xfs_iops.c  | 6 ++----
 include/linux/fs.h | 2 +-
 5 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 36618e353199..e08eb419347c 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2257,8 +2257,7 @@ static int gfs2_update_time(struct inode *inode, int flags)
 		if (error)
 			return error;
 	}
-	generic_update_time(inode, flags);
-	return 0;
+	return generic_update_time(inode, flags);
 }
 
 static const struct inode_operations gfs2_file_iops = {
diff --git a/fs/inode.c b/fs/inode.c
index 07effa0cb999..7eb28dd45a5a 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2141,7 +2141,7 @@ EXPORT_SYMBOL(inode_update_timestamps);
  * or S_VERSION need to be updated we attempt to update all three of them. S_ATIME
  * updates can be handled done independently of the rest.
  *
- * Returns a S_* mask indicating which fields were updated.
+ * Returns a negative error value on error, else 0.
  */
 int generic_update_time(struct inode *inode, int flags)
 {
@@ -2153,7 +2153,7 @@ int generic_update_time(struct inode *inode, int flags)
 	if (updated & S_VERSION)
 		dirty_flags |= I_DIRTY_SYNC;
 	__mark_inode_dirty(inode, dirty_flags);
-	return updated;
+	return 0;
 }
 EXPORT_SYMBOL(generic_update_time);
 
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index c3265b8804f5..ec1bb9f43acc 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1379,10 +1379,8 @@ int ubifs_update_time(struct inode *inode, int flags)
 			.dirtied_ino_d = ALIGN(ui->data_len, 8) };
 	int err, release;
 
-	if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT)) {
-		generic_update_time(inode, flags);
-		return 0;
-	}
+	if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
+		return generic_update_time(inode, flags);
 
 	err = ubifs_budget_space(c, &req);
 	if (err)
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index ad94fbf55014..9dedb54e3cb0 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1197,10 +1197,8 @@ xfs_vn_update_time(
 
 	if (inode->i_sb->s_flags & SB_LAZYTIME) {
 		if (!((flags & S_VERSION) &&
-		      inode_maybe_inc_iversion(inode, false))) {
-			generic_update_time(inode, flags);
-			return 0;
-		}
+		      inode_maybe_inc_iversion(inode, false)))
+			return generic_update_time(inode, flags);
 
 		/* Capture the iversion update that just occurred */
 		log_flags |= XFS_ILOG_CORE;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ee623c16d835..fccb0a38cb74 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2399,7 +2399,7 @@ extern void ihold(struct inode * inode);
 extern void iput(struct inode *);
 void iput_not_last(struct inode *);
 int inode_update_timestamps(struct inode *inode, int flags);
-int generic_update_time(struct inode *, int);
+int generic_update_time(struct inode *inode, int flags);
 
 /* /sys/fs */
 extern struct kobject *fs_kobj;
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 03/11] fs: exit early in generic_update_time when there is no work
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
  2025-12-23  0:37 ` [PATCH 01/11] fs: remove inode_update_time Christoph Hellwig
  2025-12-23  0:37 ` [PATCH 02/11] fs: allow error returns from generic_update_time Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  5:33   ` Chaitanya Kulkarni
  2025-12-23  0:37 ` [PATCH 04/11] fs: delay the actual timestamp updates in inode_update_timestamps Christoph Hellwig
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

Exit early if no attributes are to be updated, to avoid a spurious call
to __mark_inode_dirty which can turn into a fairly expensive no-op due to
the extra checks and locking.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
---
 fs/inode.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/inode.c b/fs/inode.c
index 7eb28dd45a5a..876641a6e478 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2148,6 +2148,9 @@ int generic_update_time(struct inode *inode, int flags)
 	int updated = inode_update_timestamps(inode, flags);
 	int dirty_flags = 0;
 
+	if (!updated)
+		return 0;
+
 	if (updated & (S_ATIME|S_MTIME|S_CTIME))
 		dirty_flags = inode->i_sb->s_flags & SB_LAZYTIME ? I_DIRTY_TIME : I_DIRTY_SYNC;
 	if (updated & S_VERSION)
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 04/11] fs: delay the actual timestamp updates in inode_update_timestamps
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (2 preceding siblings ...)
  2025-12-23  0:37 ` [PATCH 03/11] fs: exit early in generic_update_time when there is no work Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  5:35   ` Chaitanya Kulkarni
  2025-12-23  0:37 ` [PATCH 05/11] fs: return I_DIRTY_* and allow error returns from inode_update_timestamps Christoph Hellwig
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

Perform the actual updates of the inode timestamp at the very end of
inode_update_timestamps after finishing all checks.  This prepares for
adding non-blocking timestamp updates where we might bail out instead of
performing this updates if the update would block.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/inode.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/fs/inode.c b/fs/inode.c
index 876641a6e478..19f50bdb6f7d 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2109,10 +2109,8 @@ int inode_update_timestamps(struct inode *inode, int flags)
 		now = inode_set_ctime_current(inode);
 		if (!timespec64_equal(&now, &ctime))
 			updated |= S_CTIME;
-		if (!timespec64_equal(&now, &mtime)) {
-			inode_set_mtime_to_ts(inode, now);
+		if (!timespec64_equal(&now, &mtime))
 			updated |= S_MTIME;
-		}
 		if (IS_I_VERSION(inode) && inode_maybe_inc_iversion(inode, updated))
 			updated |= S_VERSION;
 	} else {
@@ -2122,11 +2120,14 @@ int inode_update_timestamps(struct inode *inode, int flags)
 	if (flags & S_ATIME) {
 		struct timespec64 atime = inode_get_atime(inode);
 
-		if (!timespec64_equal(&now, &atime)) {
-			inode_set_atime_to_ts(inode, now);
+		if (!timespec64_equal(&now, &atime))
 			updated |= S_ATIME;
-		}
 	}
+
+	if (updated & S_MTIME)
+		inode_set_mtime_to_ts(inode, now);
+	if (updated & S_ATIME)
+		inode_set_atime_to_ts(inode, now);
 	return updated;
 }
 EXPORT_SYMBOL(inode_update_timestamps);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 05/11] fs: return I_DIRTY_* and allow error returns from inode_update_timestamps
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (3 preceding siblings ...)
  2025-12-23  0:37 ` [PATCH 04/11] fs: delay the actual timestamp updates in inode_update_timestamps Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  5:36   ` Chaitanya Kulkarni
  2025-12-23  0:37 ` [PATCH 06/11] fs: factor out a sync_lazytime helper Christoph Hellwig
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

Change the inode_update_timestamps calling convention, so that instead
of returning the updated flags that are only needed to calculate the
I_DIRTY_* flags, return the I_DIRTY_* flags diretly in an argument, and
reserve the return value to return an error code, which will be needed to
support non-blocking timestamp updates.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/btrfs/inode.c    |  8 +++++---
 fs/inode.c          | 44 ++++++++++++++++++++++++++++----------------
 fs/nfs/inode.c      |  4 ++--
 fs/orangefs/inode.c |  5 ++++-
 fs/ubifs/file.c     |  4 ++--
 include/linux/fs.h  |  2 +-
 6 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 317db7d10a21..b04842c83eef 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6349,13 +6349,15 @@ static int btrfs_dirty_inode(struct btrfs_inode *inode)
 static int btrfs_update_time(struct inode *inode, int flags)
 {
 	struct btrfs_root *root = BTRFS_I(inode)->root;
-	bool dirty;
+	int dirty_flags, error;
 
 	if (btrfs_root_readonly(root))
 		return -EROFS;
 
-	dirty = inode_update_timestamps(inode, flags);
-	return dirty ? btrfs_dirty_inode(BTRFS_I(inode)) : 0;
+	error = inode_update_timestamps(inode, flags, &dirty_flags);
+	if (error || !dirty_flags)
+		return error;
+	return btrfs_dirty_inode(BTRFS_I(inode));
 }
 
 /*
diff --git a/fs/inode.c b/fs/inode.c
index 19f50bdb6f7d..59fffb1dbdeb 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2081,10 +2081,18 @@ static bool relatime_need_update(struct vfsmount *mnt, struct inode *inode,
 	return false;
 }
 
+static inline int timestamp_dirty_flag(struct super_block *sb)
+{
+	if (sb->s_flags & SB_LAZYTIME)
+		return I_DIRTY_TIME;
+	return I_DIRTY_SYNC;
+}
+
 /**
  * inode_update_timestamps - update the timestamps on the inode
  * @inode: inode to be updated
  * @flags: S_* flags that needed to be updated
+ * @dirty_flags: returns the I_DIRTY_* flags for the modification
  *
  * The update_time function is called when an inode's timestamps need to be
  * updated for a read or write operation. This function handles updating the
@@ -2095,14 +2103,18 @@ static bool relatime_need_update(struct vfsmount *mnt, struct inode *inode,
  * attempt to update all three of them. S_ATIME updates can be handled
  * independently of the rest.
  *
- * Returns a set of S_* flags indicating which values changed.
+ * Sets @dirty_flags to contain the I_DIRTY_FLAG_* flags for the actual changes.
+ *
+ * Returns 0 or a negative errno.
  */
-int inode_update_timestamps(struct inode *inode, int flags)
+int inode_update_timestamps(struct inode *inode, int flags, int *dirty_flags)
 {
-	int updated = 0;
 	struct timespec64 now;
+	int updated = 0;
 
-	if (flags & (S_MTIME|S_CTIME|S_VERSION)) {
+	*dirty_flags = 0;
+
+	if (flags & (S_MTIME | S_CTIME | S_VERSION)) {
 		struct timespec64 ctime = inode_get_ctime(inode);
 		struct timespec64 mtime = inode_get_mtime(inode);
 
@@ -2124,11 +2136,17 @@ int inode_update_timestamps(struct inode *inode, int flags)
 			updated |= S_ATIME;
 	}
 
+	if (updated & (S_MTIME | S_CTIME | S_MTIME))
+		*dirty_flags |= timestamp_dirty_flag(inode->i_sb);
+	if (updated & S_VERSION)
+		*dirty_flags |= I_DIRTY_SYNC;
+
 	if (updated & S_MTIME)
 		inode_set_mtime_to_ts(inode, now);
 	if (updated & S_ATIME)
 		inode_set_atime_to_ts(inode, now);
-	return updated;
+
+	return 0;
 }
 EXPORT_SYMBOL(inode_update_timestamps);
 
@@ -2146,18 +2164,12 @@ EXPORT_SYMBOL(inode_update_timestamps);
  */
 int generic_update_time(struct inode *inode, int flags)
 {
-	int updated = inode_update_timestamps(inode, flags);
-	int dirty_flags = 0;
-
-	if (!updated)
-		return 0;
+	int dirty_flags, error;
 
-	if (updated & (S_ATIME|S_MTIME|S_CTIME))
-		dirty_flags = inode->i_sb->s_flags & SB_LAZYTIME ? I_DIRTY_TIME : I_DIRTY_SYNC;
-	if (updated & S_VERSION)
-		dirty_flags |= I_DIRTY_SYNC;
-	__mark_inode_dirty(inode, dirty_flags);
-	return 0;
+	error = inode_update_timestamps(inode, flags, &dirty_flags);
+	if (!error && dirty_flags)
+		__mark_inode_dirty(inode, dirty_flags);
+	return error;
 }
 EXPORT_SYMBOL(generic_update_time);
 
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 84049f3cd340..6dfe382cb9fa 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -671,8 +671,8 @@ static void nfs_set_timestamps_to_ts(struct inode *inode, struct iattr *attr)
 
 static void nfs_update_timestamps(struct inode *inode, unsigned int ia_valid)
 {
-	enum file_time_flags time_flags = 0;
 	unsigned int cache_flags = 0;
+	int time_flags = 0, dirty_flags;
 
 	if (ia_valid & ATTR_MTIME) {
 		time_flags |= S_MTIME | S_CTIME;
@@ -682,7 +682,7 @@ static void nfs_update_timestamps(struct inode *inode, unsigned int ia_valid)
 		time_flags |= S_ATIME;
 		cache_flags |= NFS_INO_INVALID_ATIME;
 	}
-	inode_update_timestamps(inode, time_flags);
+	inode_update_timestamps(inode, time_flags, &dirty_flags);
 	NFS_I(inode)->cache_validity &= ~cache_flags;
 }
 
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index d7275990ffa4..beb45690081c 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -875,11 +875,14 @@ int orangefs_permission(struct mnt_idmap *idmap,
 int orangefs_update_time(struct inode *inode, int flags)
 {
 	struct iattr iattr;
+	int error, dirty_flags;
 
 	gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_update_time: %pU\n",
 	    get_khandle_from_ino(inode));
 
-	flags = inode_update_timestamps(inode, flags);
+	error = inode_update_timestamps(inode, flags, &dirty_flags);
+	if (error || !flags)
+		return error;
 
 	memset(&iattr, 0, sizeof iattr);
         if (flags & S_ATIME)
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index ec1bb9f43acc..fe236886484c 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1377,7 +1377,7 @@ int ubifs_update_time(struct inode *inode, int flags)
 	struct ubifs_info *c = inode->i_sb->s_fs_info;
 	struct ubifs_budget_req req = { .dirtied_ino = 1,
 			.dirtied_ino_d = ALIGN(ui->data_len, 8) };
-	int err, release;
+	int err, release, dirty_flags;
 
 	if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
 		return generic_update_time(inode, flags);
@@ -1387,7 +1387,7 @@ int ubifs_update_time(struct inode *inode, int flags)
 		return err;
 
 	mutex_lock(&ui->ui_mutex);
-	inode_update_timestamps(inode, flags);
+	inode_update_timestamps(inode, flags, &dirty_flags);
 	release = ui->dirty;
 	__mark_inode_dirty(inode, I_DIRTY_SYNC);
 	mutex_unlock(&ui->ui_mutex);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index fccb0a38cb74..ec2f78db0977 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2398,7 +2398,7 @@ static inline void super_set_sysfs_name_generic(struct super_block *sb, const ch
 extern void ihold(struct inode * inode);
 extern void iput(struct inode *);
 void iput_not_last(struct inode *);
-int inode_update_timestamps(struct inode *inode, int flags);
+int inode_update_timestamps(struct inode *inode, int flags, int *dirty_flags);
 int generic_update_time(struct inode *inode, int flags);
 
 /* /sys/fs */
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 06/11] fs: factor out a sync_lazytime helper
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (4 preceding siblings ...)
  2025-12-23  0:37 ` [PATCH 05/11] fs: return I_DIRTY_* and allow error returns from inode_update_timestamps Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  5:36   ` Chaitanya Kulkarni
  2025-12-23  0:37 ` [PATCH 07/11] fs: add a ->sync_lazytime method Christoph Hellwig
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

Centralize how we synchronize a lazytime update into the actual on-disk
timestamp into a single helper.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
---
 fs/fs-writeback.c                | 22 +++++++++++++++-------
 fs/inode.c                       |  5 +----
 fs/internal.h                    |  3 ++-
 fs/sync.c                        |  4 ++--
 include/trace/events/writeback.h |  6 ------
 5 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 6800886c4d10..3d68b757136c 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -1711,6 +1711,16 @@ static void requeue_inode(struct inode *inode, struct bdi_writeback *wb,
 	}
 }
 
+bool sync_lazytime(struct inode *inode)
+{
+	if (!(inode_state_read_once(inode) & I_DIRTY_TIME))
+		return false;
+
+	trace_writeback_lazytime(inode);
+	mark_inode_dirty_sync(inode);
+	return true;
+}
+
 /*
  * Write out an inode and its dirty pages (or some of its dirty pages, depending
  * on @wbc->nr_to_write), and clear the relevant dirty flags from i_state.
@@ -1750,17 +1760,15 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
 	}
 
 	/*
-	 * If the inode has dirty timestamps and we need to write them, call
-	 * mark_inode_dirty_sync() to notify the filesystem about it and to
-	 * change I_DIRTY_TIME into I_DIRTY_SYNC.
+	 * For data integrity writeback, or when the dirty interval expired,
+	 * ask the file system to propagata lazy timestamp updates into real
+	 * dirty state.
 	 */
 	if ((inode_state_read_once(inode) & I_DIRTY_TIME) &&
 	    (wbc->sync_mode == WB_SYNC_ALL ||
 	     time_after(jiffies, inode->dirtied_time_when +
-			dirtytime_expire_interval * HZ))) {
-		trace_writeback_lazytime(inode);
-		mark_inode_dirty_sync(inode);
-	}
+			dirtytime_expire_interval * HZ)))
+		sync_lazytime(inode);
 
 	/*
 	 * Get and clear the dirty flags from i_state.  This needs to be done
diff --git a/fs/inode.c b/fs/inode.c
index 59fffb1dbdeb..212dab5c65ad 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1979,11 +1979,8 @@ void iput(struct inode *inode)
 	if (atomic_add_unless(&inode->i_count, -1, 1))
 		return;
 
-	if ((inode_state_read_once(inode) & I_DIRTY_TIME) && inode->i_nlink) {
-		trace_writeback_lazytime_iput(inode);
-		mark_inode_dirty_sync(inode);
+	if (inode->i_nlink && sync_lazytime(inode))
 		goto retry;
-	}
 
 	spin_lock(&inode->i_lock);
 	if (unlikely((inode_state_read(inode) & I_DIRTY_TIME) && inode->i_nlink)) {
diff --git a/fs/internal.h b/fs/internal.h
index ab638d41ab81..18a062c1b5b0 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -214,7 +214,8 @@ bool in_group_or_capable(struct mnt_idmap *idmap,
 /*
  * fs-writeback.c
  */
-extern long get_nr_dirty_inodes(void);
+long get_nr_dirty_inodes(void);
+bool sync_lazytime(struct inode *inode);
 
 /*
  * dcache.c
diff --git a/fs/sync.c b/fs/sync.c
index 431fc5f5be06..4283af7119d1 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -183,8 +183,8 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
 
 	if (!file->f_op->fsync)
 		return -EINVAL;
-	if (!datasync && (inode_state_read_once(inode) & I_DIRTY_TIME))
-		mark_inode_dirty_sync(inode);
+	if (!datasync)
+		sync_lazytime(inode);
 	return file->f_op->fsync(file, start, end, datasync);
 }
 EXPORT_SYMBOL(vfs_fsync_range);
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 311a341e6fe4..7162d03e69a5 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -856,12 +856,6 @@ DEFINE_EVENT(writeback_inode_template, writeback_lazytime,
 	TP_ARGS(inode)
 );
 
-DEFINE_EVENT(writeback_inode_template, writeback_lazytime_iput,
-	TP_PROTO(struct inode *inode),
-
-	TP_ARGS(inode)
-);
-
 DEFINE_EVENT(writeback_inode_template, writeback_dirty_inode_enqueue,
 
 	TP_PROTO(struct inode *inode),
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 07/11] fs: add a ->sync_lazytime method
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (5 preceding siblings ...)
  2025-12-23  0:37 ` [PATCH 06/11] fs: factor out a sync_lazytime helper Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  5:37   ` Chaitanya Kulkarni
  2025-12-23  0:37 ` [PATCH 08/11] fs: add support for non-blocking timestamp updates Christoph Hellwig
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

Allow the file system to explicitly implement lazytime syncing instead
of pigging back on generic inode dirtying.  This allows to simplify
the XFS implementation and prepares for non-blocking lazytime timestamp
updates.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
---
 Documentation/filesystems/locking.rst |  2 ++
 Documentation/filesystems/vfs.rst     |  6 ++++++
 fs/fs-writeback.c                     | 13 +++++++++++--
 include/linux/fs.h                    |  1 +
 4 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
index 77704fde9845..9b2f14ada8cd 100644
--- a/Documentation/filesystems/locking.rst
+++ b/Documentation/filesystems/locking.rst
@@ -81,6 +81,7 @@ prototypes::
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
 	void (*update_time)(struct inode *, struct timespec *, int);
+	void (*sync_lazytime)(struct inode *inode);
 	int (*atomic_open)(struct inode *, struct dentry *,
 				struct file *, unsigned open_flag,
 				umode_t create_mode);
@@ -117,6 +118,7 @@ getattr:	no
 listxattr:	no
 fiemap:		no
 update_time:	no
+sync_lazytime:	no
 atomic_open:	shared (exclusive if O_CREAT is set in open flags)
 tmpfile:	no
 fileattr_get:	no or exclusive
diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
index 670ba66b60e4..4509655d12c6 100644
--- a/Documentation/filesystems/vfs.rst
+++ b/Documentation/filesystems/vfs.rst
@@ -486,6 +486,7 @@ As of kernel 2.6.22, the following members are defined:
 		int (*getattr) (struct mnt_idmap *, const struct path *, struct kstat *, u32, unsigned int);
 		ssize_t (*listxattr) (struct dentry *, char *, size_t);
 		void (*update_time)(struct inode *, struct timespec *, int);
+		void (*sync_lazytime)(struct inode *inode);
 		int (*atomic_open)(struct inode *, struct dentry *, struct file *,
 				   unsigned open_flag, umode_t create_mode);
 		int (*tmpfile) (struct mnt_idmap *, struct inode *, struct file *, umode_t);
@@ -642,6 +643,11 @@ otherwise noted.
 	an inode.  If this is not defined the VFS will update the inode
 	itself and call mark_inode_dirty_sync.
 
+``sync_lazytime``:
+	called by the writeback code to update the lazy time stamps to
+	regular time stamp updates that get syncing into the on-disk
+	inode.
+
 ``atomic_open``
 	called on the last component of an open.  Using this optional
 	method the filesystem can look up, possibly create and open the
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 3d68b757136c..62658be2578b 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -1717,7 +1717,10 @@ bool sync_lazytime(struct inode *inode)
 		return false;
 
 	trace_writeback_lazytime(inode);
-	mark_inode_dirty_sync(inode);
+	if (inode->i_op->sync_lazytime)
+		inode->i_op->sync_lazytime(inode);
+	else
+		mark_inode_dirty_sync(inode);
 	return true;
 }
 
@@ -2569,6 +2572,8 @@ void __mark_inode_dirty(struct inode *inode, int flags)
 	trace_writeback_mark_inode_dirty(inode, flags);
 
 	if (flags & I_DIRTY_INODE) {
+		bool was_dirty_time = false;
+
 		/*
 		 * Inode timestamp update will piggback on this dirtying.
 		 * We tell ->dirty_inode callback that timestamps need to
@@ -2579,6 +2584,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
 			if (inode_state_read(inode) & I_DIRTY_TIME) {
 				inode_state_clear(inode, I_DIRTY_TIME);
 				flags |= I_DIRTY_TIME;
+				was_dirty_time = true;
 			}
 			spin_unlock(&inode->i_lock);
 		}
@@ -2591,9 +2597,12 @@ void __mark_inode_dirty(struct inode *inode, int flags)
 		 * for just I_DIRTY_PAGES or I_DIRTY_TIME.
 		 */
 		trace_writeback_dirty_inode_start(inode, flags);
-		if (sb->s_op->dirty_inode)
+		if (sb->s_op->dirty_inode) {
 			sb->s_op->dirty_inode(inode,
 				flags & (I_DIRTY_INODE | I_DIRTY_TIME));
+		} else if (was_dirty_time && inode->i_op->sync_lazytime) {
+			inode->i_op->sync_lazytime(inode);
+		}
 		trace_writeback_dirty_inode(inode, flags);
 
 		/* I_DIRTY_INODE supersedes I_DIRTY_TIME. */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ec2f78db0977..d1d57149aa93 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2011,6 +2011,7 @@ struct inode_operations {
 	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
 		      u64 len);
 	int (*update_time)(struct inode *, int);
+	void (*sync_lazytime)(struct inode *inode);
 	int (*atomic_open)(struct inode *, struct dentry *,
 			   struct file *, unsigned open_flag,
 			   umode_t create_mode);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 08/11] fs: add support for non-blocking timestamp updates
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (6 preceding siblings ...)
  2025-12-23  0:37 ` [PATCH 07/11] fs: add a ->sync_lazytime method Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  5:38   ` Chaitanya Kulkarni
  2025-12-23  0:37 ` [PATCH 09/11] fat: enable " Christoph Hellwig
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

Currently file_update_time_flags unconditionally returns -EAGAIN if any
timestamp needs to be updated and IOCB_NOWAIT is passed.  This makes
non-blocking direct writes impossible on file systems with granular
enough timestamps.

Add a S_NOWAIT to ask for timestamps to not block, and return -EAGAIN in
all methods for now.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
---
 fs/fat/misc.c        |  3 +++
 fs/gfs2/inode.c      |  3 +++
 fs/inode.c           | 29 ++++++++++++++++++++++++++---
 fs/overlayfs/inode.c |  2 ++
 fs/ubifs/file.c      |  3 +++
 fs/xfs/xfs_iops.c    |  3 +++
 include/linux/fs.h   | 21 +++++++++++++++++----
 7 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 950da09f0961..5df3193c35f9 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -346,6 +346,9 @@ int fat_update_time(struct inode *inode, int flags)
 	if (inode->i_ino == MSDOS_ROOT_INO)
 		return 0;
 
+	if (flags & S_NOWAIT)
+		return -EAGAIN;
+
 	if (flags & (S_ATIME | S_CTIME | S_MTIME)) {
 		fat_truncate_time(inode, NULL, flags);
 		if (inode->i_sb->s_flags & SB_LAZYTIME)
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index e08eb419347c..0dce2af533b2 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2249,6 +2249,9 @@ static int gfs2_update_time(struct inode *inode, int flags)
 	struct gfs2_holder *gh;
 	int error;
 
+	if (flags & S_NOWAIT)
+		return -EAGAIN;
+
 	gh = gfs2_glock_is_locked_by_me(gl);
 	if (gh && gl->gl_state != LM_ST_EXCLUSIVE) {
 		gfs2_glock_dq(gh);
diff --git a/fs/inode.c b/fs/inode.c
index 212dab5c65ad..98a878427ecb 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2111,6 +2111,13 @@ int inode_update_timestamps(struct inode *inode, int flags, int *dirty_flags)
 
 	*dirty_flags = 0;
 
+	/*
+	 * Non-blocking timestamp updates require an explicit opt-in from the
+	 * file system.
+	 */
+	if ((flags & S_NOWAIT) && !(flags & S_CAN_NOWAIT_LAZYTIME))
+		return -EAGAIN;
+
 	if (flags & (S_MTIME | S_CTIME | S_VERSION)) {
 		struct timespec64 ctime = inode_get_ctime(inode);
 		struct timespec64 mtime = inode_get_mtime(inode);
@@ -2120,8 +2127,24 @@ int inode_update_timestamps(struct inode *inode, int flags, int *dirty_flags)
 			updated |= S_CTIME;
 		if (!timespec64_equal(&now, &mtime))
 			updated |= S_MTIME;
-		if (IS_I_VERSION(inode) && inode_maybe_inc_iversion(inode, updated))
-			updated |= S_VERSION;
+
+		/*
+		 * Pure timestamp updates can be recorded in the inode without
+		 * blocking by not dirtying the inode.  But when the file system
+		 * requires i_version updates, actual i_version update may block
+		 * despite that.  Error out if we'd actually have to update
+		 * i_version or don't support lazytime.
+		 */
+		if (IS_I_VERSION(inode)) {
+			if (flags & S_NOWAIT) {
+				if (!(inode->i_sb->s_flags & SB_LAZYTIME) ||
+				    inode_iversion_need_inc(inode))
+					return -EAGAIN;
+			} else {
+				if (inode_maybe_inc_iversion(inode, updated))
+					updated |= S_NOWAIT;
+			}
+		}
 	} else {
 		now = current_time(inode);
 	}
@@ -2391,7 +2414,7 @@ static int file_update_time_flags(struct file *file, unsigned int flags)
 		return 0;
 
 	if (flags & IOCB_NOWAIT)
-		return -EAGAIN;
+		sync_mode |= S_NOWAIT;
 
 	if (mnt_get_write_access_file(file))
 		return 0;
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index bdbf86b56a9b..6d23cacbf776 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -565,6 +565,8 @@ int ovl_update_time(struct inode *inode, int flags)
 		};
 
 		if (upperpath.dentry) {
+			if (flags & S_NOWAIT)
+				return -EAGAIN;
 			touch_atime(&upperpath);
 			inode_set_atime_to_ts(inode,
 					      inode_get_atime(d_inode(upperpath.dentry)));
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index fe236886484c..b74dd4d21330 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1382,6 +1382,9 @@ int ubifs_update_time(struct inode *inode, int flags)
 	if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
 		return generic_update_time(inode, flags);
 
+	if (flags & S_NOWAIT)
+		return -EAGAIN;
+
 	err = ubifs_budget_space(c, &req);
 	if (err)
 		return err;
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 9dedb54e3cb0..626a541b247b 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1195,6 +1195,9 @@ xfs_vn_update_time(
 
 	trace_xfs_update_time(ip);
 
+	if (flags & S_NOWAIT)
+		return -EAGAIN;
+
 	if (inode->i_sb->s_flags & SB_LAZYTIME) {
 		if (!((flags & S_VERSION) &&
 		      inode_maybe_inc_iversion(inode, false)))
diff --git a/include/linux/fs.h b/include/linux/fs.h
index d1d57149aa93..0ea175e19a8b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2239,10 +2239,23 @@ static inline void inode_dec_link_count(struct inode *inode)
 }
 
 enum file_time_flags {
-	S_ATIME = 1,
-	S_MTIME = 2,
-	S_CTIME = 4,
-	S_VERSION = 8,
+	/* update atime: */
+	S_ATIME			= 1U << 0,
+
+	/* update mtime */
+	S_MTIME			= 1U << 1,
+
+	/* update ctime */
+	S_CTIME			= 1U << 2,
+
+	/* force update i_version even if no timestamp changes */
+	S_VERSION		= 1U << 3,
+
+	/* only update timestamps or i_version if it doesn't require blocking */
+	S_NOWAIT		= 1U << 14,
+
+	/* support S_NOWAIT for SB_LAZYTIME mounts in inode_update_timestamps */
+	S_CAN_NOWAIT_LAZYTIME	= 1U << 15,
 };
 
 extern bool atime_needs_update(const struct path *, struct inode *);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 09/11] fat: enable non-blocking timestamp updates
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (7 preceding siblings ...)
  2025-12-23  0:37 ` [PATCH 08/11] fs: add support for non-blocking timestamp updates Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  0:37 ` [PATCH 10/11] xfs: implement ->sync_lazytime Christoph Hellwig
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

As fat dosn't implement ->dirty_inode, nothing in fat_update_time can
block, and fat can thus trivially implement non-blocking timestamp
updates.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 fs/fat/misc.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 5df3193c35f9..950da09f0961 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -346,9 +346,6 @@ int fat_update_time(struct inode *inode, int flags)
 	if (inode->i_ino == MSDOS_ROOT_INO)
 		return 0;
 
-	if (flags & S_NOWAIT)
-		return -EAGAIN;
-
 	if (flags & (S_ATIME | S_CTIME | S_MTIME)) {
 		fat_truncate_time(inode, NULL, flags);
 		if (inode->i_sb->s_flags & SB_LAZYTIME)
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 10/11] xfs: implement ->sync_lazytime
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (8 preceding siblings ...)
  2025-12-23  0:37 ` [PATCH 09/11] fat: enable " Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  0:37 ` [PATCH 11/11] xfs: enable non-blocking timestamp updates Christoph Hellwig
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

Switch to the new explicit lazytime syncing method instead of trying
to second guess what could be a lazytime update in ->dirty_inode.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
---
 fs/xfs/xfs_iops.c  | 20 ++++++++++++++++++++
 fs/xfs/xfs_super.c | 29 -----------------------------
 2 files changed, 20 insertions(+), 29 deletions(-)

diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 626a541b247b..e12c6e6d313e 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1227,6 +1227,22 @@ xfs_vn_update_time(
 	return xfs_trans_commit(tp);
 }
 
+static void
+xfs_vn_sync_lazytime(
+	struct inode		*inode)
+{
+	struct xfs_inode	*ip = XFS_I(inode);
+	struct xfs_mount	*mp = ip->i_mount;
+	struct xfs_trans	*tp;
+
+	if (xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp))
+		return;
+	xfs_ilock(ip, XFS_ILOCK_EXCL);
+	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+	xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP);
+	xfs_trans_commit(tp);
+}
+
 STATIC int
 xfs_vn_fiemap(
 	struct inode		*inode,
@@ -1270,6 +1286,7 @@ static const struct inode_operations xfs_inode_operations = {
 	.listxattr		= xfs_vn_listxattr,
 	.fiemap			= xfs_vn_fiemap,
 	.update_time		= xfs_vn_update_time,
+	.sync_lazytime		= xfs_vn_sync_lazytime,
 	.fileattr_get		= xfs_fileattr_get,
 	.fileattr_set		= xfs_fileattr_set,
 };
@@ -1296,6 +1313,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
 	.setattr		= xfs_vn_setattr,
 	.listxattr		= xfs_vn_listxattr,
 	.update_time		= xfs_vn_update_time,
+	.sync_lazytime		= xfs_vn_sync_lazytime,
 	.tmpfile		= xfs_vn_tmpfile,
 	.fileattr_get		= xfs_fileattr_get,
 	.fileattr_set		= xfs_fileattr_set,
@@ -1323,6 +1341,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
 	.setattr		= xfs_vn_setattr,
 	.listxattr		= xfs_vn_listxattr,
 	.update_time		= xfs_vn_update_time,
+	.sync_lazytime		= xfs_vn_sync_lazytime,
 	.tmpfile		= xfs_vn_tmpfile,
 	.fileattr_get		= xfs_fileattr_get,
 	.fileattr_set		= xfs_fileattr_set,
@@ -1334,6 +1353,7 @@ static const struct inode_operations xfs_symlink_inode_operations = {
 	.setattr		= xfs_vn_setattr,
 	.listxattr		= xfs_vn_listxattr,
 	.update_time		= xfs_vn_update_time,
+	.sync_lazytime		= xfs_vn_sync_lazytime,
 	.fileattr_get		= xfs_fileattr_get,
 	.fileattr_set		= xfs_fileattr_set,
 };
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index bc71aa9dcee8..094f257eff15 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -712,34 +712,6 @@ xfs_fs_destroy_inode(
 	xfs_inode_mark_reclaimable(ip);
 }
 
-static void
-xfs_fs_dirty_inode(
-	struct inode			*inode,
-	int				flags)
-{
-	struct xfs_inode		*ip = XFS_I(inode);
-	struct xfs_mount		*mp = ip->i_mount;
-	struct xfs_trans		*tp;
-
-	if (!(inode->i_sb->s_flags & SB_LAZYTIME))
-		return;
-
-	/*
-	 * Only do the timestamp update if the inode is dirty (I_DIRTY_SYNC)
-	 * and has dirty timestamp (I_DIRTY_TIME). I_DIRTY_TIME can be passed
-	 * in flags possibly together with I_DIRTY_SYNC.
-	 */
-	if ((flags & ~I_DIRTY_TIME) != I_DIRTY_SYNC || !(flags & I_DIRTY_TIME))
-		return;
-
-	if (xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp))
-		return;
-	xfs_ilock(ip, XFS_ILOCK_EXCL);
-	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
-	xfs_trans_log_inode(tp, ip, XFS_ILOG_TIMESTAMP);
-	xfs_trans_commit(tp);
-}
-
 /*
  * Slab object creation initialisation for the XFS inode.
  * This covers only the idempotent fields in the XFS inode;
@@ -1304,7 +1276,6 @@ xfs_fs_show_stats(
 static const struct super_operations xfs_super_operations = {
 	.alloc_inode		= xfs_fs_alloc_inode,
 	.destroy_inode		= xfs_fs_destroy_inode,
-	.dirty_inode		= xfs_fs_dirty_inode,
 	.drop_inode		= xfs_fs_drop_inode,
 	.evict_inode		= xfs_fs_evict_inode,
 	.put_super		= xfs_fs_put_super,
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 11/11] xfs: enable non-blocking timestamp updates
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (9 preceding siblings ...)
  2025-12-23  0:37 ` [PATCH 10/11] xfs: implement ->sync_lazytime Christoph Hellwig
@ 2025-12-23  0:37 ` Christoph Hellwig
  2025-12-23  5:39   ` Chaitanya Kulkarni
  2025-12-23 22:53 ` re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
  2025-12-24 13:11 ` Christian Brauner
  12 siblings, 1 reply; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23  0:37 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

The lazytime path using the generic helpers can never block in XFS
because there is no ->dirty_inode method that could block.  Allow
non-blocking timestamp updates for this case by replacing
generic_update_time with the open coded version without the S_NOWAIT
check.

Fixes: 66fa3cedf16a ("fs: Add async write file modification handling.")
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
---
 fs/xfs/xfs_iops.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index e12c6e6d313e..1fba10281e54 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1195,16 +1195,23 @@ xfs_vn_update_time(
 
 	trace_xfs_update_time(ip);
 
-	if (flags & S_NOWAIT)
-		return -EAGAIN;
-
 	if (inode->i_sb->s_flags & SB_LAZYTIME) {
-		if (!((flags & S_VERSION) &&
-		      inode_maybe_inc_iversion(inode, false)))
-			return generic_update_time(inode, flags);
+		int dirty_flags;
+
+		error = inode_update_timestamps(inode,
+				flags | S_CAN_NOWAIT_LAZYTIME, &dirty_flags);
+		if (error)
+			return error;
+		if (dirty_flags == I_DIRTY_TIME) {
+			__mark_inode_dirty(inode, I_DIRTY_TIME);
+			return 0;
+		}
 
 		/* Capture the iversion update that just occurred */
 		log_flags |= XFS_ILOG_CORE;
+	} else {
+		if (flags & S_NOWAIT)
+			return -EAGAIN;
 	}
 
 	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_fsyncts, 0, 0, 0, &tp);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH 03/11] fs: exit early in generic_update_time when there is no work
  2025-12-23  0:37 ` [PATCH 03/11] fs: exit early in generic_update_time when there is no work Christoph Hellwig
@ 2025-12-23  5:33   ` Chaitanya Kulkarni
  0 siblings, 0 replies; 21+ messages in thread
From: Chaitanya Kulkarni @ 2025-12-23  5:33 UTC (permalink / raw)
  To: Christoph Hellwig, Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

On 12/22/25 16:37, Christoph Hellwig wrote:
> Exit early if no attributes are to be updated, to avoid a spurious call
> to __mark_inode_dirty which can turn into a fairly expensive no-op due to
> the extra checks and locking.
>
> Signed-off-by: Christoph Hellwig<hch@lst.de>
> Reviewed-by: Jan Kara<jack@suse.cz>
> Reviewed-by: Jeff Layton<jlayton@kernel.org>


Looks good.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>

-ck



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 04/11] fs: delay the actual timestamp updates in inode_update_timestamps
  2025-12-23  0:37 ` [PATCH 04/11] fs: delay the actual timestamp updates in inode_update_timestamps Christoph Hellwig
@ 2025-12-23  5:35   ` Chaitanya Kulkarni
  0 siblings, 0 replies; 21+ messages in thread
From: Chaitanya Kulkarni @ 2025-12-23  5:35 UTC (permalink / raw)
  To: Christoph Hellwig, Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

On 12/22/25 16:37, Christoph Hellwig wrote:
> Perform the actual updates of the inode timestamp at the very end of
> inode_update_timestamps after finishing all checks.  This prepares for
> adding non-blocking timestamp updates where we might bail out instead of
> performing this updates if the update would block.
>
> Signed-off-by: Christoph Hellwig<hch@lst.de>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>

-ck



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 05/11] fs: return I_DIRTY_* and allow error returns from inode_update_timestamps
  2025-12-23  0:37 ` [PATCH 05/11] fs: return I_DIRTY_* and allow error returns from inode_update_timestamps Christoph Hellwig
@ 2025-12-23  5:36   ` Chaitanya Kulkarni
  0 siblings, 0 replies; 21+ messages in thread
From: Chaitanya Kulkarni @ 2025-12-23  5:36 UTC (permalink / raw)
  To: Christoph Hellwig, Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

On 12/22/25 16:37, Christoph Hellwig wrote:
> Change the inode_update_timestamps calling convention, so that instead
> of returning the updated flags that are only needed to calculate the
> I_DIRTY_* flags, return the I_DIRTY_* flags diretly in an argument, and
> reserve the return value to return an error code, which will be needed to
> support non-blocking timestamp updates.
>
> Signed-off-by: Christoph Hellwig<hch@lst.de>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>

-ck



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 06/11] fs: factor out a sync_lazytime helper
  2025-12-23  0:37 ` [PATCH 06/11] fs: factor out a sync_lazytime helper Christoph Hellwig
@ 2025-12-23  5:36   ` Chaitanya Kulkarni
  0 siblings, 0 replies; 21+ messages in thread
From: Chaitanya Kulkarni @ 2025-12-23  5:36 UTC (permalink / raw)
  To: Christoph Hellwig, Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

On 12/22/25 16:37, Christoph Hellwig wrote:
> Centralize how we synchronize a lazytime update into the actual on-disk
> timestamp into a single helper.
>
> Signed-off-by: Christoph Hellwig<hch@lst.de>
> Reviewed-by: Jan Kara<jack@suse.cz>
> Reviewed-by: Jeff Layton<jlayton@kernel.org>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>

-ck



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 07/11] fs: add a ->sync_lazytime method
  2025-12-23  0:37 ` [PATCH 07/11] fs: add a ->sync_lazytime method Christoph Hellwig
@ 2025-12-23  5:37   ` Chaitanya Kulkarni
  0 siblings, 0 replies; 21+ messages in thread
From: Chaitanya Kulkarni @ 2025-12-23  5:37 UTC (permalink / raw)
  To: Christoph Hellwig, Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

On 12/22/25 16:37, Christoph Hellwig wrote:
> Allow the file system to explicitly implement lazytime syncing instead
> of pigging back on generic inode dirtying.  This allows to simplify
> the XFS implementation and prepares for non-blocking lazytime timestamp
> updates.
>
> Signed-off-by: Christoph Hellwig<hch@lst.de>
> Reviewed-by: Jeff Layton<jlayton@kernel.org>


Looks good.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>

-ck


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 08/11] fs: add support for non-blocking timestamp updates
  2025-12-23  0:37 ` [PATCH 08/11] fs: add support for non-blocking timestamp updates Christoph Hellwig
@ 2025-12-23  5:38   ` Chaitanya Kulkarni
  0 siblings, 0 replies; 21+ messages in thread
From: Chaitanya Kulkarni @ 2025-12-23  5:38 UTC (permalink / raw)
  To: Christoph Hellwig, Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

On 12/22/25 16:37, Christoph Hellwig wrote:
> Currently file_update_time_flags unconditionally returns -EAGAIN if any
> timestamp needs to be updated and IOCB_NOWAIT is passed.  This makes
> non-blocking direct writes impossible on file systems with granular
> enough timestamps.
>
> Add a S_NOWAIT to ask for timestamps to not block, and return -EAGAIN in
> all methods for now.
>
> Signed-off-by: Christoph Hellwig<hch@lst.de>
> Reviewed-by: Jeff Layton<jlayton@kernel.org>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>

-ck



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 11/11] xfs: enable non-blocking timestamp updates
  2025-12-23  0:37 ` [PATCH 11/11] xfs: enable non-blocking timestamp updates Christoph Hellwig
@ 2025-12-23  5:39   ` Chaitanya Kulkarni
  0 siblings, 0 replies; 21+ messages in thread
From: Chaitanya Kulkarni @ 2025-12-23  5:39 UTC (permalink / raw)
  To: Christoph Hellwig, Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

On 12/22/25 16:37, Christoph Hellwig wrote:
> The lazytime path using the generic helpers can never block in XFS
> because there is no ->dirty_inode method that could block.  Allow
> non-blocking timestamp updates for this case by replacing
> generic_update_time with the open coded version without the S_NOWAIT
> check.
>
> Fixes: 66fa3cedf16a ("fs: Add async write file modification handling.")
> Signed-off-by: Christoph Hellwig<hch@lst.de>
> Reviewed-by: Jeff Layton<jlayton@kernel.org>


Looks good.

Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>

-ck



^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: re-enable IOCB_NOWAIT writes to files v4
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (10 preceding siblings ...)
  2025-12-23  0:37 ` [PATCH 11/11] xfs: enable non-blocking timestamp updates Christoph Hellwig
@ 2025-12-23 22:53 ` Christoph Hellwig
  2025-12-24 13:11 ` Christian Brauner
  12 siblings, 0 replies; 21+ messages in thread
From: Christoph Hellwig @ 2025-12-23 22:53 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

Julia found a nice little typo in the new changes, which really
wants me to split the atime from c/mtime update path badly.  So
don't feel rushed to review this version and enjoy the holidays,
there will be a new one soon.

On Tue, Dec 23, 2025 at 09:37:43AM +0900, Christoph Hellwig wrote:
> Hi all,
> 
> commit 66fa3cedf16a ("fs: Add async write file modification handling.")
> effectively disabled IOCB_NOWAIT writes as timestamp updates currently
> always require blocking, and the modern timestamp resolution means we
> always update timestamps.  This leads to a lot of context switches from
> applications using io_uring to submit file writes, making it often worse
> than using the legacy aio code that is not using IOCB_NOWAIT.
> 
> This series allows non-blocking updates for lazytime if the file system
> supports it, and adds that support for XFS.
> 
> Changes since v3:
>  - fix was_dirty_time handling in __mark_inode_dirty for the racy flag
>    update case
>  - refactor inode_update_timestamps to make the lazytime vs blocking
>    logical more clear
>  - allow non-blocking timestamp updates for fat
> 
> Changes since v2:
>  - drop patches merged upstream
>  - adjust for the inode state accesors
>  - keep a check in __writeback_single_inode instead of exercising
>    potentially undefined behavior
>  - more spelling fixes
> 
> Changes since v1:
>  - more regular numbering of the S_* flags
>  - fix XFS to actually not block
>  - don't ignore the generic_update_time return value in
>    file_update_time_flags
>  - fix the sync_lazytime return value
>  - fix an out of data comment in btrfs
>  - fix a race that would update i_version before returning -EAGAIN in XFS
> 
> Diffstat:
>  Documentation/filesystems/locking.rst |    2 
>  Documentation/filesystems/vfs.rst     |    6 +
>  fs/btrfs/inode.c                      |    8 +-
>  fs/fs-writeback.c                     |   33 +++++++---
>  fs/gfs2/inode.c                       |    6 +
>  fs/inode.c                            |  111 +++++++++++++++++++++-------------
>  fs/internal.h                         |    3 
>  fs/nfs/inode.c                        |    4 -
>  fs/orangefs/inode.c                   |    5 +
>  fs/overlayfs/inode.c                  |    2 
>  fs/sync.c                             |    4 -
>  fs/ubifs/file.c                       |   13 ++-
>  fs/xfs/xfs_iops.c                     |   34 +++++++++-
>  fs/xfs/xfs_super.c                    |   29 --------
>  include/linux/fs.h                    |   27 ++++++--
>  include/trace/events/writeback.h      |    6 -
>  16 files changed, 182 insertions(+), 111 deletions(-)
---end quoted text---

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: re-enable IOCB_NOWAIT writes to files v4
  2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
                   ` (11 preceding siblings ...)
  2025-12-23 22:53 ` re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
@ 2025-12-24 13:11 ` Christian Brauner
  12 siblings, 0 replies; 21+ messages in thread
From: Christian Brauner @ 2025-12-24 13:11 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Christian Brauner, Al Viro, David Sterba, Jan Kara, Mike Marshall,
	Martin Brandenburg, Carlos Maiolino, Stefan Roesch, Jeff Layton,
	linux-kernel, linux-btrfs, linux-fsdevel, gfs2, io-uring, devel,
	linux-unionfs, linux-mtd, linux-xfs, linux-nfs

On Tue, 23 Dec 2025 09:37:43 +0900, Christoph Hellwig wrote:
> commit 66fa3cedf16a ("fs: Add async write file modification handling.")
> effectively disabled IOCB_NOWAIT writes as timestamp updates currently
> always require blocking, and the modern timestamp resolution means we
> always update timestamps.  This leads to a lot of context switches from
> applications using io_uring to submit file writes, making it often worse
> than using the legacy aio code that is not using IOCB_NOWAIT.
> 
> [...]

Applied to the vfs-7.0.nonblocking_timestamps branch of the vfs/vfs.git tree.
Patches in the vfs-7.0.nonblocking_timestamps branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs-7.0.nonblocking_timestamps

[01/11] fs: remove inode_update_time
        https://git.kernel.org/vfs/vfs/c/a3c5dc04be9f
[02/11] fs: allow error returns from generic_update_time
        https://git.kernel.org/vfs/vfs/c/829f055d68ee
[03/11] fs: exit early in generic_update_time when there is no work
        https://git.kernel.org/vfs/vfs/c/3c5f7a9696fa
[04/11] fs: delay the actual timestamp updates in inode_update_timestamps
        https://git.kernel.org/vfs/vfs/c/6e827e32c6ae
[05/11] fs: return I_DIRTY_* and allow error returns from inode_update_timestamps
        https://git.kernel.org/vfs/vfs/c/b79904581c69
[06/11] fs: factor out a sync_lazytime helper
        https://git.kernel.org/vfs/vfs/c/0cd53e2011e2
[07/11] fs: add a ->sync_lazytime method
        https://git.kernel.org/vfs/vfs/c/641284ff9133
[08/11] fs: add support for non-blocking timestamp updates
        https://git.kernel.org/vfs/vfs/c/3cb9ff38ddaf
[09/11] fat: enable non-blocking timestamp updates
        https://git.kernel.org/vfs/vfs/c/1736c77f0834
[10/11] xfs: implement ->sync_lazytime
        https://git.kernel.org/vfs/vfs/c/831c93b34fa4
[11/11] xfs: enable non-blocking timestamp updates
        https://git.kernel.org/vfs/vfs/c/bafbe984c54e

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2025-12-24 13:11 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-23  0:37 re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
2025-12-23  0:37 ` [PATCH 01/11] fs: remove inode_update_time Christoph Hellwig
2025-12-23  0:37 ` [PATCH 02/11] fs: allow error returns from generic_update_time Christoph Hellwig
2025-12-23  0:37 ` [PATCH 03/11] fs: exit early in generic_update_time when there is no work Christoph Hellwig
2025-12-23  5:33   ` Chaitanya Kulkarni
2025-12-23  0:37 ` [PATCH 04/11] fs: delay the actual timestamp updates in inode_update_timestamps Christoph Hellwig
2025-12-23  5:35   ` Chaitanya Kulkarni
2025-12-23  0:37 ` [PATCH 05/11] fs: return I_DIRTY_* and allow error returns from inode_update_timestamps Christoph Hellwig
2025-12-23  5:36   ` Chaitanya Kulkarni
2025-12-23  0:37 ` [PATCH 06/11] fs: factor out a sync_lazytime helper Christoph Hellwig
2025-12-23  5:36   ` Chaitanya Kulkarni
2025-12-23  0:37 ` [PATCH 07/11] fs: add a ->sync_lazytime method Christoph Hellwig
2025-12-23  5:37   ` Chaitanya Kulkarni
2025-12-23  0:37 ` [PATCH 08/11] fs: add support for non-blocking timestamp updates Christoph Hellwig
2025-12-23  5:38   ` Chaitanya Kulkarni
2025-12-23  0:37 ` [PATCH 09/11] fat: enable " Christoph Hellwig
2025-12-23  0:37 ` [PATCH 10/11] xfs: implement ->sync_lazytime Christoph Hellwig
2025-12-23  0:37 ` [PATCH 11/11] xfs: enable non-blocking timestamp updates Christoph Hellwig
2025-12-23  5:39   ` Chaitanya Kulkarni
2025-12-23 22:53 ` re-enable IOCB_NOWAIT writes to files v4 Christoph Hellwig
2025-12-24 13:11 ` Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox