bcachefs: Fix spurious transaction restarts
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 28 Oct 2020 18:18:18 +0000 (14:18 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:45 +0000 (17:08 -0400)
The check for whether locking a btree node would deadlock was wrong - we
have to check that interior nodes are locked before descendents, but
this check was wrong when consider cached vs. non cached iterators.

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

index a76e13000d11a999a5c58454a64566b9a11d9bea..d310b2389e384c131bbaa40889414a95ef3883a2 100644 (file)
@@ -244,6 +244,7 @@ bool __bch2_btree_node_lock(struct btree *b, struct bpos pos,
                 * we're about to lock, it must have the ancestors locked too:
                 */
                if (linked->btree_id == iter->btree_id &&
+                   btree_iter_is_cached(linked) == btree_iter_is_cached(iter) &&
                    level > __fls(linked->nodes_locked)) {
                        if (!(trans->nounlock)) {
                                linked->locks_want =
index f02518f9d9ec49f93f21c69c290df257c65481c8..d4f0db1fe457bacbfeca0fc81650b35588de3f11 100644 (file)
@@ -283,6 +283,11 @@ btree_iter_type(const struct btree_iter *iter)
        return iter->flags & BTREE_ITER_TYPE;
 }
 
+static inline bool btree_iter_is_cached(const struct btree_iter *iter)
+{
+       return btree_iter_type(iter) == BTREE_ITER_CACHED;
+}
+
 static inline struct btree_iter_level *iter_l(struct btree_iter *iter)
 {
        return iter->l + iter->level;