summaryrefslogtreecommitdiff
path: root/fs/bcachefs/ec.c
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-01-17 17:43:49 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:51 -0400
commitc6e658ee9f7f7d1da410ada1c3174fe46541c454 (patch)
treeb116d27a43d8fca5cb9737e1876545054cd4ad11 /fs/bcachefs/ec.c
parent6e53151b7b738fe60b9295c2ff47e6b2092718b1 (diff)
downloadlwn-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.c59
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);