bcachefs: Fix deadlock on -ENOSPC w.r.t. partial open buckets
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 27 Oct 2024 00:21:41 +0000 (20:21 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Tue, 29 Oct 2024 10:34:10 +0000 (06:34 -0400)
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>
fs/bcachefs/alloc_foreground.c
fs/bcachefs/bcachefs.h

index 32f2a24..372178c 100644 (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));
 
        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;
        c->open_buckets_partial[c->open_buckets_partial_nr++] =
                ob - c->open_buckets;
@@ -972,7 +976,7 @@ static int bucket_alloc_set_partial(struct bch_fs *c,
                        u64 avail;
 
                        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)
                                continue;
 
@@ -981,6 +985,10 @@ static int bucket_alloc_set_partial(struct bch_fs *c,
                                          i);
                        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,
                                             nr_replicas, nr_effective,
                                             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;
                        swap(c->open_buckets_partial[i],
                             c->open_buckets_partial[c->open_buckets_partial_nr]);
+
                        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);
                        bch2_open_bucket_put(c, ob);
                        spin_lock(&c->freelist_lock);
index f4151ee..e94a83b 100644 (file)
@@ -555,6 +555,7 @@ struct bch_dev {
        u64                     alloc_cursor[3];
 
        unsigned                nr_open_buckets;
+       unsigned                nr_partial_buckets;
        unsigned                nr_btree_reserve;
 
        size_t                  inc_gen_needs_gc;