Commit 2c40a240 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Change allocations for ec stripes to blocking

We don't want writes to not get erasure coded just because the allocator
temporarily wasn't keeping up.

However, it's not guaranteed that these allocations will ever succeed,
we can currently get stuck - especially if devices are different sizes -
we still have work to do in this area.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 81d8599e
...@@ -446,16 +446,18 @@ bch2_bucket_alloc_set(struct bch_fs *c, ...@@ -446,16 +446,18 @@ bch2_bucket_alloc_set(struct bch_fs *c,
* it's to a device we don't want: * it's to a device we don't want:
*/ */
static void bucket_alloc_from_stripe(struct bch_fs *c, static enum bucket_alloc_ret
struct open_buckets *ptrs, bucket_alloc_from_stripe(struct bch_fs *c,
struct write_point *wp, struct open_buckets *ptrs,
struct bch_devs_mask *devs_may_alloc, struct write_point *wp,
u16 target, struct bch_devs_mask *devs_may_alloc,
unsigned erasure_code, u16 target,
unsigned nr_replicas, unsigned erasure_code,
unsigned *nr_effective, unsigned nr_replicas,
bool *have_cache, unsigned *nr_effective,
unsigned flags) bool *have_cache,
unsigned flags,
struct closure *cl)
{ {
struct dev_alloc_list devs_sorted; struct dev_alloc_list devs_sorted;
struct ec_stripe_head *h; struct ec_stripe_head *h;
...@@ -464,17 +466,19 @@ static void bucket_alloc_from_stripe(struct bch_fs *c, ...@@ -464,17 +466,19 @@ static void bucket_alloc_from_stripe(struct bch_fs *c,
unsigned i, ec_idx; unsigned i, ec_idx;
if (!erasure_code) if (!erasure_code)
return; return 0;
if (nr_replicas < 2) if (nr_replicas < 2)
return; return 0;
if (ec_open_bucket(c, ptrs)) 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) if (!h)
return; return 0;
devs_sorted = bch2_dev_alloc_list(c, &wp->stripe, devs_may_alloc); devs_sorted = bch2_dev_alloc_list(c, &wp->stripe, devs_may_alloc);
...@@ -496,6 +500,7 @@ static void bucket_alloc_from_stripe(struct bch_fs *c, ...@@ -496,6 +500,7 @@ static void bucket_alloc_from_stripe(struct bch_fs *c,
atomic_inc(&h->s->pin); atomic_inc(&h->s->pin);
out_put_head: out_put_head:
bch2_ec_stripe_head_put(c, h); bch2_ec_stripe_head_put(c, h);
return 0;
} }
/* Sector allocator */ /* Sector allocator */
...@@ -573,10 +578,13 @@ open_bucket_add_buckets(struct bch_fs *c, ...@@ -573,10 +578,13 @@ open_bucket_add_buckets(struct bch_fs *c,
} }
if (!ec_open_bucket(c, ptrs)) { 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, target, erasure_code,
nr_replicas, nr_effective, 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) if (*nr_effective >= nr_replicas)
return 0; return 0;
} }
......
...@@ -1228,10 +1228,9 @@ struct ec_stripe_head *__bch2_ec_stripe_head_get(struct bch_fs *c, ...@@ -1228,10 +1228,9 @@ struct ec_stripe_head *__bch2_ec_stripe_head_get(struct bch_fs *c,
return h; return h;
} }
/* static enum bucket_alloc_ret
* XXX: use a higher watermark for allocating open buckets here: new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h,
*/ struct closure *cl)
static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h)
{ {
struct bch_devs_mask devs; struct bch_devs_mask devs;
struct open_bucket *ob; struct open_bucket *ob;
...@@ -1239,7 +1238,7 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h) ...@@ -1239,7 +1238,7 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h)
min_t(unsigned, h->nr_active_devs, min_t(unsigned, h->nr_active_devs,
BCH_BKEY_PTRS_MAX) - h->redundancy; BCH_BKEY_PTRS_MAX) - h->redundancy;
bool have_cache = true; bool have_cache = true;
int ret = 0; enum bucket_alloc_ret ret = ALLOC_SUCCESS;
devs = h->devs; devs = h->devs;
...@@ -1270,7 +1269,7 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h) ...@@ -1270,7 +1269,7 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h)
&have_cache, &have_cache,
RESERVE_NONE, RESERVE_NONE,
0, 0,
NULL); cl);
if (ret) if (ret)
goto err; goto err;
} }
...@@ -1286,7 +1285,7 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h) ...@@ -1286,7 +1285,7 @@ static int new_stripe_alloc_buckets(struct bch_fs *c, struct ec_stripe_head *h)
&have_cache, &have_cache,
RESERVE_NONE, RESERVE_NONE,
0, 0,
NULL); cl);
if (ret) if (ret)
goto err; goto err;
} }
...@@ -1352,7 +1351,8 @@ static int get_stripe_key(struct bch_fs *c, u64 idx, struct ec_stripe_buf *strip ...@@ -1352,7 +1351,8 @@ static int get_stripe_key(struct bch_fs *c, u64 idx, struct ec_stripe_buf *strip
struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c, struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c,
unsigned target, unsigned target,
unsigned algo, unsigned algo,
unsigned redundancy) unsigned redundancy,
struct closure *cl)
{ {
struct ec_stripe_head *h; struct ec_stripe_head *h;
struct open_bucket *ob; struct open_bucket *ob;
...@@ -1421,14 +1421,13 @@ struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c, ...@@ -1421,14 +1421,13 @@ struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c,
bch2_ec_stripe_head_put(c, h); bch2_ec_stripe_head_put(c, h);
h = NULL; h = NULL;
goto out; 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); bch2_ec_stripe_head_put(c, h);
h = NULL; h = ERR_PTR(-ret);
goto out; goto out;
} }
......
...@@ -146,8 +146,8 @@ void bch2_ec_bucket_cancel(struct bch_fs *, struct open_bucket *); ...@@ -146,8 +146,8 @@ void bch2_ec_bucket_cancel(struct bch_fs *, struct open_bucket *);
int bch2_ec_stripe_new_alloc(struct bch_fs *, struct ec_stripe_head *); 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 *); 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, struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *,
unsigned, unsigned); unsigned, unsigned, unsigned, struct closure *);
void bch2_stripes_heap_update(struct bch_fs *, struct stripe *, size_t); void bch2_stripes_heap_update(struct bch_fs *, struct stripe *, size_t);
void bch2_stripes_heap_del(struct bch_fs *, struct stripe *, size_t); void bch2_stripes_heap_del(struct bch_fs *, struct stripe *, size_t);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment