mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 06:33:34 +00:00
bcachefs: Stripe deletion now checks what it's deleting
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
ebe8bd75a0
commit
ba7c37d330
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user