diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2022-04-18 21:50:19 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:32 -0400 |
commit | fd4cecd2583e784ff28b851de2ff5046201c57d7 (patch) | |
tree | d26722d2122b782773fb784514ba1701e751b235 /fs/bcachefs/btree_update_interior.c | |
parent | c0960603e2d42d097fea4afd6b720619441061bd (diff) |
bcachefs: Lock ordering fix
Can't take btree node locks while holding btree_reserve_cache_lock - it
would be nice if we could check this with lockdep.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Diffstat (limited to 'fs/bcachefs/btree_update_interior.c')
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 11 |
1 files changed, 5 insertions, 6 deletions
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 27ab1cde2217..9696eb2b91e7 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -383,16 +383,13 @@ static void bch2_btree_reserve_put(struct btree_update *as) struct bch_fs *c = as->c; struct prealloc_nodes *p; - mutex_lock(&c->btree_reserve_cache_lock); - for (p = as->prealloc_nodes; p < as->prealloc_nodes + ARRAY_SIZE(as->prealloc_nodes); p++) { while (p->nr) { struct btree *b = p->b[--p->nr]; - six_lock_intent(&b->c.lock, NULL, NULL); - six_lock_write(&b->c.lock, NULL, NULL); + mutex_lock(&c->btree_reserve_cache_lock); if (c->btree_reserve_cache_nr < ARRAY_SIZE(c->btree_reserve_cache)) { @@ -406,13 +403,15 @@ static void bch2_btree_reserve_put(struct btree_update *as) bch2_open_buckets_put(c, &b->ob); } + mutex_unlock(&c->btree_reserve_cache_lock); + + six_lock_intent(&b->c.lock, NULL, NULL); + six_lock_write(&b->c.lock, NULL, NULL); __btree_node_free(c, b); six_unlock_write(&b->c.lock); six_unlock_intent(&b->c.lock); } } - - mutex_unlock(&c->btree_reserve_cache_lock); } static int bch2_btree_reserve_get(struct btree_trans *trans, |