summaryrefslogtreecommitdiff
path: root/fs/bcachefs/alloc_foreground.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/alloc_foreground.c')
-rw-r--r--fs/bcachefs/alloc_foreground.c47
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,