summaryrefslogtreecommitdiff
path: root/fs/bcachefs/btree_key_cache.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2022-09-03 05:59:39 +0300
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-23 00:09:40 +0300
commit38474c264252475196a5e3c555b2625a5bc36a00 (patch)
tree68d8bbf34a8bf3a3548b0e2c09bbd6d38bbeedee /fs/bcachefs/btree_key_cache.c
parent3d21d48e898a2eadc9055c44e0fd51e6087c9e9f (diff)
downloadlinux-38474c264252475196a5e3c555b2625a5bc36a00.tar.xz
bcachefs: Avoid using btree_node_lock_nopath()
With the upcoming cycle detector, we have to be careful about using btree_node_lock_nopath - in particular, using it to take write locks can cause deadlocks. All held locks need to be tracked in a btree_path, so that the cycle detector knows about them - unless we know that we cannot cause deadlocks for other reasons: e.g. we are only taking read locks, or we're in very early fsck (topology repair). Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/btree_key_cache.c')
-rw-r--r--fs/bcachefs/btree_key_cache.c17
1 files changed, 6 insertions, 11 deletions
diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c
index 89e540c5a244..0f54db0c1b8a 100644
--- a/fs/bcachefs/btree_key_cache.c
+++ b/fs/bcachefs/btree_key_cache.c
@@ -568,26 +568,21 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans,
atomic_long_dec(&c->btree_key_cache.nr_dirty);
}
} else {
+ struct btree_path *path2;
evict:
- BUG_ON(!btree_node_intent_locked(c_iter.path, 0));
+ trans_for_each_path(trans, path2)
+ if (path2 != c_iter.path)
+ __bch2_btree_path_unlock(trans, path2);
- /*
- * XXX: holding a lock that is not marked in btree_trans, not
- * ideal:
- */
- six_lock_increment(&ck->c.lock, SIX_LOCK_intent);
- bch2_trans_unlock(trans);
-
- /* Will not fail because we are holding no other locks: */
- btree_node_lock_nopath_nofail(trans, &ck->c, SIX_LOCK_write);
+ bch2_btree_node_lock_write_nofail(trans, c_iter.path, &ck->c);
if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) {
clear_bit(BKEY_CACHED_DIRTY, &ck->flags);
atomic_long_dec(&c->btree_key_cache.nr_dirty);
}
+ mark_btree_node_locked_noreset(c_iter.path, 0, BTREE_NODE_UNLOCKED);
bkey_cached_evict(&c->btree_key_cache, ck);
-
bkey_cached_free_fast(&c->btree_key_cache, ck);
}
out: