diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2020-10-28 14:18:18 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2022-03-12 20:11:56 -0500 |
commit | b75e2c3a1d99aeeec593568c1cb3d3d594be45f8 (patch) | |
tree | bcdcdb1cea1e3cfd6e6cae6ae12889260a21478f | |
parent | 0182782d4e42e6e5d2beb5e570ff2d960656a49e (diff) |
bcachefs: Fix spurious transaction restarts
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>
-rw-r--r-- | fs/bcachefs/btree_iter.c | 1 | ||||
-rw-r--r-- | fs/bcachefs/btree_types.h | 5 |
2 files changed, 6 insertions, 0 deletions
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index ebed0103b03c..357b8514e65c 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -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 = diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index cc01baeec138..844d853eacc3 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -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; |