Commit af4d05c4 authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Account for stripe parity sectors separately

Instead of trying to charge EC parity to the data within the stripe
(which is subject to rounding errors), let's charge it to the stripe
itself. It should also make -ENOSPC issues easier to deal with if we
charge for parity blocks up front, and means we can also make more fine
grained accounting available to the user.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 39283c71
...@@ -1036,7 +1036,8 @@ LE64_BITMASK(BCH_KDF_SCRYPT_P, struct bch_sb_field_crypt, kdf_flags, 32, 48); ...@@ -1036,7 +1036,8 @@ LE64_BITMASK(BCH_KDF_SCRYPT_P, struct bch_sb_field_crypt, kdf_flags, 32, 48);
x(journal, 2) \ x(journal, 2) \
x(btree, 3) \ x(btree, 3) \
x(user, 4) \ x(user, 4) \
x(cached, 5) x(cached, 5) \
x(parity, 6)
enum bch_data_type { enum bch_data_type {
#define x(t, n) BCH_DATA_##t, #define x(t, n) BCH_DATA_##t,
......
This diff is collapsed.
...@@ -343,12 +343,17 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf, ...@@ -343,12 +343,17 @@ static void ec_block_io(struct bch_fs *c, struct ec_stripe_buf *buf,
unsigned offset = 0, bytes = buf->size << 9; unsigned offset = 0, bytes = buf->size << 9;
struct bch_extent_ptr *ptr = &v->ptrs[idx]; struct bch_extent_ptr *ptr = &v->ptrs[idx];
struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
enum bch_data_type data_type = idx < buf->key.v.nr_blocks - buf->key.v.nr_redundant
? BCH_DATA_user
: BCH_DATA_parity;
if (!bch2_dev_get_ioref(ca, rw)) { if (!bch2_dev_get_ioref(ca, rw)) {
clear_bit(idx, buf->valid); clear_bit(idx, buf->valid);
return; return;
} }
this_cpu_add(ca->io_done->sectors[rw][data_type], buf->size);
while (offset < bytes) { while (offset < bytes) {
unsigned nr_iovecs = min_t(size_t, BIO_MAX_VECS, unsigned nr_iovecs = min_t(size_t, BIO_MAX_VECS,
DIV_ROUND_UP(bytes, PAGE_SIZE)); DIV_ROUND_UP(bytes, PAGE_SIZE));
...@@ -670,6 +675,7 @@ static void ec_stripe_delete_work(struct work_struct *work) ...@@ -670,6 +675,7 @@ static void ec_stripe_delete_work(struct work_struct *work)
/* stripe creation: */ /* stripe creation: */
static int ec_stripe_bkey_insert(struct bch_fs *c, static int ec_stripe_bkey_insert(struct bch_fs *c,
struct ec_stripe_new *s,
struct bkey_i_stripe *stripe) struct bkey_i_stripe *stripe)
{ {
struct btree_trans trans; struct btree_trans trans;
...@@ -711,7 +717,7 @@ static int ec_stripe_bkey_insert(struct bch_fs *c, ...@@ -711,7 +717,7 @@ static int ec_stripe_bkey_insert(struct bch_fs *c,
bch2_trans_update(&trans, iter, &stripe->k_i, 0); bch2_trans_update(&trans, iter, &stripe->k_i, 0);
ret = bch2_trans_commit(&trans, NULL, NULL, ret = bch2_trans_commit(&trans, &s->res, NULL,
BTREE_INSERT_NOFAIL); BTREE_INSERT_NOFAIL);
err: err:
bch2_trans_iter_put(&trans, iter); bch2_trans_iter_put(&trans, iter);
...@@ -858,8 +864,8 @@ static void ec_stripe_create(struct ec_stripe_new *s) ...@@ -858,8 +864,8 @@ static void ec_stripe_create(struct ec_stripe_new *s)
ret = s->existing_stripe ret = s->existing_stripe
? bch2_btree_insert(c, BTREE_ID_EC, &s->stripe.key.k_i, ? bch2_btree_insert(c, BTREE_ID_EC, &s->stripe.key.k_i,
NULL, NULL, BTREE_INSERT_NOFAIL) &s->res, NULL, BTREE_INSERT_NOFAIL)
: ec_stripe_bkey_insert(c, &s->stripe.key); : ec_stripe_bkey_insert(c, s, &s->stripe.key);
if (ret) { if (ret) {
bch_err(c, "error creating stripe: error creating stripe key"); bch_err(c, "error creating stripe: error creating stripe key");
goto err_put_writes; goto err_put_writes;
...@@ -886,6 +892,8 @@ static void ec_stripe_create(struct ec_stripe_new *s) ...@@ -886,6 +892,8 @@ static void ec_stripe_create(struct ec_stripe_new *s)
err_put_writes: err_put_writes:
percpu_ref_put(&c->writes); percpu_ref_put(&c->writes);
err: err:
bch2_disk_reservation_put(c, &s->res);
open_bucket_for_each(c, &s->blocks, ob, i) { open_bucket_for_each(c, &s->blocks, ob, i) {
ob->ec = NULL; ob->ec = NULL;
__bch2_open_bucket_put(c, ob); __bch2_open_bucket_put(c, ob);
...@@ -1325,6 +1333,7 @@ struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c, ...@@ -1325,6 +1333,7 @@ struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c,
struct open_bucket *ob; struct open_bucket *ob;
unsigned i, data_idx = 0; unsigned i, data_idx = 0;
s64 idx; s64 idx;
int ret;
closure_init_stack(&cl); closure_init_stack(&cl);
...@@ -1356,6 +1365,22 @@ struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c, ...@@ -1356,6 +1365,22 @@ struct ec_stripe_head *bch2_ec_stripe_head_get(struct bch_fs *c,
} }
} }
if (!h->s->existing_stripe &&
!h->s->res.sectors) {
ret = bch2_disk_reservation_get(c, &h->s->res,
h->blocksize,
h->s->nr_parity, 0);
if (ret) {
/* What should we do here? */
bch_err(c, "unable to create new stripe: %i", ret);
bch2_ec_stripe_head_put(c, h);
h = NULL;
goto out;
}
}
if (new_stripe_alloc_buckets(c, h)) { if (new_stripe_alloc_buckets(c, h)) {
bch2_ec_stripe_head_put(c, h); bch2_ec_stripe_head_put(c, h);
h = NULL; h = NULL;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#define _BCACHEFS_EC_H #define _BCACHEFS_EC_H
#include "ec_types.h" #include "ec_types.h"
#include "buckets_types.h"
#include "keylist_types.h" #include "keylist_types.h"
const char *bch2_stripe_invalid(const struct bch_fs *, struct bkey_s_c); const char *bch2_stripe_invalid(const struct bch_fs *, struct bkey_s_c);
...@@ -105,6 +106,7 @@ struct ec_stripe_new { ...@@ -105,6 +106,7 @@ struct ec_stripe_new {
struct open_buckets blocks; struct open_buckets blocks;
u8 data_block_idx[EC_STRIPE_MAX]; u8 data_block_idx[EC_STRIPE_MAX];
struct open_buckets parity; struct open_buckets parity;
struct disk_reservation res;
struct keylist keys; struct keylist keys;
u64 inline_keys[BKEY_U64s * 8]; u64 inline_keys[BKEY_U64s * 8];
......
...@@ -122,7 +122,7 @@ void bch2_bkey_to_replicas(struct bch_replicas_entry *e, ...@@ -122,7 +122,7 @@ void bch2_bkey_to_replicas(struct bch_replicas_entry *e,
extent_to_replicas(k, e); extent_to_replicas(k, e);
break; break;
case KEY_TYPE_stripe: case KEY_TYPE_stripe:
e->data_type = BCH_DATA_user; e->data_type = BCH_DATA_parity;
stripe_to_replicas(k, e); stripe_to_replicas(k, e);
break; break;
} }
...@@ -449,7 +449,23 @@ static int __bch2_mark_bkey_replicas(struct bch_fs *c, struct bkey_s_c k, ...@@ -449,7 +449,23 @@ static int __bch2_mark_bkey_replicas(struct bch_fs *c, struct bkey_s_c k,
bch2_bkey_to_replicas(&search.e, k); bch2_bkey_to_replicas(&search.e, k);
return __bch2_mark_replicas(c, &search.e, check); ret = __bch2_mark_replicas(c, &search.e, check);
if (ret)
return ret;
if (search.e.data_type == BCH_DATA_parity) {
search.e.data_type = BCH_DATA_cached;
ret = __bch2_mark_replicas(c, &search.e, check);
if (ret)
return ret;
search.e.data_type = BCH_DATA_user;
ret = __bch2_mark_replicas(c, &search.e, check);
if (ret)
return ret;
}
return 0;
} }
bool bch2_bkey_replicas_marked(struct bch_fs *c, bool bch2_bkey_replicas_marked(struct bch_fs *c,
......
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