}
static int new_stripe_alloc_buckets(struct btree_trans *trans,
+ struct alloc_request *req,
struct ec_stripe_head *h, struct ec_stripe_new *s,
- enum bch_watermark watermark, struct closure *cl)
+ struct closure *cl)
{
struct bch_fs *c = trans->c;
struct open_bucket *ob;
unsigned i, j, nr_have_parity = 0, nr_have_data = 0;
int ret = 0;
- struct alloc_request req = {
- .watermark = watermark,
- .devs_may_alloc = h->devs,
- .have_cache = true,
- };
+ enum bch_data_type saved_data_type = req->data_type;
+ struct open_buckets saved_ptrs = req->ptrs;
+ unsigned saved_nr_replicas = req->nr_replicas;
+ unsigned saved_nr_effective = req->nr_effective;
+ bool saved_have_cache = req->have_cache;
+ struct bch_devs_mask saved_devs_may_alloc = req->devs_may_alloc;
+
+ req->devs_may_alloc = h->devs;
+ req->have_cache = true;
BUG_ON(v->nr_blocks != s->nr_data + s->nr_parity);
BUG_ON(v->nr_redundant != s->nr_parity);
/* * We bypass the sector allocator which normally does this: */
- bitmap_and(req.devs_may_alloc.d, req.devs_may_alloc.d,
+ bitmap_and(req->devs_may_alloc.d, req->devs_may_alloc.d,
c->rw_devs[BCH_DATA_user].d, BCH_SB_MEMBERS_MAX);
for_each_set_bit(i, s->blocks_gotten, v->nr_blocks) {
* block when updating the stripe
*/
if (v->ptrs[i].dev != BCH_SB_MEMBER_INVALID)
- __clear_bit(v->ptrs[i].dev, req.devs_may_alloc.d);
+ __clear_bit(v->ptrs[i].dev, req->devs_may_alloc.d);
if (i < s->nr_data)
nr_have_data++;
BUG_ON(nr_have_data > s->nr_data);
BUG_ON(nr_have_parity > s->nr_parity);
- req.ptrs.nr = 0;
+ req->ptrs.nr = 0;
if (nr_have_parity < s->nr_parity) {
- req.nr_replicas = s->nr_parity;
- req.nr_effective = nr_have_parity;
- req.data_type = BCH_DATA_parity;
+ req->nr_replicas = s->nr_parity;
+ req->nr_effective = nr_have_parity;
+ req->data_type = BCH_DATA_parity;
- ret = bch2_bucket_alloc_set_trans(trans, &req, &h->parity_stripe, cl);
+ ret = bch2_bucket_alloc_set_trans(trans, req, &h->parity_stripe, cl);
- open_bucket_for_each(c, &req.ptrs, ob, i) {
+ open_bucket_for_each(c, &req->ptrs, ob, i) {
j = find_next_zero_bit(s->blocks_gotten,
s->nr_data + s->nr_parity,
s->nr_data);
BUG_ON(j >= s->nr_data + s->nr_parity);
- s->blocks[j] = req.ptrs.v[i];
+ s->blocks[j] = req->ptrs.v[i];
v->ptrs[j] = bch2_ob_ptr(c, ob);
__set_bit(j, s->blocks_gotten);
}
if (ret)
- return ret;
+ goto err;
}
- req.ptrs.nr = 0;
+ req->ptrs.nr = 0;
if (nr_have_data < s->nr_data) {
- req.nr_replicas = s->nr_data;
- req.nr_effective = nr_have_data;
- req.data_type = BCH_DATA_user;
+ req->nr_replicas = s->nr_data;
+ req->nr_effective = nr_have_data;
+ req->data_type = BCH_DATA_user;
- ret = bch2_bucket_alloc_set_trans(trans, &req, &h->block_stripe, cl);
+ ret = bch2_bucket_alloc_set_trans(trans, req, &h->block_stripe, cl);
- open_bucket_for_each(c, &req.ptrs, ob, i) {
+ open_bucket_for_each(c, &req->ptrs, ob, i) {
j = find_next_zero_bit(s->blocks_gotten,
s->nr_data, 0);
BUG_ON(j >= s->nr_data);
- s->blocks[j] = req.ptrs.v[i];
+ s->blocks[j] = req->ptrs.v[i];
v->ptrs[j] = bch2_ob_ptr(c, ob);
__set_bit(j, s->blocks_gotten);
}
if (ret)
- return ret;
+ goto err;
}
-
- return 0;
+err:
+ req->data_type = saved_data_type;
+ req->ptrs = saved_ptrs;
+ req->nr_replicas = saved_nr_replicas;
+ req->nr_effective = saved_nr_effective;
+ req->have_cache = saved_have_cache;
+ req->devs_may_alloc = saved_devs_may_alloc;
+ return ret;
}
static int __get_existing_stripe(struct btree_trans *trans,
goto alloc_existing;
/* First, try to allocate a full stripe: */
- ret = new_stripe_alloc_buckets(trans, h, s, BCH_WATERMARK_stripe, NULL) ?:
+ enum bch_watermark saved_watermark = BCH_WATERMARK_stripe;
+ 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);
+
if (!ret)
goto allocate_buf;
if (bch2_err_matches(ret, BCH_ERR_transaction_restart) ||
goto err;
if (req->watermark == BCH_WATERMARK_copygc) {
- ret = new_stripe_alloc_buckets(trans, h, s, req->watermark, NULL) ?:
+ ret = new_stripe_alloc_buckets(trans, req, h, s, NULL) ?:
__bch2_ec_stripe_head_reserve(trans, h, s);
if (ret)
goto err;
* Retry allocating buckets, with the watermark for this
* particular write:
*/
- ret = new_stripe_alloc_buckets(trans, h, s, req->watermark, cl);
+ ret = new_stripe_alloc_buckets(trans, req, h, s, cl);
if (ret)
goto err;