]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fs: refactor ->update_time handling
authorChristoph Hellwig <hch@lst.de>
Thu, 8 Jan 2026 14:19:05 +0000 (15:19 +0100)
committerChristian Brauner <brauner@kernel.org>
Mon, 12 Jan 2026 13:01:32 +0000 (14:01 +0100)
Pass the type of update (atime vs c/mtime plus version) as an enum
instead of a set of flags that caused all kinds of confusion.
Because inode_update_timestamps now can't return a modified version
of those flags, return the I_DIRTY_* flags needed to persist the
update, which is what the main caller in generic_update_time wants
anyway, and which is suitable for the other callers that only want
to know if an update happened.

The whole update_time path keeps the flags argument, which will be used
to support non-blocking updates soon even if it is unused, and (the
slightly renamed) inode_update_time also gains the possibility to return
a negative errno to support this.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://patch.msgid.link/20260108141934.2052404-6-hch@lst.de
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
17 files changed:
Documentation/filesystems/locking.rst
Documentation/filesystems/vfs.rst
fs/bad_inode.c
fs/btrfs/inode.c
fs/fat/fat.h
fs/fat/misc.c
fs/gfs2/inode.c
fs/inode.c
fs/nfs/inode.c
fs/orangefs/inode.c
fs/orangefs/orangefs-kernel.h
fs/overlayfs/inode.c
fs/overlayfs/overlayfs.h
fs/ubifs/file.c
fs/ubifs/ubifs.h
fs/xfs/xfs_iops.c
include/linux/fs.h

index 77704fde98457423beae7ff00525a7383e37132b..37a4a7fa8094c5b3f0348c564f8bc2ce5bba0705 100644 (file)
@@ -80,7 +80,8 @@ prototypes::
        int (*getattr) (struct mnt_idmap *, const struct path *, struct kstat *, u32, unsigned int);
        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 (*update_time)(struct inode *inode, enum fs_update_time type,
+                           int flags);
        int (*atomic_open)(struct inode *, struct dentry *,
                                struct file *, unsigned open_flag,
                                umode_t create_mode);
index 670ba66b60e4964927164a57e68adc0edfc681ee..51aa9db64784f36fc9576fcf823b573045f7d8ef 100644 (file)
@@ -485,7 +485,8 @@ As of kernel 2.6.22, the following members are defined:
                int (*setattr) (struct mnt_idmap *, struct dentry *, struct iattr *);
                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 (*update_time)(struct inode *inode, enum fs_update_time type,
+                                   int flags);
                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);
index 0ef9bcb744dd620bf47caa024d97a1316ff7bc89..acf8613f5e368ece22e4afaaf1a4684663336de5 100644 (file)
@@ -133,7 +133,8 @@ static int bad_inode_fiemap(struct inode *inode,
        return -EIO;
 }
 
-static int bad_inode_update_time(struct inode *inode, int flags)
+static int bad_inode_update_time(struct inode *inode, enum fs_update_time type,
+                                unsigned int flags)
 {
        return -EIO;
 }
index c4bee47829eda067c1b6085deca27e1993ab599e..753c31a12a54ec11a80361df708aa19424fa7c41 100644 (file)
@@ -6345,16 +6345,19 @@ static int btrfs_dirty_inode(struct btrfs_inode *inode)
  * We need our own ->update_time so that we can return error on ENOSPC for
  * updating the inode in the case of file write and mmap writes.
  */
-static int btrfs_update_time(struct inode *inode, int flags)
+static int btrfs_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
-       bool dirty;
+       int dirty;
 
        if (btrfs_root_readonly(root))
                return -EROFS;
 
