diff options
Diffstat (limited to 'fs/bcachefs/ec.c')
-rw-r--r-- | fs/bcachefs/ec.c | 38 |
1 files changed, 14 insertions, 24 deletions
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index 71956ee86a9c..687c3ba98095 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -1720,7 +1720,8 @@ err: static int new_stripe_alloc_buckets(struct btree_trans *trans, struct alloc_request *req, - struct ec_stripe_head *h, struct ec_stripe_new *s) + struct ec_stripe_head *h, struct ec_stripe_new *s, + struct closure *cl) { struct bch_fs *c = trans->c; struct open_bucket *ob; @@ -1770,7 +1771,7 @@ static int new_stripe_alloc_buckets(struct btree_trans *trans, req->nr_effective = nr_have_parity; req->data_type = BCH_DATA_parity; - ret = bch2_bucket_alloc_set_trans(trans, req, &h->parity_stripe); + ret = bch2_bucket_alloc_set_trans(trans, req, &h->parity_stripe, cl); open_bucket_for_each(c, &req->ptrs, ob, i) { j = find_next_zero_bit(s->blocks_gotten, @@ -1793,7 +1794,7 @@ static int new_stripe_alloc_buckets(struct btree_trans *trans, req->nr_effective = nr_have_data; req->data_type = BCH_DATA_user; - ret = bch2_bucket_alloc_set_trans(trans, req, &h->block_stripe); + ret = bch2_bucket_alloc_set_trans(trans, req, &h->block_stripe, cl); open_bucket_for_each(c, &req->ptrs, ob, i) { j = find_next_zero_bit(s->blocks_gotten, @@ -1925,7 +1926,7 @@ static int __bch2_ec_stripe_head_reuse(struct btree_trans *trans, struct ec_stri } bch2_trans_iter_exit(trans, &lru_iter); if (!ret) - return bch_err_throw(c, stripe_alloc_blocked); + ret = bch_err_throw(c, stripe_alloc_blocked); if (ret == 1) ret = 0; if (ret) @@ -1997,7 +1998,8 @@ err: struct ec_stripe_head *bch2_ec_stripe_head_get(struct btree_trans *trans, struct alloc_request *req, - unsigned algo) + unsigned algo, + struct closure *cl) { struct bch_fs *c = trans->c; unsigned redundancy = req->nr_replicas - 1; @@ -2039,18 +2041,12 @@ struct ec_stripe_head *bch2_ec_stripe_head_get(struct btree_trans *trans, if (s->have_existing_stripe) goto alloc_existing; - /* First, try to allocate a full stripe: */ enum bch_watermark saved_watermark = BCH_WATERMARK_stripe; - unsigned saved_flags = req->flags | BCH_WRITE_alloc_nowait; - swap(req->watermark, saved_watermark); - swap(req->flags, saved_flags); - - ret = new_stripe_alloc_buckets(trans, req, h, s) ?: + swap(req->watermark, saved_watermark); + ret = new_stripe_alloc_buckets(trans, req, h, s, NULL) ?: __bch2_ec_stripe_head_reserve(trans, h, s); - - swap(req->watermark, saved_watermark); - swap(req->flags, saved_flags); + swap(req->watermark, saved_watermark); if (!ret) goto allocate_buf; @@ -2066,25 +2062,19 @@ struct ec_stripe_head *bch2_ec_stripe_head_get(struct btree_trans *trans, ret = __bch2_ec_stripe_head_reuse(trans, h, s); if (!ret) break; - if (waiting || - (req->flags & BCH_WRITE_alloc_nowait) || - ret != -BCH_ERR_stripe_alloc_blocked) + if (waiting || !cl || ret != -BCH_ERR_stripe_alloc_blocked) goto err; if (req->watermark == BCH_WATERMARK_copygc) { - /* Don't self-deadlock copygc */ - swap(req->flags, saved_flags); - ret = new_stripe_alloc_buckets(trans, req, h, s) ?: + ret = new_stripe_alloc_buckets(trans, req, h, s, NULL) ?: __bch2_ec_stripe_head_reserve(trans, h, s); - swap(req->flags, saved_flags); - if (ret) goto err; goto allocate_buf; } /* XXX freelist_wait? */ - closure_wait(&c->freelist_wait, req->cl); + closure_wait(&c->freelist_wait, cl); waiting = true; } @@ -2095,7 +2085,7 @@ alloc_existing: * Retry allocating buckets, with the watermark for this * particular write: */ - ret = new_stripe_alloc_buckets(trans, req, h, s); + ret = new_stripe_alloc_buckets(trans, req, h, s, cl); if (ret) goto err; |