summaryrefslogtreecommitdiff
path: root/fs/bcachefs/btree_update_interior.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/btree_update_interior.c')
-rw-r--r--fs/bcachefs/btree_update_interior.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index 76897cf15946..a9877a47bfc6 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -95,7 +95,7 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
if (!b->c.level)
goto out;
- while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) {
+ while ((k = bch2_btree_and_journal_iter_peek(c, &iter)).k) {
if (k.k->type != KEY_TYPE_btree_ptr_v2)
goto out;
@@ -336,6 +336,20 @@ static struct btree *__bch2_btree_node_alloc(struct btree_trans *trans,
BUG_ON(b->ob.nr);
mutex_lock(&c->btree_reserve_cache_lock);
+ if (unlikely(c->open_buckets_nr_free <= bch2_open_buckets_reserved(watermark))) {
+ guard(spinlock)(&c->freelist_lock);
+ if (c->open_buckets_nr_free <= bch2_open_buckets_reserved(watermark)) {
+ if (cl)
+ closure_wait(&c->open_buckets_wait, cl);
+
+ ret = cl
+ ? bch_err_throw(c, bucket_alloc_blocked)
+ : bch_err_throw(c, open_buckets_empty);
+ mutex_unlock(&c->btree_reserve_cache_lock);
+ goto err;
+ }
+ }
+
if (c->btree_reserve_cache_nr > nr_reserve) {
for (struct btree_alloc *a = c->btree_reserve_cache;
a < c->btree_reserve_cache + c->btree_reserve_cache_nr;) {