-       dirty = inode_update_timestamps(inode, flags);
-       return dirty ? btrfs_dirty_inode(BTRFS_I(inode)) : 0;
+       dirty = inode_update_time(inode, type, flags);
+       if (dirty <= 0)
+               return dirty;
+       return btrfs_dirty_inode(BTRFS_I(inode));
 }
 
 /*
index 767b566b1cabc18a3d4a9e844ab03900febc5325..0d269dba897bba304eaf569fbd63c8e3cf7d6bc4 100644 (file)
@@ -472,7 +472,8 @@ extern struct timespec64 fat_truncate_atime(const struct msdos_sb_info *sbi,
 #define FAT_UPDATE_CMTIME      (1u << 1)
 void fat_truncate_time(struct inode *inode, struct timespec64 *now,
                unsigned int flags);
-extern int fat_update_time(struct inode *inode, int flags);
+int fat_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags);
 extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
 
 int fat_cache_init(void);
index 78c620e9b3fd1a5ca4ce55a82bac217b8c6513b4..b154a516276452d91d11432c7c74b7f30541fbdf 100644 (file)
@@ -332,28 +332,14 @@ void fat_truncate_time(struct inode *inode, struct timespec64 *now,
 }
 EXPORT_SYMBOL_GPL(fat_truncate_time);
 
-int fat_update_time(struct inode *inode, int flags)
+int fat_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags)
 {
-       unsigned int fat_flags = 0;
-       int dirty_flags = 0;
-
-       if (inode->i_ino == MSDOS_ROOT_INO)
-               return 0;
-
-       if (flags & S_ATIME)
-               fat_flags |= FAT_UPDATE_ATIME;
-       if (flags & (S_CTIME | S_MTIME))
-               fat_flags |= FAT_UPDATE_CMTIME;
-
-       if (fat_flags) {
-               fat_truncate_time(inode, NULL, flags);
-               if (inode->i_sb->s_flags & SB_LAZYTIME)
-                       dirty_flags |= I_DIRTY_TIME;
-               else
-                       dirty_flags |= I_DIRTY_SYNC;
+       if (inode->i_ino != MSDOS_ROOT_INO) {
+               fat_truncate_time(inode, NULL, type == FS_UPD_ATIME ?
+                               FAT_UPDATE_ATIME : FAT_UPDATE_CMTIME);
+               __mark_inode_dirty(inode, inode_time_dirty_flag(inode));
        }
-
-       __mark_inode_dirty(inode, dirty_flags);
        return 0;
 }
 EXPORT_SYMBOL_GPL(fat_update_time);
index e08eb419347c36afa44b7f6a6ef9b92d001c1633..4ef39ff6889dece3455e6b56537eef7e87509539 100644 (file)
@@ -2242,7 +2242,8 @@ loff_t gfs2_seek_hole(struct file *file, loff_t offset)
        return vfs_setpos(file, ret, inode->i_sb->s_maxbytes);
 }
 
-static int gfs2_update_time(struct inode *inode, int flags)
+static int gfs2_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_glock *gl = ip->i_gl;
@@ -2257,7 +2258,7 @@ static int gfs2_update_time(struct inode *inode, int flags)
                if (error)
                        return error;
        }
-       return generic_update_time(inode, flags);
+       return generic_update_time(inode, type, flags);
 }
 
 static const struct inode_operations gfs2_file_iops = {
index 7eb28dd45a5aeae479dc4cddec2c7ee79680a743..a0dd11a05473fec1f445be9ee99c35b23e479bbe 100644 (file)
@@ -2081,78 +2081,84 @@ static bool relatime_need_update(struct vfsmount *mnt, struct inode *inode,
        return false;
 }
 
+static int inode_update_atime(struct inode *inode)
+{
+       struct timespec64 atime = inode_get_atime(inode);
+       struct timespec64 now = current_time(inode);
+
+       if (timespec64_equal(&now, &atime))
+               return 0;
+
+       inode_set_atime_to_ts(inode, now);
+       return inode_time_dirty_flag(inode);
+}
+
+static int inode_update_cmtime(struct inode *inode)
+{
+       struct timespec64 ctime = inode_get_ctime(inode);
+       struct timespec64 mtime = inode_get_mtime(inode);
+       struct timespec64 now = inode_set_ctime_current(inode);
+       unsigned int dirty = 0;
+       bool mtime_changed;
+
+       mtime_changed = !timespec64_equal(&now, &mtime);
+       if (mtime_changed || !timespec64_equal(&now, &ctime))
+               dirty = inode_time_dirty_flag(inode);
+       if (mtime_changed)
+               inode_set_mtime_to_ts(inode, now);
+
+       if (IS_I_VERSION(inode) && inode_maybe_inc_iversion(inode, !!dirty))
+               dirty |= I_DIRTY_SYNC;
+
+       return dirty;
+}
+
 /**
- * inode_update_timestamps - update the timestamps on the inode
+ * inode_update_time - update either atime or c/mtime and i_version on the inode
  * @inode: inode to be updated
- * @flags: S_* flags that needed to be updated
+ * @type: timestamp to be updated
+ * @flags: flags for the update
  *
- * 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
- * actual timestamps. It's up to the caller to ensure that the inode is marked
- * dirty appropriately.
+ * Update either atime or c/mtime and version in a inode if needed for a file
+ * access or modification.  It is up to the caller to mark the inode dirty
+ * appropriately.
  *
- * In the case where any of S_MTIME, S_CTIME, or S_VERSION need to be updated,
- * 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.
+ * Returns the positive I_DIRTY_* flags for __mark_inode_dirty() if the inode
+ * needs to be marked dirty, 0 if it did not, or a negative errno if an error
+ * happened.
  */
