diff options
Diffstat (limited to 'fs/bcachefs/alloc_foreground.c')
-rw-r--r-- | fs/bcachefs/alloc_foreground.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c index 4dbab45be5ed..112d6e1eac14 100644 --- a/fs/bcachefs/alloc_foreground.c +++ b/fs/bcachefs/alloc_foreground.c @@ -300,11 +300,11 @@ static struct open_bucket *try_alloc_bucket(struct btree_trans *trans, struct bc bch2_alloc_to_v4(k, &a); - if (bch2_fs_inconsistent_on(bucket_state(a) != BUCKET_free, c, + if (bch2_fs_inconsistent_on(a.data_type != BCH_DATA_free, c, "non free bucket in freespace btree (state %s)\n" " %s\n" " at %llu (genbits %u)", - bch2_bucket_states[bucket_state(a)], + bch2_data_types[a.data_type], (bch2_bkey_val_to_text(&buf, c, k), buf.buf), free_entry, genbits)) { ob = ERR_PTR(-EIO); @@ -402,7 +402,7 @@ bch2_bucket_alloc_trans_early(struct btree_trans *trans, bch2_alloc_to_v4(k, &a); - if (bucket_state(a) != BUCKET_free) + if (a.data_type != BCH_DATA_free) continue; (*buckets_seen)++; @@ -489,29 +489,33 @@ struct open_bucket *bch2_bucket_alloc(struct bch_fs *c, struct bch_dev *ca, struct closure *cl) { struct open_bucket *ob = NULL; - u64 avail = dev_buckets_available(ca, reserve); + struct bch_dev_usage usage; + u64 avail; u64 cur_bucket = 0; u64 buckets_seen = 0; u64 skipped_open = 0; u64 skipped_need_journal_commit = 0; u64 skipped_nouse = 0; + bool waiting = false; int ret; - - if (may_alloc_partial) { - ob = try_alloc_partial_bucket(c, ca, reserve); - if (ob) - return ob; - } again: + usage = bch2_dev_usage_read(ca); + avail = __dev_buckets_available(ca, usage,reserve); + + if (usage.d[BCH_DATA_need_discard].buckets > avail) + bch2_do_discards(c); + + if (usage.d[BCH_DATA_need_gc_gens].buckets > avail) + bch2_do_gc_gens(c); + + if (should_invalidate_buckets(ca, usage)) + bch2_do_invalidates(c); + if (!avail) { - if (cl) { + if (cl && !waiting) { closure_wait(&c->freelist_wait, cl); - /* recheck after putting ourself on waitlist */ - avail = dev_buckets_available(ca, reserve); - if (avail) { - closure_wake_up(&c->freelist_wait); - goto again; - } + waiting = true; + goto again; } if (!c->blocked_allocate) @@ -521,6 +525,15 @@ again: goto err; } + if (waiting) + closure_wake_up(&c->freelist_wait); + + if (may_alloc_partial) { + ob = try_alloc_partial_bucket(c, ca, reserve); + if (ob) + return ob; + } + ret = bch2_trans_do(c, NULL, NULL, 0, PTR_ERR_OR_ZERO(ob = bch2_bucket_alloc_trans(&trans, ca, reserve, &cur_bucket, |