/**
  * bch2_bucket_alloc_trans - allocate a single bucket from a specific device
  * @trans:     transaction object
+ * @req:       state for the entire allocation
  * @ca:                device to allocate from
- * @watermark: how important is this allocation?
- * @data_type: BCH_DATA_journal, btree, user...
  * @cl:                if not NULL, closure to be used to wait if buckets not available
  * @nowait:    if true, do not wait for buckets to become available
  * @usage:     for secondarily also returning the current device usage
                return 0;
 
        struct ec_stripe_head *h =
-               bch2_ec_stripe_head_get(trans, req->target, 0, req->nr_replicas - 1, req->watermark, cl);
+               bch2_ec_stripe_head_get(trans, req, 0, cl);
        if (IS_ERR(h))
                return PTR_ERR(h);
        if (!h)
 
        enum bch_write_flags    flags;
        enum bch_data_type      data_type;
        struct bch_devs_list    *devs_have;
-
        struct write_point      *wp;
-       struct open_buckets     ptrs;
-       unsigned                nr_effective;
-       bool                    have_cache;
 
+       struct open_buckets     ptrs;
+       unsigned                nr_effective;   /* sum of @ptrs durability */
+       bool                    have_cache;     /* have we allocated from a 0 durability dev */
        struct bch_devs_mask    devs_may_alloc;
 };
 
 
 }
 
 struct ec_stripe_head *bch2_ec_stripe_head_get(struct btree_trans *trans,
-                                              unsigned target,
+                                              struct alloc_request *req,
                                               unsigned algo,
-                                              unsigned redundancy,
-                                              enum bch_watermark watermark,
                                               struct closure *cl)
 {
        struct bch_fs *c = trans->c;
-       struct ec_stripe_head *h;
-       bool waiting = false;
+       unsigned redundancy = req->nr_replicas - 1;
        unsigned disk_label = 0;
-       struct target t = target_decode(target);
+       struct target t = target_decode(req->target);
+       bool waiting = false;
        int ret;
 
        if (t.type == TARGET_GROUP) {
                disk_label = t.group + 1; /* 0 == no label */
        }
 
-       h = __bch2_ec_stripe_head_get(trans, disk_label, algo, redundancy, watermark);
+       struct ec_stripe_head *h =
+               __bch2_ec_stripe_head_get(trans, disk_label, algo,
+                                         redundancy, req->watermark);
        if (IS_ERR_OR_NULL(h))
                return h;
 
                if (waiting || !cl || ret != -BCH_ERR_stripe_alloc_blocked)
                        goto err;
 
-               if (watermark == BCH_WATERMARK_copygc) {
-                       ret =   new_stripe_alloc_buckets(trans, h, s, watermark, NULL) ?:
+               if (req->watermark == BCH_WATERMARK_copygc) {
+                       ret =   new_stripe_alloc_buckets(trans, h, s, req->watermark, 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, watermark, cl);
+       ret = new_stripe_alloc_buckets(trans, h, s, req->watermark, cl);
        if (ret)
                goto err;
 
 
 int bch2_ec_stripe_new_alloc(struct bch_fs *, struct ec_stripe_head *);
 
 void bch2_ec_stripe_head_put(struct bch_fs *, struct ec_stripe_head *);
+
+struct alloc_request;
 struct ec_stripe_head *bch2_ec_stripe_head_get(struct btree_trans *,
-                       unsigned, unsigned, unsigned,
-                       enum bch_watermark, struct closure *);
+                       struct alloc_request *, unsigned, struct closure *);
 
 void bch2_do_stripe_deletes(struct bch_fs *);
 void bch2_ec_do_stripe_creates(struct bch_fs *);