[PATCH 05/11] fs: return I_DIRTY_* and allow error returns from inode_update_timestamps

Christoph Hellwig <[email protected]>
Newsgroups dev.linux.lists.gfs2,org.infradead.lists.linux-mtd,org.kernel.vger.io-uring,org.kernel.vger.linux-btrfs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-nfs,org.kernel.vger.linux-unionfs,org.kernel.vger.linux-xfs
Message-ID <[email protected]>
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 <[email protected]>
---
 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.