-int inode_update_timestamps(struct inode *inode, int flags)
+int inode_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags)
 {
-       int updated = 0;
-       struct timespec64 now;
-
-       if (flags & (S_MTIME|S_CTIME|S_VERSION)) {
-               struct timespec64 ctime = inode_get_ctime(inode);
-               struct timespec64 mtime = inode_get_mtime(inode);
-
-               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);
-                       updated |= S_MTIME;
-               }
-               if (IS_I_VERSION(inode) && inode_maybe_inc_iversion(inode, updated))
-                       updated |= S_VERSION;
-       } else {
-               now = current_time(inode);
-       }
-
-       if (flags & S_ATIME) {
-               struct timespec64 atime = inode_get_atime(inode);
-
-               if (!timespec64_equal(&now, &atime)) {
-                       inode_set_atime_to_ts(inode, now);
-                       updated |= S_ATIME;
-               }
+       switch (type) {
+       case FS_UPD_ATIME:
+               return inode_update_atime(inode);
+       case FS_UPD_CMTIME:
+               return inode_update_cmtime(inode);
+       default:
+               WARN_ON_ONCE(1);
+               return -EIO;
        }
-       return updated;
 }
-EXPORT_SYMBOL(inode_update_timestamps);
+EXPORT_SYMBOL(inode_update_time);
 
 /**
  * generic_update_time - update the timestamps on the inode
  * @inode: inode to be updated
- * @flags: S_* flags that needed to be updated
- *
- * The update_time function is called when an inode's timestamps need to be
- * updated for a read or write operation. In the case where any of S_MTIME, S_CTIME,
- * 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.
+ * @type: timestamp to be updated
+ * @flags: flags for the update
  *
  * Returns a negative error value on error, else 0.
  */
-int generic_update_time(struct inode *inode, int flags)
+int generic_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags)
 {
-       int updated = inode_update_timestamps(inode, flags);
-       int dirty_flags = 0;
+       int dirty;
 
-       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);
+       dirty = inode_update_time(inode, type, flags);
+       if (dirty <= 0)
+               return dirty;
+       __mark_inode_dirty(inode, dirty);
        return 0;
 }
 EXPORT_SYMBOL(generic_update_time);
@@ -2225,9 +2231,9 @@ void touch_atime(const struct path *path)
         * of the fs read only, e.g. subvolumes in Btrfs.
         */
        if (inode->i_op->update_time)
-               inode->i_op->update_time(inode, S_ATIME);
+               inode->i_op->update_time(inode, FS_UPD_ATIME, 0);
        else
-               generic_update_time(inode, S_ATIME);
+               generic_update_time(inode, FS_UPD_ATIME, 0);
        mnt_put_write_access(mnt);
 skip_update:
        sb_end_write(inode->i_sb);
