bcachefs: Stripe deletion now checks what it's deleting

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2023-02-18 21:31:07 -05:00
parent ebe8bd75a0
commit ba7c37d330

View File

@ -584,12 +584,12 @@ static int ec_stripe_mem_alloc(struct btree_trans *trans,
bch2_trans_relock(trans);
}
static ssize_t stripe_idx_to_delete(struct bch_fs *c)
static u64 stripe_idx_to_delete(struct bch_fs *c)
{
ec_stripes_heap *h = &c->ec_stripes_heap;
return h->used && h->data[0].blocks_nonempty == 0
? h->data[0].idx : -1;
? h->data[0].idx : 0;
}
static inline int ec_stripes_heap_cmp(ec_stripes_heap *h,
@ -674,41 +674,81 @@ void bch2_stripes_heap_update(struct bch_fs *c,
heap_verify_backpointer(c, idx);
if (stripe_idx_to_delete(c) >= 0)
if (stripe_idx_to_delete(c))
bch2_do_stripe_deletes(c);
}
/* stripe deletion */
static int ec_stripe_delete(struct bch_fs *c, size_t idx)
static int ec_stripe_delete(struct btree_trans *trans, u64 idx)
{
return bch2_btree_delete_range(c, BTREE_ID_stripes,
POS(0, idx),
POS(0, idx),
0, NULL);
struct bch_fs *c = trans->c;
struct btree_iter iter;
struct bkey_s_c k;
struct bkey_s_c_stripe s;
int ret;
bch2_trans_iter_init(trans, &iter, BTREE_ID_stripes, POS(0, idx),
BTREE_ITER_INTENT);
k = bch2_btree_iter_peek_slot(&iter);
ret = bkey_err(k);
if (ret)
goto err;
if (k.k->type != KEY_TYPE_stripe) {
bch2_fs_inconsistent(c, "attempting to delete nonexistent stripe %llu", idx);
ret = -EINVAL;
goto err;
}
s = bkey_s_c_to_stripe(k);
for (unsigned i = 0; i < s.v->nr_blocks; i++)
if (stripe_blockcount_get(s.v, i)) {
struct printbuf buf = PRINTBUF;
bch2_bkey_val_to_text(&buf, c, k);
bch2_fs_inconsistent(c, "attempting to delete nonempty stripe %s", buf.buf);
printbuf_exit(&buf);
ret = -EINVAL;
goto err;
}
ret = bch2_btree_delete_at(trans, &iter, 0);
err:
bch2_trans_iter_exit(trans, &iter);
return ret;
}
static void ec_stripe_delete_work(struct work_struct *work)
{
struct bch_fs *c =
container_of(work, struct bch_fs, ec_stripe_delete_work);
ssize_t idx;
struct btree_trans trans;
int ret;
u64 idx;
bch2_trans_init(&trans, c, 0, 0);
while (1) {
mutex_lock(&c->ec_stripes_heap_lock);
idx = stripe_idx_to_delete(c);
if (idx < 0) {
mutex_unlock(&c->ec_stripes_heap_lock);
break;
}
bch2_stripes_heap_del(c, genradix_ptr(&c->stripes, idx), idx);
if (idx)
bch2_stripes_heap_del(c, genradix_ptr(&c->stripes, idx), idx);
mutex_unlock(&c->ec_stripes_heap_lock);
if (ec_stripe_delete(c, idx))
if (!idx)
break;
ret = commit_do(&trans, NULL, NULL, BTREE_INSERT_NOFAIL,
ec_stripe_delete(&trans, idx));
if (ret) {
bch_err(c, "%s: err %s", __func__, bch2_err_str(ret));
break;
}
}
bch2_trans_exit(&trans);
bch2_write_ref_put(c, BCH_WRITE_REF_stripe_delete);
}