bcachefs: Fix deadlock on -ENOSPC w.r.t. partial open buckets

Open buckets on the partial list should not count as allocated when
we're trying to allocate from the partial list.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2024-10-26 20:21:41 -04:00
parent e0fafac5c4
commit 778ac324cc
2 changed files with 16 additions and 1 deletions

View File

@ -162,6 +162,10 @@ static void open_bucket_free_unused(struct bch_fs *c, struct open_bucket *ob)
ARRAY_SIZE(c->open_buckets_partial)); ARRAY_SIZE(c->open_buckets_partial));
spin_lock(&c->freelist_lock); spin_lock(&c->freelist_lock);
rcu_read_lock();
bch2_dev_rcu(c, ob->dev)->nr_partial_buckets++;
rcu_read_unlock();
ob->on_partial_list = true; ob->on_partial_list = true;
c->open_buckets_partial[c->open_buckets_partial_nr++] = c->open_buckets_partial[c->open_buckets_partial_nr++] =
ob - c->open_buckets; ob - c->open_buckets;
@ -972,7 +976,7 @@ static int bucket_alloc_set_partial(struct bch_fs *c,
u64 avail; u64 avail;
bch2_dev_usage_read_fast(ca, &usage); bch2_dev_usage_read_fast(ca, &usage);
avail = dev_buckets_free(ca, usage, watermark); avail = dev_buckets_free(ca, usage, watermark) + ca->nr_partial_buckets;
if (!avail) if (!avail)
continue; continue;
@ -981,6 +985,10 @@ static int bucket_alloc_set_partial(struct bch_fs *c,
i); i);
ob->on_partial_list = false; ob->on_partial_list = false;
rcu_read_lock();
bch2_dev_rcu(c, ob->dev)->nr_partial_buckets--;
rcu_read_unlock();
ret = add_new_bucket(c, ptrs, devs_may_alloc, ret = add_new_bucket(c, ptrs, devs_may_alloc,
nr_replicas, nr_effective, nr_replicas, nr_effective,
have_cache, ob); have_cache, ob);
@ -1191,7 +1199,13 @@ void bch2_open_buckets_stop(struct bch_fs *c, struct bch_dev *ca,
--c->open_buckets_partial_nr; --c->open_buckets_partial_nr;
swap(c->open_buckets_partial[i], swap(c->open_buckets_partial[i],
c->open_buckets_partial[c->open_buckets_partial_nr]); c->open_buckets_partial[c->open_buckets_partial_nr]);
ob->on_partial_list = false; ob->on_partial_list = false;
rcu_read_lock();
bch2_dev_rcu(c, ob->dev)->nr_partial_buckets--;
rcu_read_unlock();
spin_unlock(&c->freelist_lock); spin_unlock(&c->freelist_lock);
bch2_open_bucket_put(c, ob); bch2_open_bucket_put(c, ob);
spin_lock(&c->freelist_lock); spin_lock(&c->freelist_lock);

View File

@ -555,6 +555,7 @@ struct bch_dev {
u64 alloc_cursor[3]; u64 alloc_cursor[3];
unsigned nr_open_buckets; unsigned nr_open_buckets;
unsigned nr_partial_buckets;
unsigned nr_btree_reserve; unsigned nr_btree_reserve;
size_t inc_gen_needs_gc; size_t inc_gen_needs_gc;