@@ -2354,7 +2360,7 @@ static int file_update_time_flags(struct file *file, unsigned int flags)
 {
        struct inode *inode = file_inode(file);
        struct timespec64 now, ts;
-       int sync_mode = 0;
+       bool need_update = false;
        int ret = 0;
 
        /* First try to exhaust all avenues to not sync */
@@ -2367,14 +2373,14 @@ static int file_update_time_flags(struct file *file, unsigned int flags)
 
        ts = inode_get_mtime(inode);
        if (!timespec64_equal(&ts, &now))
-               sync_mode |= S_MTIME;
+               need_update = true;
        ts = inode_get_ctime(inode);
        if (!timespec64_equal(&ts, &now))
-               sync_mode |= S_CTIME;
+               need_update = true;
        if (IS_I_VERSION(inode) && inode_iversion_need_inc(inode))
-               sync_mode |= S_VERSION;
+               need_update = true;
 
-       if (!sync_mode)
+       if (!need_update)
                return 0;
 
        if (flags & IOCB_NOWAIT)
@@ -2383,9 +2389,9 @@ static int file_update_time_flags(struct file *file, unsigned int flags)
        if (mnt_get_write_access_file(file))
                return 0;
        if (inode->i_op->update_time)
-               ret = inode->i_op->update_time(inode, sync_mode);
+               ret = inode->i_op->update_time(inode, FS_UPD_CMTIME, 0);
        else
-               ret = generic_update_time(inode, sync_mode);
+               ret = generic_update_time(inode, FS_UPD_CMTIME, 0);
        mnt_put_write_access_file(file);
        return ret;
 }
index 3be8ba7b98c51ee728e34ade84980f6174a7b4a6..cd6d7c6e123758be4903d330dd3701846a2fa479 100644 (file)
@@ -649,15 +649,15 @@ static void nfs_set_timestamps_to_ts(struct inode *inode, struct iattr *attr)
                struct timespec64 ctime = inode_get_ctime(inode);
                struct timespec64 mtime = inode_get_mtime(inode);
                struct timespec64 now;
-               int updated = 0;
+               bool updated = false;
 
                now = inode_set_ctime_current(inode);
                if (!timespec64_equal(&now, &ctime))
-                       updated |= S_CTIME;
+                       updated = true;
 
                inode_set_mtime_to_ts(inode, attr->ia_mtime);
                if (!timespec64_equal(&now, &mtime))
-                       updated |= S_MTIME;
+                       updated = true;
 
                inode_maybe_inc_iversion(inode, updated);
                cache_flags |= NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME;
@@ -671,13 +671,13 @@ static void nfs_set_timestamps_to_ts(struct inode *inode, struct iattr *attr)
 
 static void nfs_update_atime(struct inode *inode)
 {
-       inode_update_timestamps(inode, S_ATIME);
+       inode_update_time(inode, FS_UPD_ATIME, 0);
        NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ATIME;
 }
 
 static void nfs_update_mtime(struct inode *inode)
 {
-       inode_update_timestamps(inode, S_MTIME | S_CTIME);
+       inode_update_time(inode, FS_UPD_CMTIME, 0);
        NFS_I(inode)->cache_validity &=
                ~(NFS_INO_INVALID_CTIME | NFS_INO_INVALID_MTIME);
 }
index d7275990ffa48a3224bd2bd93e03d88d6e1568c2..eab16afb5b8af2ddfe19583368771e94e94eb3a5 100644 (file)
@@ -872,22 +872,24 @@ int orangefs_permission(struct mnt_idmap *idmap,
        return generic_permission(&nop_mnt_idmap, inode, mask);
 }
 
-int orangefs_update_time(struct inode *inode, int flags)
+int orangefs_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags)
 {
-       struct iattr iattr;
+       struct iattr iattr = { };
+       int dirty;
 
-       gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_update_time: %pU\n",
-           get_khandle_from_ino(inode));
-
-       flags = inode_update_timestamps(inode, flags);
+       switch (type) {
+       case FS_UPD_ATIME:
+               iattr.ia_valid = ATTR_ATIME;
+               break;
+       case FS_UPD_CMTIME:
+               iattr.ia_valid = ATTR_CTIME | ATTR_MTIME;
+               break;
+       }
 
