bcachefs: bch2_assert_pos_locked()
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 6 Nov 2021 04:03:40 +0000 (00:03 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:16 +0000 (17:09 -0400)
This adds a new assertion to be used by bch2_inode_update_after_write(),
which updates the VFS inode based on the update to the btree inode we
just did - we require that the btree inode still be locked when we do
that update.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/acl.c
fs/bcachefs/btree_iter.c
fs/bcachefs/btree_iter.h
fs/bcachefs/fs.c
fs/bcachefs/fs.h
fs/bcachefs/inode.c
fs/bcachefs/inode.h

index 51a0b48a5313800310bb9a6c86b768c4d9644c58..00cd40a8d7fac937b19a24426661b7c289f87479 100644 (file)
@@ -339,7 +339,7 @@ btree_err:
        if (unlikely(ret))
                goto err;
 
-       bch2_inode_update_after_write(c, inode, &inode_u,
+       bch2_inode_update_after_write(&trans, inode, &inode_u,
                                      ATTR_CTIME|ATTR_MODE);
 
        set_cached_acl(&inode->v, type, acl);
index 94ba43626cde8ca3bd764bbfde5656b586905585..1ad81cad36f1895503bf1191d05584d84c493c13 100644 (file)
@@ -46,7 +46,7 @@ static inline int __btree_path_cmp(const struct btree_path *l,
                                   unsigned             r_level)
 {
        return   cmp_int(l->btree_id,   r_btree_id) ?:
-                cmp_int(l->cached,     r_cached) ?:
+                cmp_int((int) l->cached,       (int) r_cached) ?:
                 bpos_cmp(l->pos,       r_pos) ?:
                -cmp_int(l->level,      r_level);
 }
@@ -762,6 +762,43 @@ out:
        return ret;
 }
 
+void bch2_assert_pos_locked(struct btree_trans *trans, enum btree_id id,
+                           struct bpos pos, bool key_cache)
+{
+       struct btree_path *path;
+       unsigned idx;
+       char buf[100];
+
+       trans_for_each_path_inorder(trans, path, idx) {
+               int cmp = cmp_int(path->btree_id, id) ?:
+                       cmp_int(path->cached, key_cache);
+
+               if (cmp > 0)
+                       break;
+               if (cmp < 0)
+                       continue;
+
+               if (!(path->nodes_locked & 1) ||
+                   !path->should_be_locked)
+                       continue;
+
+               if (!key_cache) {
+                       if (bkey_cmp(pos, path->l[0].b->data->min_key) >= 0 &&
+                           bkey_cmp(pos, path->l[0].b->key.k.p) <= 0)
+                               return;
+               } else {
+                       if (!bkey_cmp(pos, path->pos))
+                               return;
+               }
+       }
+
+       bch2_dump_trans_paths_updates(trans);
+       panic("not locked: %s %s%s\n",
+             bch2_btree_ids[id],
+             (bch2_bpos_to_text(&PBUF(buf), pos), buf),
+             key_cache ? " cached" : "");
+}
+
 #else
 
 static inline void bch2_btree_path_verify_level(struct btree_trans *trans,
@@ -1720,11 +1757,13 @@ void bch2_dump_trans_paths_updates(struct btree_trans *trans)
        btree_trans_sort_paths(trans);
 
        trans_for_each_path_inorder(trans, path, idx)
-               printk(KERN_ERR "path: idx %u ref %u:%u%s btree %s pos %s %pS\n",
+               printk(KERN_ERR "path: idx %u ref %u:%u%s%s btree %s pos %s locks %u %pS\n",
                       path->idx, path->ref, path->intent_ref,
-                      path->preserve ? " preserve" : "",
+                      path->should_be_locked ? " S" : "",
+                      path->preserve ? " P" : "",
                       bch2_btree_ids[path->btree_id],
                       (bch2_bpos_to_text(&PBUF(buf1), path->pos), buf1),
+                      path->nodes_locked,
 #ifdef CONFIG_BCACHEFS_DEBUG
                       (void *) path->ip_allocated
 #else
index c71e42a782d61fc13691519806980167dff7a227..72b9605cf3e7d7cc4ad4b9c6782d29415971e00e 100644 (file)
@@ -166,9 +166,13 @@ inline struct bkey_s_c bch2_btree_path_peek_slot(struct btree_path *, struct bke
 #ifdef CONFIG_BCACHEFS_DEBUG
 void bch2_trans_verify_paths(struct btree_trans *);
 void bch2_trans_verify_locks(struct btree_trans *);
+void bch2_assert_pos_locked(struct btree_trans *, enum btree_id,
+                           struct bpos, bool);
 #else
 static inline void bch2_trans_verify_paths(struct btree_trans *trans) {}
 static inline void bch2_trans_verify_locks(struct btree_trans *trans) {}
+static inline void bch2_assert_pos_locked(struct btree_trans *trans, enum btree_id id,
+                                         struct bpos pos, bool key_cache) {}
 #endif
 
 void bch2_btree_path_fix_key_modified(struct btree_trans *trans,
index 92919b16f2f51ce6b664b0d83f479b32aee37bc8..5596081b93c1ad8c2f39db0a09fce9454849a74c 100644 (file)
@@ -37,7 +37,7 @@
 
 static struct kmem_cache *bch2_inode_cache;
 
-static void bch2_vfs_inode_init(struct bch_fs *, subvol_inum,
+static void bch2_vfs_inode_init(struct btree_trans *, subvol_inum,
                                struct bch_inode_info *,
                                struct bch_inode_unpacked *);
 
@@ -93,11 +93,19 @@ void bch2_pagecache_block_get(struct pagecache_lock *lock)
        __pagecache_lock_get(lock, -1);
 }
 
-void bch2_inode_update_after_write(struct bch_fs *c,
+void bch2_inode_update_after_write(struct btree_trans *trans,
                                   struct bch_inode_info *inode,
                                   struct bch_inode_unpacked *bi,
                                   unsigned fields)
 {
+       struct bch_fs *c = trans->c;
+
+       BUG_ON(bi->bi_inum != inode->v.i_ino);
+
+       bch2_assert_pos_locked(trans, BTREE_ID_inodes,
+                              POS(0, bi->bi_inum),
+                              0 && c->opts.inodes_use_key_cache);
+
        set_nlink(&inode->v, bch2_inode_nlink_get(bi));
        i_uid_write(&inode->v, bi->bi_uid);
        i_gid_write(&inode->v, bi->bi_gid);
@@ -126,6 +134,7 @@ int __must_check bch2_write_inode(struct bch_fs *c,
        int ret;
 
        bch2_trans_init(&trans, c, 0, 512);
+       trans.ip = _RET_IP_;
 retry:
        bch2_trans_begin(&trans);
 
@@ -140,7 +149,7 @@ retry:
         * this is important for inode updates via bchfs_write_index_update
         */
        if (!ret)
-               bch2_inode_update_after_write(c, inode, &inode_u, fields);
+               bch2_inode_update_after_write(&trans, inode, &inode_u, fields);
 
        bch2_trans_iter_exit(&trans, &iter);
 
@@ -215,6 +224,7 @@ struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum)
 {
        struct bch_inode_unpacked inode_u;
        struct bch_inode_info *inode;
+       struct btree_trans trans;
        int ret;
 
        inode = to_bch_ei(iget5_locked(c->vfs_sb,
@@ -227,14 +237,19 @@ struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum)
        if (!(inode->v.i_state & I_NEW))
                return &inode->v;
 
-       ret = bch2_inode_find_by_inum(c, inum, &inode_u);
+       bch2_trans_init(&trans, c, 8, 0);
+       ret = lockrestart_do(&trans,
+               bch2_inode_find_by_inum_trans(&trans, inum, &inode_u));
+
+       if (!ret)
+               bch2_vfs_inode_init(&trans, inum, inode, &inode_u);
+       bch2_trans_exit(&trans);
+
        if (ret) {
                iget_failed(&inode->v);
                return ERR_PTR(ret);
        }
 
-       bch2_vfs_inode_init(c, inum, inode, &inode_u);
-
        unlock_new_inode(&inode->v);
 
        return &inode->v;
@@ -306,7 +321,7 @@ err_before_quota:
        }
 
        if (!(flags & BCH_CREATE_TMPFILE)) {
-               bch2_inode_update_after_write(c, dir, &dir_u,
+               bch2_inode_update_after_write(&trans, dir, &dir_u,
                                              ATTR_MTIME|ATTR_CTIME);
                mutex_unlock(&dir->ei_update_lock);
        }
@@ -314,7 +329,8 @@ err_before_quota:
        inum.subvol = inode_u.bi_subvol ?: dir->ei_subvol;
        inum.inum = inode_u.bi_inum;
 
-       bch2_vfs_inode_init(c, inum, inode, &inode_u);
+       bch2_iget5_set(&inode->v, &inum);
+       bch2_vfs_inode_init(&trans, inum, inode, &inode_u);
 
        set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl);
        set_cached_acl(&inode->v, ACL_TYPE_DEFAULT, default_acl);
@@ -429,11 +445,9 @@ static int __bch2_link(struct bch_fs *c,
                                        &dentry->d_name));
 
        if (likely(!ret)) {
-               BUG_ON(inode_u.bi_inum != inode->v.i_ino);
-
-               bch2_inode_update_after_write(c, dir, &dir_u,
+               bch2_inode_update_after_write(&trans, dir, &dir_u,
                                              ATTR_MTIME|ATTR_CTIME);
-               bch2_inode_update_after_write(c, inode, &inode_u, ATTR_CTIME);
+               bch2_inode_update_after_write(&trans, inode, &inode_u, ATTR_CTIME);
        }
 
        bch2_trans_exit(&trans);
@@ -481,11 +495,9 @@ int __bch2_unlink(struct inode *vdir, struct dentry *dentry,
                                          deleting_snapshot));
 
        if (likely(!ret)) {
-               BUG_ON(inode_u.bi_inum != inode->v.i_ino);
-
-               bch2_inode_update_after_write(c, dir, &dir_u,
+               bch2_inode_update_after_write(&trans, dir, &dir_u,
                                              ATTR_MTIME|ATTR_CTIME);
-               bch2_inode_update_after_write(c, inode, &inode_u,
+               bch2_inode_update_after_write(&trans, inode, &inode_u,
                                              ATTR_MTIME);
        }
 
@@ -613,18 +625,18 @@ static int bch2_rename2(struct mnt_idmap *idmap,
        BUG_ON(dst_inode &&
               dst_inode->v.i_ino != dst_inode_u.bi_inum);
 
-       bch2_inode_update_after_write(c, src_dir, &src_dir_u,
+       bch2_inode_update_after_write(&trans, src_dir, &src_dir_u,
                                      ATTR_MTIME|ATTR_CTIME);
 
        if (src_dir != dst_dir)
-               bch2_inode_update_after_write(c, dst_dir, &dst_dir_u,
+               bch2_inode_update_after_write(&trans, dst_dir, &dst_dir_u,
                                              ATTR_MTIME|ATTR_CTIME);
 
-       bch2_inode_update_after_write(c, src_inode, &src_inode_u,
+       bch2_inode_update_after_write(&trans, src_inode, &src_inode_u,
                                      ATTR_CTIME);
 
        if (dst_inode)
-               bch2_inode_update_after_write(c, dst_inode, &dst_inode_u,
+               bch2_inode_update_after_write(&trans, dst_inode, &dst_inode_u,
                                              ATTR_CTIME);
 err:
        bch2_trans_exit(&trans);
@@ -742,7 +754,7 @@ btree_err:
        if (unlikely(ret))
                goto err_trans;
 
-       bch2_inode_update_after_write(c, inode, &inode_u, attr->ia_valid);
+       bch2_inode_update_after_write(&trans, inode, &inode_u, attr->ia_valid);
 
        if (acl)
                set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl);
@@ -1154,11 +1166,11 @@ static const struct export_operations bch_export_ops = {
        //.get_parent   = bch2_get_parent,
 };
 
-static void bch2_vfs_inode_init(struct bch_fs *c, subvol_inum inum,
+static void bch2_vfs_inode_init(struct btree_trans *trans, subvol_inum inum,
                                struct bch_inode_info *inode,
                                struct bch_inode_unpacked *bi)
 {
-       bch2_inode_update_after_write(c, inode, bi, ~0);
+       bch2_inode_update_after_write(trans, inode, bi, ~0);
 
        inode->v.i_blocks       = bi->bi_sectors;
        inode->v.i_ino          = bi->bi_inum;
index 1c8936df9fbb9cf1dc962bad94d5d65ef18c0f19..530238780a880e249e8770099ba0d08b911a973d 100644 (file)
@@ -172,7 +172,7 @@ struct inode *bch2_vfs_inode_get(struct bch_fs *, subvol_inum);
 typedef int (*inode_set_fn)(struct bch_inode_info *,
                            struct bch_inode_unpacked *, void *);
 
-void bch2_inode_update_after_write(struct bch_fs *,
+void bch2_inode_update_after_write(struct btree_trans *,
                                   struct bch_inode_info *,
                                   struct bch_inode_unpacked *,
                                   unsigned);
index 728545141a3927028db5adc41a53f969b959c294..a24bbc5228c1bf4926947fefb3e4daaac24c2d19 100644 (file)
@@ -722,9 +722,9 @@ err:
        return ret;
 }
 
-static int bch2_inode_find_by_inum_trans(struct btree_trans *trans,
-                                        subvol_inum inum,
-                                        struct bch_inode_unpacked *inode)
+int bch2_inode_find_by_inum_trans(struct btree_trans *trans,
+                                 subvol_inum inum,
+                                 struct bch_inode_unpacked *inode)
 {
        struct btree_iter iter;
        int ret;
index d433d48de4e0d69d45f58c364b9c8cbcde7a976f..723186d8afb6d661535e7e59dfb80170e9eb1105 100644 (file)
@@ -89,6 +89,8 @@ int bch2_inode_create(struct btree_trans *, struct btree_iter *,
 
 int bch2_inode_rm(struct bch_fs *, subvol_inum, bool);
 
+int bch2_inode_find_by_inum_trans(struct btree_trans *, subvol_inum,
+                                 struct bch_inode_unpacked *);
 int bch2_inode_find_by_inum(struct bch_fs *, subvol_inum,
                            struct bch_inode_unpacked *);