diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-01-17 17:43:49 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:51 -0400 |
commit | c6e658ee9f7f7d1da410ada1c3174fe46541c454 (patch) | |
tree | b116d27a43d8fca5cb9737e1876545054cd4ad11 /fs/bcachefs/ec.c | |
parent | 6e53151b7b738fe60b9295c2ff47e6b2092718b1 (diff) | |
download | lwn-c6e658ee9f7f7d1da410ada1c3174fe46541c454.tar.gz lwn-c6e658ee9f7f7d1da410ada1c3174fe46541c454.zip |
bcachefs: Preserve stripe blockcounts on existing stripes
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/ec.c')
-rw-r--r-- | fs/bcachefs/ec.c | 59 |
1 files changed, 48 insertions, 11 deletions
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index 0d9a27726c05..d48df42d41e9 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -684,8 +684,8 @@ static void ec_stripe_delete_work(struct work_struct *work) /* stripe creation: */ 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 disk_reservation *res) { struct btree_trans trans; struct btree_iter *iter; @@ -726,7 +726,7 @@ found_slot: bch2_trans_update(&trans, iter, &stripe->k_i, 0); - ret = bch2_trans_commit(&trans, &s->res, NULL, + ret = bch2_trans_commit(&trans, res, NULL, BTREE_INSERT_NOFAIL); err: bch2_trans_iter_put(&trans, iter); @@ -740,6 +740,47 @@ err: return ret; } +static int ec_stripe_bkey_update(struct btree_trans *trans, + struct bkey_i_stripe *new) +{ + struct bch_fs *c = trans->c; + struct btree_iter *iter; + struct bkey_s_c k; + const struct bch_stripe *existing; + unsigned i; + int ret; + + iter = bch2_trans_get_iter(trans, BTREE_ID_EC, + new->k.p, BTREE_ITER_INTENT); + k = bch2_btree_iter_peek_slot(iter); + ret = bkey_err(k); + if (ret) + goto err; + + if (!k.k || k.k->type != KEY_TYPE_stripe) { + bch_err(c, "error updating stripe: not found"); + ret = -ENOENT; + goto err; + } + + existing = bkey_s_c_to_stripe(k).v; + + if (existing->nr_blocks != new->v.nr_blocks) { + bch_err(c, "error updating stripe: nr_blocks does not match"); + ret = -EINVAL; + goto err; + } + + for (i = 0; i < new->v.nr_blocks; i++) + stripe_blockcount_set(&new->v, i, + stripe_blockcount_get(existing, i)); + + bch2_trans_update(trans, iter, &new->k_i, 0); +err: + bch2_trans_iter_put(trans, iter); + return ret; +} + static void extent_stripe_ptr_add(struct bkey_s_extent e, struct ec_stripe_buf *s, struct bch_extent_ptr *ptr, @@ -884,9 +925,9 @@ static void ec_stripe_create(struct ec_stripe_new *s) } ret = s->have_existing_stripe - ? bch2_btree_insert(c, BTREE_ID_EC, &s->new_stripe.key.k_i, - &s->res, NULL, BTREE_INSERT_NOFAIL) - : ec_stripe_bkey_insert(c, s, &s->new_stripe.key); + ? bch2_trans_do(c, &s->res, NULL, BTREE_INSERT_NOFAIL, + ec_stripe_bkey_update(&trans, &s->new_stripe.key)) + : ec_stripe_bkey_insert(c, &s->new_stripe.key, &s->res); if (ret) { bch_err(c, "error creating stripe: error creating stripe key"); goto err_put_writes; @@ -902,11 +943,7 @@ static void ec_stripe_create(struct ec_stripe_new *s) spin_lock(&c->ec_stripes_heap_lock); m = genradix_ptr(&c->stripes[0], s->new_stripe.key.k.p.offset); -#if 0 - pr_info("created a %s stripe %llu", - s->have_existing_stripe ? "existing" : "new", - s->stripe.key.k.p.offset); -#endif + BUG_ON(m->on_heap); bch2_stripes_heap_insert(c, m, s->new_stripe.key.k.p.offset); spin_unlock(&c->ec_stripes_heap_lock); |