-       memset(&iattr, 0, sizeof iattr);
-        if (flags & S_ATIME)
-               iattr.ia_valid |= ATTR_ATIME;
-       if (flags & S_CTIME)
-               iattr.ia_valid |= ATTR_CTIME;
-       if (flags & S_MTIME)
-               iattr.ia_valid |= ATTR_MTIME;
+       dirty = inode_update_time(inode, type, flags);
+       if (dirty <= 0)
+               return dirty;
        return __orangefs_setattr(inode, &iattr);
 }
 
index 29c6da43e39663780b812abff698ec14c2c13f0f..1451fc2c1917c4bb055cf3a84cfc329b36348c45 100644 (file)
@@ -360,7 +360,8 @@ int orangefs_getattr(struct mnt_idmap *idmap, const struct path *path,
 int orangefs_permission(struct mnt_idmap *idmap,
                        struct inode *inode, int mask);
 
-int orangefs_update_time(struct inode *, int);
+int orangefs_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags);
 
 /*
  * defined in xattr.c
index bdbf86b56a9ba6a61b39cf7c54118ee2b885671c..c0ce3519e4af70fec6fd670ea289260114fba583 100644 (file)
@@ -555,9 +555,10 @@ int ovl_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
 }
 #endif
 
-int ovl_update_time(struct inode *inode, int flags)
+int ovl_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags)
 {
-       if (flags & S_ATIME) {
+       if (type == FS_UPD_ATIME) {
                struct ovl_fs *ofs = OVL_FS(inode->i_sb);
                struct path upperpath = {
                        .mnt = ovl_upper_mnt(ofs),
index f9ac9bdde830596c44a3e5b2a8792161c1bad04d..315882a360cea3da7914b8c33187f4cd2904f8ea 100644 (file)
@@ -820,7 +820,8 @@ static inline struct posix_acl *ovl_get_acl_path(const struct path *path,
 }
 #endif
 
-int ovl_update_time(struct inode *inode, int flags);
+int ovl_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags);
 bool ovl_is_private_xattr(struct super_block *sb, const char *name);
 
 struct ovl_inode_params {
index ec1bb9f43accbb08e3ea3d8a091b718af2242ffa..0cc44ad142de3cd02aba467884eae701d59fe26c 100644 (file)
@@ -1361,17 +1361,8 @@ static inline int mctime_update_needed(const struct inode *inode,
        return 0;
 }
 
-/**
- * ubifs_update_time - update time of inode.
- * @inode: inode to update
- * @flags: time updating control flag determines updating
- *         which time fields of @inode
- *
- * This function updates time of the inode.
- *
- * Returns: %0 for success or a negative error code otherwise.
- */
-int ubifs_update_time(struct inode *inode, int flags)
+int ubifs_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags)
 {
        struct ubifs_inode *ui = ubifs_inode(inode);
        struct ubifs_info *c = inode->i_sb->s_fs_info;
@@ -1379,15 +1370,19 @@ int ubifs_update_time(struct inode *inode, int flags)
                        .dirtied_ino_d = ALIGN(ui->data_len, 8) };
        int err, release;
 
+       /* ubifs sets S_NOCMTIME on all inodes, this should not happen. */
+       if (WARN_ON_ONCE(type != FS_UPD_ATIME))
+               return -EIO;
+
        if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
-               return generic_update_time(inode, flags);
+               return generic_update_time(inode, type, flags);
 
        err = ubifs_budget_space(c, &req);
        if (err)
                return err;
 
        mutex_lock(&ui->ui_mutex);
-       inode_update_timestamps(inode, flags);
+       inode_update_time(inode, type, flags);
        release = ui->dirty;
        __mark_inode_dirty(inode, I_DIRTY_SYNC);
        mutex_unlock(&ui->ui_mutex);
index 118392aa9f2a50859b58ff40415371e7c96e5726..b62a154c7bd4c8351bc7f2b6d3ac61c3c2a6c899 100644 (file)
@@ -2018,7 +2018,8 @@ int ubifs_calc_dark(const struct ubifs_info *c, int spc);
 int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
 int ubifs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
                  struct iattr *attr);
