* it's to a device we don't want:
  */
 
-static void bucket_alloc_from_stripe(struct bch_fs *c,
-                                    struct open_buckets *ptrs,
-                                    struct write_point *wp,
-                                    struct bch_devs_mask *devs_may_alloc,
-                                    u16 target,
-                                    unsigned erasure_code,
-                                    unsigned nr_replicas,
-                                    unsigned *nr_effective,
-                                    bool *have_cache,
-                                    unsigned flags)
+static enum bucket_alloc_ret
+bucket_alloc_from_stripe(struct bch_fs *c,
+                        struct open_buckets *ptrs,
+                        struct write_point *wp,
+                        struct bch_devs_mask *devs_may_alloc,
+                        u16 target,
+                        unsigned erasure_code,
+                        unsigned nr_replicas,
+                        unsigned *nr_effective,
+                        bool *have_cache,
+                        unsigned flags,
+                        struct closure *cl)
 {
        struct dev_alloc_list devs_sorted;
        struct ec_stripe_head *h;
        unsigned i, ec_idx;
 
        if (!erasure_code)
-               return;
+               return 0;
 
        if (nr_replicas < 2)
-               return;
+               return 0;
 
        if (ec_open_bucket(c, ptrs))
-               return;
+               return 0;
 
-       h = bch2_ec_stripe_head_get(c, target, 0, nr_replicas - 1);
+       h = bch2_ec_stripe_head_get(c, target, 0, nr_replicas - 1, cl);
+       if (IS_ERR(h))
+               return -PTR_ERR(h);
        if (!h)
-               return;
+               return 0;
 
        devs_sorted = bch2_dev_alloc_list(c, &wp->stripe, devs_may_alloc);
 
        atomic_inc(&h->s->pin);
 out_put_head:
        bch2_ec_stripe_head_put(c, h);
+       return 0;
 }
 
 /* Sector allocator */
                }
 
                if (!ec_open_bucket(c, ptrs)) {
-                       bucket_alloc_from_stripe(c, ptrs, wp, &devs,
+                       ret = bucket_alloc_from_stripe(c, ptrs, wp, &devs,
                                                 target, erasure_code,
                                                 nr_replicas, nr_effective,
-                                                have_cache, flags);
+                                                have_cache, flags, _cl);
+                       if (ret == FREELIST_EMPTY ||
+                           ret == OPEN_BUCKETS_EMPTY)
+                               return ret;
                        if (*nr_effective >= nr_replicas)
                                return 0;
                }
 
        return h;
 }
 
-/*
- * XXX: use a higher watermark for allocating open buckets here:
- */
-static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h)
+static enum bucket_alloc_ret
+new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h,
+                        struct closure *cl)
 {
        struct bch_devs_mask devs;
        struct open_bucket *ob;
                min_t(unsigned, h->nr_active_devs,
                      BCH_BKEY_PTRS_MAX) - h->redundancy;
        bool have_cache = true;
-       int ret = 0;
+       enum bucket_alloc_ret ret = ALLOC_SUCCESS;
 
        devs = h->devs;
 
                                            &have_cache,
                                            RESERVE_NONE,
                                            0,
-                                           NULL);
+                                           cl);
                if (ret)
                        goto err;
        }
                                            &have_cache,
                                            RESERVE_NONE,
                                            0,
-                                           NULL);
+                                           cl);
                if (ret)
                        goto err;
        }
 struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c,
                                               unsigned target,
                                               unsigned algo,
-                                              unsigned redundancy)
+                                              unsigned redundancy,
+                                              struct closure *cl)
 {
        struct ec_stripe_head *h;
        struct open_bucket *ob;
                                bch2_ec_stripe_head_put(c, h);
                                h = NULL;
                                goto out;
-
                        }
-
                }
 
-               if (new_stripe_alloc_buckets(c, h)) {
+               ret = new_stripe_alloc_buckets(c, h, cl);
+               if (ret) {
                        bch2_ec_stripe_head_put(c, h);
-                       h = NULL;
+                       h = ERR_PTR(-ret);
                        goto out;
                }
 
 
 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 ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *, unsigned,
-                                              unsigned, unsigned);
+struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *,
+                       unsigned, unsigned, unsigned, struct closure *);
 
 void bch2_stripes_heap_update(struct bch_fs *, struct stripe *, size_t);
 void bch2_stripes_heap_del(struct bch_fs *, struct stripe *, size_t);