bcachefs: Fix mtime/ctime updates
authorKent Overstreet <kent.overstreet@gmail.com>
Tue, 17 Jul 2018 18:12:42 +0000 (14:12 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:07 +0000 (17:08 -0400)
Also make inode flags consistent with how the rest of the inode is
updated

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/acl.c
fs/bcachefs/fs-io.c
fs/bcachefs/fs-ioctl.c
fs/bcachefs/fs-ioctl.h
fs/bcachefs/fs.c
fs/bcachefs/fs.h
fs/bcachefs/xattr.c

index eaf5c8e138fbd04f51b53c9a288466e09a529a67..7ee2022d9501981caac1296636cdcf20b57d3b2e 100644 (file)
@@ -286,10 +286,9 @@ static int inode_update_for_set_acl_fn(struct bch_inode_info *inode,
                                       void *p)
 {
        struct bch_fs *c = inode->v.i_sb->s_fs_info;
-       struct timespec64 now = current_time(&inode->v);
        umode_t mode = (unsigned long) p;
 
-       bi->bi_ctime    = timespec_to_bch2_time(c, now);
+       bi->bi_ctime    = bch2_current_time(c);
        bi->bi_mode     = mode;
        return 0;
 }
index 29d289b0dfa5f595adb50c47b53abedd41da4d34..33c379ecf5a170e38db80e011245351726c98574 100644 (file)
@@ -177,23 +177,40 @@ static int bch2_quota_reservation_add(struct bch_fs *c,
 
 /* i_size updates: */
 
+struct inode_new_size {
+       loff_t          new_size;
+       u64             now;
+       unsigned        fields;
+};
+
 static int inode_set_size(struct bch_inode_info *inode,
                          struct bch_inode_unpacked *bi,
                          void *p)
 {
-       loff_t *new_i_size = p;
+       struct inode_new_size *s = p;
 
-       lockdep_assert_held(&inode->ei_update_lock);
+       bi->bi_size = s->new_size;
+       if (s->fields & ATTR_ATIME)
+               bi->bi_atime = s->now;
+       if (s->fields & ATTR_MTIME)
+               bi->bi_mtime = s->now;
+       if (s->fields & ATTR_CTIME)
+               bi->bi_ctime = s->now;
 
-       bi->bi_size = *new_i_size;
        return 0;
 }
 
 static int __must_check bch2_write_inode_size(struct bch_fs *c,
                                              struct bch_inode_info *inode,
-                                             loff_t new_size)
+                                             loff_t new_size, unsigned fields)
 {
-       return __bch2_write_inode(c, inode, inode_set_size, &new_size, 0);
+       struct inode_new_size s = {
+               .new_size       = new_size,
+               .now            = bch2_current_time(c),
+               .fields         = fields,
+       };
+
+       return bch2_write_inode(c, inode, inode_set_size, &s, fields);
 }
 
 static void i_sectors_acct(struct bch_fs *c, struct bch_inode_info *inode,
@@ -241,6 +258,7 @@ static int i_sectors_dirty_finish_fn(struct bch_inode_info *inode,
                                     struct bch_inode_unpacked *bi,
                                     void *p)
 {
+       struct bch_fs *c = inode->v.i_sb->s_fs_info;
        struct i_sectors_hook *h = p;
 
        if (h->new_i_size != U64_MAX &&
@@ -249,6 +267,7 @@ static int i_sectors_dirty_finish_fn(struct bch_inode_info *inode,
                bi->bi_size = h->new_i_size;
        bi->bi_sectors  += h->sectors;
        bi->bi_flags    &= ~h->flags;
+       bi->bi_mtime    = bi->bi_ctime = bch2_current_time(c);
        return 0;
 }
 
@@ -259,7 +278,7 @@ static int i_sectors_dirty_finish(struct bch_fs *c, struct i_sectors_hook *h)
        mutex_lock(&h->inode->ei_update_lock);
        i_sectors_acct(c, h->inode, &h->quota_res, h->sectors);
 
-       ret = __bch2_write_inode(c, h->inode, i_sectors_dirty_finish_fn, h, 0);
+       ret = bch2_write_inode(c, h->inode, i_sectors_dirty_finish_fn, h, 0);
 
        if (!ret && h->new_i_size != U64_MAX)
                i_size_write(&h->inode->v, h->new_i_size);
@@ -289,7 +308,7 @@ static int i_sectors_dirty_start(struct bch_fs *c, struct i_sectors_hook *h)
        int ret;
 
        mutex_lock(&h->inode->ei_update_lock);
-       ret = __bch2_write_inode(c, h->inode, i_sectors_dirty_start_fn, h, 0);
+       ret = bch2_write_inode(c, h->inode, i_sectors_dirty_start_fn, h, 0);
        mutex_unlock(&h->inode->ei_update_lock);
 
        return ret;
@@ -2223,9 +2242,8 @@ static int bch2_extend(struct bch_inode_info *inode, struct iattr *iattr)
        setattr_copy(NULL, &inode->v, iattr);
 
        mutex_lock(&inode->ei_update_lock);
-       inode_set_ctime_current(&inode->v);
-       inode->v.i_mtime = inode_get_ctime(&inode->v);
-       ret = bch2_write_inode_size(c, inode, inode->v.i_size);
+       ret = bch2_write_inode_size(c, inode, inode->v.i_size,
+                                   ATTR_MTIME|ATTR_CTIME);
        mutex_unlock(&inode->ei_update_lock);
 
        return ret;
@@ -2284,8 +2302,6 @@ int bch2_truncate(struct bch_inode_info *inode, struct iattr *iattr)
 
        /* ATTR_MODE will never be set here, ns argument isn't needed: */
        setattr_copy(NULL, &inode->v, iattr);
-       inode_set_ctime_current(&inode->v);
-       inode->v.i_mtime = inode_get_ctime(&inode->v);
 out:
        ret = i_sectors_dirty_finish(c, &i_sectors_hook) ?: ret;
 err_put_pagecache:
@@ -2617,7 +2633,7 @@ btree_iter_err:
                i_size_write(&inode->v, end);
 
                mutex_lock(&inode->ei_update_lock);
-               ret = bch2_write_inode_size(c, inode, inode->v.i_size);
+               ret = bch2_write_inode_size(c, inode, inode->v.i_size, 0);
                mutex_unlock(&inode->ei_update_lock);
        }
 
@@ -2633,7 +2649,8 @@ btree_iter_err:
 
                if (inode->ei_inode.bi_size != inode->v.i_size) {
                        mutex_lock(&inode->ei_update_lock);
-                       ret = bch2_write_inode_size(c, inode, inode->v.i_size);
+                       ret = bch2_write_inode_size(c, inode,
+                                                   inode->v.i_size, 0);
                        mutex_unlock(&inode->ei_update_lock);
                }
        }
index 895ccc79e78279f80f418bb8958ddae854429b47..a89786f295cf1b841fbaa3d6a20e95a0d37fe202 100644 (file)
 
 #define FS_IOC_GOINGDOWN            _IOR('X', 125, __u32)
 
-/* Inode flags: */
-
-/* bcachefs inode flags -> vfs inode flags: */
-static const unsigned bch_flags_to_vfs[] = {
-       [__BCH_INODE_SYNC]      = S_SYNC,
-       [__BCH_INODE_IMMUTABLE] = S_IMMUTABLE,
-       [__BCH_INODE_APPEND]    = S_APPEND,
-       [__BCH_INODE_NOATIME]   = S_NOATIME,
-};
-
-/* bcachefs inode flags -> FS_IOC_GETFLAGS: */
-static const unsigned bch_flags_to_uflags[] = {
-       [__BCH_INODE_SYNC]      = FS_SYNC_FL,
-       [__BCH_INODE_IMMUTABLE] = FS_IMMUTABLE_FL,
-       [__BCH_INODE_APPEND]    = FS_APPEND_FL,
-       [__BCH_INODE_NODUMP]    = FS_NODUMP_FL,
-       [__BCH_INODE_NOATIME]   = FS_NOATIME_FL,
-};
-
-/* bcachefs inode flags -> FS_IOC_FSGETXATTR: */
-static const unsigned bch_flags_to_xflags[] = {
-       [__BCH_INODE_SYNC]      = FS_XFLAG_SYNC,
-       [__BCH_INODE_IMMUTABLE] = FS_XFLAG_IMMUTABLE,
-       [__BCH_INODE_APPEND]    = FS_XFLAG_APPEND,
-       [__BCH_INODE_NODUMP]    = FS_XFLAG_NODUMP,
-       [__BCH_INODE_NOATIME]   = FS_XFLAG_NOATIME,
-       //[__BCH_INODE_PROJINHERIT] = FS_XFLAG_PROJINHERIT;
-};
-
-#define set_flags(_map, _in, _out)                                     \
-do {                                                                   \
-       unsigned _i;                                                    \
-                                                                       \
-       for (_i = 0; _i < ARRAY_SIZE(_map); _i++)                       \
-               if ((_in) & (1 << _i))                                  \
-                       (_out) |= _map[_i];                             \
-               else                                                    \
-                       (_out) &= ~_map[_i];                            \
-} while (0)
-
-#define map_flags(_map, _in)                                           \
-({                                                                     \
-       unsigned _out = 0;                                              \
-                                                                       \
-       set_flags(_map, _in, _out);                                     \
-       _out;                                                           \
-})
-
-#define map_flags_rev(_map, _in)                                       \
-({                                                                     \
-       unsigned _i, _out = 0;                                          \
-                                                                       \
-       for (_i = 0; _i < ARRAY_SIZE(_map); _i++)                       \
-               if ((_in) & _map[_i]) {                                 \
-                       (_out) |= 1 << _i;                              \
-                       (_in) &= ~_map[_i];                             \
-               }                                                       \
-       (_out);                                                         \
-})
-
-#define map_defined(_map)                                              \
-({                                                                     \
-       unsigned _in = ~0;                                              \
-                                                                       \
-       map_flags_rev(_map, _in);                                       \
-})
-
-/* Set VFS inode flags from bcachefs inode: */
-void bch2_inode_flags_to_vfs(struct bch_inode_info *inode)
-{
-       set_flags(bch_flags_to_vfs, inode->ei_inode.bi_flags, inode->v.i_flags);
-}
-
 struct flags_set {
        unsigned                mask;
        unsigned                flags;
@@ -96,6 +23,7 @@ static int bch2_inode_flags_set(struct bch_inode_info *inode,
                                struct bch_inode_unpacked *bi,
                                void *p)
 {
+       struct bch_fs *c = inode->v.i_sb->s_fs_info;
        /*
         * We're relying on btree locking here for exclusion with other ioctl
         * calls - use the flags in the btree (@bi), not inode->i_flags:
@@ -108,14 +36,15 @@ static int bch2_inode_flags_set(struct bch_inode_info *inode,
            !capable(CAP_LINUX_IMMUTABLE))
                return -EPERM;
 
-       if (!S_ISREG(inode->v.i_mode) &&
-           !S_ISDIR(inode->v.i_mode) &&
+       if (!S_ISREG(bi->bi_mode) &&
+           !S_ISDIR(bi->bi_mode) &&
            (newflags & (BCH_INODE_NODUMP|BCH_INODE_NOATIME)) != newflags)
                return -EINVAL;
 
        bi->bi_flags &= ~s->mask;
        bi->bi_flags |= newflags;
-       inode_set_ctime_current(&inode->v);
+
+       bi->bi_ctime = timespec_to_bch2_time(c, current_time(&inode->v));
        return 0;
 }
 
@@ -153,10 +82,8 @@ static int bch2_ioc_setflags(struct bch_fs *c,
        }
 
        mutex_lock(&inode->ei_update_lock);
-       ret = __bch2_write_inode(c, inode, bch2_inode_flags_set, &s, 0);
-
-       if (!ret)
-               bch2_inode_flags_to_vfs(inode);
+       ret = bch2_write_inode(c, inode, bch2_inode_flags_set, &s,
+                              ATTR_CTIME);
        mutex_unlock(&inode->ei_update_lock);
 
 setflags_out:
@@ -242,9 +169,8 @@ static int bch2_ioc_fssetxattr(struct bch_fs *c,
        if (ret)
                goto err_unlock;
 
-       ret = __bch2_write_inode(c, inode, fssetxattr_inode_update_fn, &s, 0);
-       if (!ret)
-               bch2_inode_flags_to_vfs(inode);
+       ret = bch2_write_inode(c, inode, fssetxattr_inode_update_fn, &s,
+                              ATTR_CTIME);
 err_unlock:
        mutex_unlock(&inode->ei_update_lock);
 err:
index 2d117ef80ab2e9a7d598b14ea228305a93f770a6..f201980ef2c38e2dbbe5faf7138f0d2a2c479f16 100644 (file)
@@ -2,7 +2,78 @@
 #ifndef _BCACHEFS_FS_IOCTL_H
 #define _BCACHEFS_FS_IOCTL_H
 
-void bch2_inode_flags_to_vfs(struct bch_inode_info *);
+/* Inode flags: */
+
+/* bcachefs inode flags -> vfs inode flags: */
+static const unsigned bch_flags_to_vfs[] = {
+       [__BCH_INODE_SYNC]      = S_SYNC,
+       [__BCH_INODE_IMMUTABLE] = S_IMMUTABLE,
+       [__BCH_INODE_APPEND]    = S_APPEND,
+       [__BCH_INODE_NOATIME]   = S_NOATIME,
+};
+
+/* bcachefs inode flags -> FS_IOC_GETFLAGS: */
+static const unsigned bch_flags_to_uflags[] = {
+       [__BCH_INODE_SYNC]      = FS_SYNC_FL,
+       [__BCH_INODE_IMMUTABLE] = FS_IMMUTABLE_FL,
+       [__BCH_INODE_APPEND]    = FS_APPEND_FL,
+       [__BCH_INODE_NODUMP]    = FS_NODUMP_FL,
+       [__BCH_INODE_NOATIME]   = FS_NOATIME_FL,
+};
+
+/* bcachefs inode flags -> FS_IOC_FSGETXATTR: */
+static const unsigned bch_flags_to_xflags[] = {
+       [__BCH_INODE_SYNC]      = FS_XFLAG_SYNC,
+       [__BCH_INODE_IMMUTABLE] = FS_XFLAG_IMMUTABLE,
+       [__BCH_INODE_APPEND]    = FS_XFLAG_APPEND,
+       [__BCH_INODE_NODUMP]    = FS_XFLAG_NODUMP,
+       [__BCH_INODE_NOATIME]   = FS_XFLAG_NOATIME,
+       //[__BCH_INODE_PROJINHERIT] = FS_XFLAG_PROJINHERIT;
+};
+
+#define set_flags(_map, _in, _out)                                     \
+do {                                                                   \
+       unsigned _i;                                                    \
+                                                                       \
+       for (_i = 0; _i < ARRAY_SIZE(_map); _i++)                       \
+               if ((_in) & (1 << _i))                                  \
+                       (_out) |= _map[_i];                             \
+               else                                                    \
+                       (_out) &= ~_map[_i];                            \
+} while (0)
+
+#define map_flags(_map, _in)                                           \
+({                                                                     \
+       unsigned _out = 0;                                              \
+                                                                       \
+       set_flags(_map, _in, _out);                                     \
+       _out;                                                           \
+})
+
+#define map_flags_rev(_map, _in)                                       \
+({                                                                     \
+       unsigned _i, _out = 0;                                          \
+                                                                       \
+       for (_i = 0; _i < ARRAY_SIZE(_map); _i++)                       \
+               if ((_in) & _map[_i]) {                                 \
+                       (_out) |= 1 << _i;                              \
+                       (_in) &= ~_map[_i];                             \
+               }                                                       \
+       (_out);                                                         \
+})
+
+#define map_defined(_map)                                              \
+({                                                                     \
+       unsigned _in = ~0;                                              \
+                                                                       \
+       map_flags_rev(_map, _in);                                       \
+})
+
+/* Set VFS inode flags from bcachefs inode: */
+static inline void bch2_inode_flags_to_vfs(struct bch_inode_info *inode)
+{
+       set_flags(bch_flags_to_vfs, inode->ei_inode.bi_flags, inode->v.i_flags);
+}
 
 long bch2_fs_file_ioctl(struct file *, unsigned, unsigned long);
 long bch2_compat_fs_ioctl(struct file *, unsigned, unsigned long);
index 53107d02cbb65f43ff116e0144e47e48c528cd3e..2e2a5acae0ebdc5faf6a54b6a7c852619943ac05 100644 (file)
@@ -147,6 +147,8 @@ void bch2_inode_update_after_write(struct bch_fs *c,
 
        inode->ei_inode         = *bi;
        inode->ei_qid           = bch_qid(bi);
+
+       bch2_inode_flags_to_vfs(inode);
 }
 
 int __must_check bch2_write_inode_trans(struct btree_trans *trans,
@@ -187,10 +189,10 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
        return 0;
 }
 
-int __must_check __bch2_write_inode(struct bch_fs *c,
-                                   struct bch_inode_info *inode,
-                                   inode_set_fn set,
-                                   void *p, unsigned fields)
+int __must_check bch2_write_inode(struct bch_fs *c,
+                                 struct bch_inode_info *inode,
+                                 inode_set_fn set,
+                                 void *p, unsigned fields)
 {
        struct btree_trans trans;
        struct bch_inode_unpacked inode_u;
@@ -271,9 +273,8 @@ static int inode_update_for_create_fn(struct bch_inode_info *inode,
 {
        struct bch_fs *c = inode->v.i_sb->s_fs_info;
        struct bch_inode_unpacked *new_inode = p;
-       struct timespec64 now = current_time(&inode->v);
 
-       bi->bi_mtime = bi->bi_ctime = timespec_to_bch2_time(c, now);
+       bi->bi_mtime = bi->bi_ctime = bch2_current_time(c);
 
        if (S_ISDIR(new_inode->bi_mode))
                bi->bi_nlink++;
@@ -469,9 +470,8 @@ static int inode_update_for_link_fn(struct bch_inode_info *inode,
                                    void *p)
 {
        struct bch_fs *c = inode->v.i_sb->s_fs_info;
-       struct timespec64 now = current_time(&inode->v);
 
-       bi->bi_ctime = timespec_to_bch2_time(c, now);
+       bi->bi_ctime = bch2_current_time(c);
 
        if (bi->bi_flags & BCH_INODE_UNLINKED)
                bi->bi_flags &= ~BCH_INODE_UNLINKED;
@@ -543,9 +543,8 @@ static int inode_update_dir_for_unlink_fn(struct bch_inode_info *inode,
 {
        struct bch_fs *c = inode->v.i_sb->s_fs_info;
        struct bch_inode_info *unlink_inode = p;
-       struct timespec64 now = current_time(&inode->v);
 
-       bi->bi_mtime = bi->bi_ctime = timespec_to_bch2_time(c, now);
+       bi->bi_mtime = bi->bi_ctime = bch2_current_time(c);
 
        bi->bi_nlink -= S_ISDIR(unlink_inode->v.i_mode);
 
@@ -557,9 +556,8 @@ static int inode_update_for_unlink_fn(struct bch_inode_info *inode,
                                      void *p)
 {
        struct bch_fs *c = inode->v.i_sb->s_fs_info;
-       struct timespec64 now = current_time(&inode->v);
 
-       bi->bi_ctime = timespec_to_bch2_time(c, now);
+       bi->bi_ctime = bch2_current_time(c);
        if (bi->bi_nlink)
                bi->bi_nlink--;
        else
@@ -740,8 +738,6 @@ static int bch2_rename2(struct mnt_idmap *idmap,
 {
        struct bch_fs *c = src_vdir->i_sb->s_fs_info;
        struct rename_info i = {
-               .now            = timespec_to_bch2_time(c,
-                                               current_time(src_vdir)),
                .src_dir        = to_bch_ei(src_vdir),
                .dst_dir        = to_bch_ei(dst_vdir),
                .src_inode      = to_bch_ei(src_dentry->d_inode),
@@ -778,7 +774,7 @@ static int bch2_rename2(struct mnt_idmap *idmap,
        bch2_trans_init(&trans, c);
 retry:
        bch2_trans_begin(&trans);
-       i.now = timespec_to_bch2_time(c, current_time(src_vdir)),
+       i.now = bch2_current_time(c);
 
        ret   = bch2_dirent_rename(&trans,
                                   i.src_dir, &src_dentry->d_name,
@@ -1271,8 +1267,6 @@ static void bch2_vfs_inode_init(struct bch_fs *c,
        inode->ei_quota_reserved = 0;
        inode->ei_str_hash      = bch2_hash_info_init(c, bi);
 
-       bch2_inode_flags_to_vfs(inode);
-
        inode->v.i_mapping->a_ops = &bch_address_space_operations;
 
        switch (inode->v.i_mode & S_IFMT) {
@@ -1346,8 +1340,8 @@ static int bch2_vfs_write_inode(struct inode *vinode,
        int ret;
 
        mutex_lock(&inode->ei_update_lock);
-       ret = __bch2_write_inode(c, inode, inode_update_times_fn, NULL,
-                                ATTR_ATIME|ATTR_MTIME|ATTR_CTIME);
+       ret = bch2_write_inode(c, inode, inode_update_times_fn, NULL,
+                              ATTR_ATIME|ATTR_MTIME|ATTR_CTIME);
        mutex_unlock(&inode->ei_update_lock);
 
        if (c->opts.journal_flush_disabled)
index e8dd566285fce301e04067f3241647d7bb6923f9..4fdc11762cd7e41515e423288817e37b49a3094e 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef _BCACHEFS_FS_H
 #define _BCACHEFS_FS_H
 
+#include "inode.h"
 #include "opts.h"
 #include "str_hash.h"
 #include "quota_types.h"
@@ -81,10 +82,8 @@ int __must_check bch2_write_inode_trans(struct btree_trans *,
                                struct bch_inode_info *,
                                struct bch_inode_unpacked *,
                                inode_set_fn, void *);
-int __must_check __bch2_write_inode(struct bch_fs *, struct bch_inode_info *,
-                                   inode_set_fn, void *, unsigned);
-int __must_check bch2_write_inode(struct bch_fs *,
-                                 struct bch_inode_info *);
+int __must_check bch2_write_inode(struct bch_fs *, struct bch_inode_info *,
+                                 inode_set_fn, void *, unsigned);
 
 void bch2_vfs_exit(void);
 int bch2_vfs_init(void);
index f0440d12a031eb45fc65831c456a6bdd65e6f979..cb84bdabb6ed5f9604c26cc7dc97b73437b9266d 100644 (file)
@@ -436,7 +436,7 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
        }
 
        mutex_lock(&inode->ei_update_lock);
-       ret = __bch2_write_inode(c, inode, inode_opt_set_fn, &s, 0);
+       ret = bch2_write_inode(c, inode, inode_opt_set_fn, &s, 0);
        mutex_unlock(&inode->ei_update_lock);
 
        if (value &&