-int ubifs_update_time(struct inode *inode, int flags);
+int ubifs_update_time(struct inode *inode, enum fs_update_time type,
+                     unsigned int flags);
 
 /* dir.c */
 struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
index 9dedb54e3cb04f873ab7677ec49e0a05f8d72911..d9eae1af14a864ba463158612dab03b04804e030 100644 (file)
@@ -1184,21 +1184,21 @@ xfs_vn_setattr(
 STATIC int
 xfs_vn_update_time(
        struct inode            *inode,
-       int                     flags)
+       enum fs_update_time     type,
+       unsigned int            flags)
 {
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
        int                     log_flags = XFS_ILOG_TIMESTAMP;
        struct xfs_trans        *tp;
        int                     error;
-       struct timespec64       now;
 
        trace_xfs_update_time(ip);
 
        if (inode->i_sb->s_flags & SB_LAZYTIME) {
-               if (!((flags & S_VERSION) &&
-                     inode_maybe_inc_iversion(inode, false)))
-                       return generic_update_time(inode, flags);
+               if (type == FS_UPD_ATIME ||
+                   !inode_maybe_inc_iversion(inode, false))
+                       return generic_update_time(inode, type, flags);
 
                /* Capture the iversion update that just occurred */
                log_flags |= XFS_ILOG_CORE;
@@ -1209,16 +1209,10 @@ xfs_vn_update_time(
                return error;
 
        xfs_ilock(ip, XFS_ILOCK_EXCL);
-       if (flags & (S_CTIME|S_MTIME))
-               now = inode_set_ctime_current(inode);
+       if (type == FS_UPD_ATIME)
+               inode_set_atime_to_ts(inode, current_time(inode));
        else
-               now = current_time(inode);
-
-       if (flags & S_MTIME)
-               inode_set_mtime_to_ts(inode, now);
-       if (flags & S_ATIME)
-               inode_set_atime_to_ts(inode, now);
-
+               inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
        xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
        xfs_trans_log_inode(tp, ip, log_flags);
        return xfs_trans_commit(tp);
index 0983df0d0705e6cc303d699a3b75579266f50fe2..77985b4ed6ffc265f3717cb38f17027388971d76 100644 (file)
@@ -1717,6 +1717,13 @@ static inline struct timespec64 inode_set_ctime(struct inode *inode,
 
 struct timespec64 simple_inode_init_ts(struct inode *inode);
 
+static inline int inode_time_dirty_flag(struct inode *inode)
+{
+       if (inode->i_sb->s_flags & SB_LAZYTIME)
+               return I_DIRTY_TIME;
+       return I_DIRTY_SYNC;
+}
+
 /*
  * Snapshotting support.
  */
@@ -1983,6 +1990,11 @@ int wrap_directory_iterator(struct file *, struct dir_context *,
        static int shared_##x(struct file *file , struct dir_context *ctx) \
        { return wrap_directory_iterator(file, ctx, x); }
 
+enum fs_update_time {
+       FS_UPD_ATIME,
+       FS_UPD_CMTIME,
+};
+
 struct inode_operations {
        struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
        const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);
@@ -2010,7 +2022,8 @@ struct inode_operations {
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
                      u64 len);
-       int (*update_time)(struct inode *, int);
+       int (*update_time)(struct inode *inode, enum fs_update_time type,
+                          unsigned int flags);
        int (*atomic_open)(struct inode *, struct dentry *,
                           struct file *, unsigned open_flag,
                           umode_t create_mode);
@@ -2237,13 +2250,6 @@ static inline void inode_dec_link_count(struct inode *inode)
        mark_inode_dirty(inode);
 }
 
-enum file_time_flags {
-       S_ATIME = 1,
-       S_MTIME = 2,
-       S_CTIME = 4,
-       S_VERSION = 8,
-};
-
 extern bool atime_needs_update(const struct path *, struct inode *);
 extern void touch_atime(const struct path *);
 
@@ -2398,8 +2404,10 @@ 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 generic_update_time(struct inode *inode, int flags);
+int inode_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags);
+int generic_update_time(struct inode *inode, enum fs_update_time type,
+               unsigned int flags);
 
 /* /sys/fs */
 extern struct kobject *fs_kobj;