@@ -2054,35 +2054,22 @@ int file_remove_privs(struct file *file)
}
EXPORT_SYMBOL(file_remove_privs);
-/**
- * file_update_time - update mtime and ctime time
- * @file: file accessed
- *
- * Update the mtime and ctime members of an inode and mark the inode
- * for writeback. Note that this function is meant exclusively for
- * usage in the file write path of filesystems, and filesystems may
- * choose to explicitly ignore update via this function with the
- * S_NOCMTIME inode flag, e.g. for network filesystem where these
- * timestamps are handled by the server. This can return an error for
- * file systems who need to allocate space in order to update an inode.
- */
-
-int file_update_time(struct file *file)
+int need_file_update_time(struct inode *inode, struct file *file,
+ struct timespec64 *now)
{
- struct inode *inode = file_inode(file);
- struct timespec64 now;
int sync_it = 0;
- int ret;
+
+ if (unlikely(file->f_mode & FMODE_NOCMTIME))
+ return 0;
/* First try to exhaust all avenues to not sync */
if (IS_NOCMTIME(inode))
return 0;
- now = current_time(inode);
- if (!timespec64_equal(&inode->i_mtime, &now))
+ if (!timespec64_equal(&inode->i_mtime, now))
sync_it = S_MTIME;
- if (!timespec64_equal(&inode->i_ctime, &now))
+ if (!timespec64_equal(&inode->i_ctime, now))
sync_it |= S_CTIME;
if (IS_I_VERSION(inode) && inode_iversion_need_inc(inode))
@@ -2091,24 +2078,58 @@ int file_update_time(struct file *file)
if (!sync_it)
return 0;
+ return sync_it;
+}
+
+int do_file_update_time(struct inode *inode, struct file *file,
+ struct timespec64 *now, int sync_mode)
+{
+ int ret;
+
/* Finally allowed to write? Takes lock. */
if (__mnt_want_write_file(file))
return 0;
- ret = inode_update_time(inode, &now, sync_it);
+ ret = inode_update_time(inode, now, sync_mode);
__mnt_drop_write_file(file);
return ret;
}
+
+/**
+ * file_update_time - update mtime and ctime time
+ * @file: file accessed
+ *
+ * Update the mtime and ctime members of an inode and mark the inode
+ * for writeback. Note that this function is meant exclusively for
+ * usage in the file write path of filesystems, and filesystems may
+ * choose to explicitly ignore update via this function with the
+ * S_NOCMTIME inode flag, e.g. for network filesystem where these
+ * timestamps are handled by the server. This can return an error for
+ * file systems who need to allocate space in order to update an inode.
+ */
+
+int file_update_time(struct file *file)
+{
+ int err;
+ struct inode *inode = file_inode(file);
+ struct timespec64 now = current_time(inode);
+
+ err = need_file_update_time(inode, file, &now);
+ if (err < 0)
+ return err;
+
+ return do_file_update_time(inode, file, &now, err);
+}
EXPORT_SYMBOL(file_update_time);
/* Caller must hold the file's inode lock */
int file_modified(struct file *file)
{
- int err;
int ret;
struct dentry *dentry = file_dentry(file);
struct inode *inode = file_inode(file);
+ struct timespec64 now = current_time(inode);
/*
* Clear the security bits if the process is not being run by root.
@@ -2123,10 +2144,11 @@ int file_modified(struct file *file)
return ret;
}
- if (unlikely(file->f_mode & FMODE_NOCMTIME))
- return 0;
+ ret = need_file_update_time(inode, file, &now);
+ if (ret <= 0)
+ return ret;
- return file_update_time(file);
+ return do_file_update_time(inode, file, &now, ret);
}
EXPORT_SYMBOL(file_modified);
@@ -2384,6 +2384,11 @@ static inline void file_accessed(struct file *file)
extern int need_file_remove_privs(struct inode *inode, struct dentry *dentry);
extern int do_file_remove_privs(struct file *file, struct inode *inode,
struct dentry *dentry, int kill);
+extern int need_file_update_time(struct inode *inode, struct file *file,
+ struct timespec64 *now);
+extern int do_file_update_time(struct inode *inode, struct file *file,
+ struct timespec64 *now, int sync_mode);
+
extern int file_modified(struct file *file);
int sync_inode_metadata(struct inode *inode, int wait);
This splits off the functions need_file_update_time() and do_file_update_time() from the function file_update_time(). This is required to support async buffered writes. No intended functional changes in this patch. Signed-off-by: Stefan Roesch <shr@fb.com> --- fs/inode.c | 72 ++++++++++++++++++++++++++++++---------------- include/linux/fs.h | 5 ++++ 2 files changed, 52 insertions(+), 25 deletions(-)