diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2020-06-12 22:29:48 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:41 -0400 |
commit | bd2bb273a09b93e2a7d79d30458ab5f6f0b3757a (patch) | |
tree | 8ed7c91566eaef19f442b0a763cf43e08fb72faa /fs/bcachefs/btree_locking.h | |
parent | 515282ac7d847d567dd3ba802edf34316368bb14 (diff) |
bcachefs: Don't deadlock when btree node reuse changes lock ordering
Btree node lock ordering is based on the logical key. However, 'struct
btree' may be reused for a different btree node under memory pressure.
This patch uses the new six lock callback to check if a btree node is no
longer the node we wanted to lock before blocking.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/btree_locking.h')
-rw-r--r-- | fs/bcachefs/btree_locking.h | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/fs/bcachefs/btree_locking.h b/fs/bcachefs/btree_locking.h index 4c80ab368e69..ffee6f2d7d4b 100644 --- a/fs/bcachefs/btree_locking.h +++ b/fs/bcachefs/btree_locking.h @@ -174,17 +174,21 @@ static inline bool btree_node_lock_increment(struct btree_trans *trans, } bool __bch2_btree_node_lock(struct btree *, struct bpos, unsigned, - struct btree_iter *, enum six_lock_type); - -static inline bool btree_node_lock(struct btree *b, struct bpos pos, - unsigned level, - struct btree_iter *iter, - enum six_lock_type type) + struct btree_iter *, enum six_lock_type, + six_lock_should_sleep_fn, void *); + +static inline bool btree_node_lock(struct btree *b, + struct bpos pos, unsigned level, + struct btree_iter *iter, + enum six_lock_type type, + six_lock_should_sleep_fn should_sleep_fn, void *p) { struct btree_trans *trans = iter->trans; bool ret; EBUG_ON(level >= BTREE_MAX_DEPTH); + EBUG_ON(!(trans->iters_linked & (1ULL << iter->idx))); + #ifdef CONFIG_BCACHEFS_DEBUG trans->locking = b; trans->locking_iter_idx = iter->idx; @@ -194,7 +198,8 @@ static inline bool btree_node_lock(struct btree *b, struct bpos pos, #endif ret = likely(six_trylock_type(&b->c.lock, type)) || btree_node_lock_increment(trans, b, level, type) || - __bch2_btree_node_lock(b, pos, level, iter, type); + __bch2_btree_node_lock(b, pos, level, iter, type, + should_sleep_fn, p); #ifdef CONFIG_BCACHEFS_DEBUG trans->locking = NULL; |