bcachefs: Fix locking when checking freespace btree
On transaction restart, we weren't re-validating the hole we saw. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
359d1bad1b
commit
7d9ae04e39
@ -1212,7 +1212,7 @@ fsck_err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline_for_stack int __bch2_check_discard_freespace_key(struct btree_trans *trans,
|
static noinline_for_stack int bch2_check_discard_freespace_key(struct btree_trans *trans,
|
||||||
struct btree_iter *iter)
|
struct btree_iter *iter)
|
||||||
{
|
{
|
||||||
struct bch_fs *c = trans->c;
|
struct bch_fs *c = trans->c;
|
||||||
@ -1271,24 +1271,6 @@ delete:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bch2_check_discard_freespace_key(struct btree_trans *trans,
|
|
||||||
struct btree_iter *iter,
|
|
||||||
struct bpos end)
|
|
||||||
{
|
|
||||||
if (!btree_id_is_extents(iter->btree_id)) {
|
|
||||||
return __bch2_check_discard_freespace_key(trans, iter);
|
|
||||||
} else {
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
while (!bkey_eq(iter->pos, end) &&
|
|
||||||
!(ret = btree_trans_too_many_iters(trans) ?:
|
|
||||||
__bch2_check_discard_freespace_key(trans, iter)))
|
|
||||||
bch2_btree_iter_set_pos(iter, bpos_nosnap_successor(iter->pos));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We've already checked that generation numbers in the bucket_gens btree are
|
* We've already checked that generation numbers in the bucket_gens btree are
|
||||||
* valid for buckets that exist; this just checks for keys for nonexistent
|
* valid for buckets that exist; this just checks for keys for nonexistent
|
||||||
@ -1445,12 +1427,40 @@ bkey_err:
|
|||||||
ret = for_each_btree_key2(trans, iter,
|
ret = for_each_btree_key2(trans, iter,
|
||||||
BTREE_ID_need_discard, POS_MIN,
|
BTREE_ID_need_discard, POS_MIN,
|
||||||
BTREE_ITER_PREFETCH, k,
|
BTREE_ITER_PREFETCH, k,
|
||||||
bch2_check_discard_freespace_key(trans, &iter, k.k->p)) ?:
|
bch2_check_discard_freespace_key(trans, &iter));
|
||||||
for_each_btree_key2(trans, iter,
|
if (ret)
|
||||||
BTREE_ID_freespace, POS_MIN,
|
goto err;
|
||||||
BTREE_ITER_PREFETCH, k,
|
|
||||||
bch2_check_discard_freespace_key(trans, &iter, k.k->p)) ?:
|
bch2_trans_iter_init(trans, &iter, BTREE_ID_freespace, POS_MIN,
|
||||||
for_each_btree_key_commit(trans, iter,
|
BTREE_ITER_PREFETCH);
|
||||||
|
while (1) {
|
||||||
|
bch2_trans_begin(trans);
|
||||||
|
k = bch2_btree_iter_peek(&iter);
|
||||||
|
if (!k.k)
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret = bkey_err(k) ?:
|
||||||
|
bch2_check_discard_freespace_key(trans, &iter);
|
||||||
|
if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) {
|
||||||
|
ret = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
struct printbuf buf = PRINTBUF;
|
||||||
|
bch2_bkey_val_to_text(&buf, c, k);
|
||||||
|
|
||||||
|
bch_err(c, "while checking %s", buf.buf);
|
||||||
|
printbuf_exit(&buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bch2_btree_iter_set_pos(&iter, bpos_nosnap_successor(iter.pos));
|
||||||
|
}
|
||||||
|
bch2_trans_iter_exit(trans, &iter);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
ret = for_each_btree_key_commit(trans, iter,
|
||||||
BTREE_ID_bucket_gens, POS_MIN,
|
BTREE_ID_bucket_gens, POS_MIN,
|
||||||
BTREE_ITER_PREFETCH, k,
|
BTREE_ITER_PREFETCH, k,
|
||||||
NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW,
|
NULL, NULL, BTREE_INSERT_NOFAIL|BTREE_INSERT_LAZY_RW,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user