mirror of
https://github.com/torvalds/linux.git
synced 2026-05-21 13:27:57 +02:00
bcachefs: bch2_dev_journal_bucket_delete()
Recover from "journal and btree in same bucket". Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
0224d17d76
commit
d21262d4e3
|
|
@ -221,6 +221,20 @@ static int bch2_check_fix_ptr(struct btree_trans *trans,
|
|||
bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
|
||||
if (!p.ptr.cached &&
|
||||
data_type == BCH_DATA_btree) {
|
||||
switch (g->data_type) {
|
||||
case BCH_DATA_sb:
|
||||
bch_err(c, "btree and superblock in the same bucket - cannot repair");
|
||||
ret = -BCH_ERR_fsck_repair_unimplemented;
|
||||
goto out;
|
||||
case BCH_DATA_journal:
|
||||
ret = bch2_dev_journal_bucket_delete(ca, PTR_BUCKET_NR(ca, &p.ptr));
|
||||
bch_err_msg(c, ret, "error deleting journal bucket %zu",
|
||||
PTR_BUCKET_NR(ca, &p.ptr));
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
|
||||
g->data_type = data_type;
|
||||
g->stripe_sectors = 0;
|
||||
g->dirty_sectors = 0;
|
||||
|
|
|
|||
|
|
@ -1304,6 +1304,66 @@ int bch2_set_nr_journal_buckets(struct bch_fs *c, struct bch_dev *ca,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int bch2_dev_journal_bucket_delete(struct bch_dev *ca, u64 b)
|
||||
{
|
||||
struct bch_fs *c = ca->fs;
|
||||
struct journal *j = &c->journal;
|
||||
struct journal_device *ja = &ca->journal;
|
||||
|
||||
guard(mutex)(&c->sb_lock);
|
||||
unsigned pos;
|
||||
for (pos = 0; pos < ja->nr; pos++)
|
||||
if (ja->buckets[pos] == b)
|
||||
break;
|
||||
|
||||
if (pos == ja->nr) {
|
||||
bch_err(ca, "journal bucket %llu not found when deleting", b);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
u64 *new_buckets = kcalloc(ja->nr, sizeof(u64), GFP_KERNEL);;
|
||||
if (!new_buckets)
|
||||
return -BCH_ERR_ENOMEM_set_nr_journal_buckets;
|
||||
|
||||
memcpy(new_buckets, ja->buckets, ja->nr * sizeof(u64));
|
||||
memmove(&new_buckets[pos],
|
||||
&new_buckets[pos + 1],
|
||||
(ja->nr - 1 - pos) * sizeof(new_buckets[0]));
|
||||
|
||||
int ret = bch2_journal_buckets_to_sb(c, ca, ja->buckets, ja->nr - 1) ?:
|
||||
bch2_write_super(c);
|
||||
if (ret) {
|
||||
kfree(new_buckets);
|
||||
return ret;
|
||||
}
|
||||
|
||||
scoped_guard(spinlock, &j->lock) {
|
||||
if (pos < ja->discard_idx)
|
||||
--ja->discard_idx;
|
||||
if (pos < ja->dirty_idx_ondisk)
|
||||
--ja->dirty_idx_ondisk;
|
||||
if (pos < ja->dirty_idx)
|
||||
--ja->dirty_idx;
|
||||
if (pos < ja->cur_idx)
|
||||
--ja->cur_idx;
|
||||
|
||||
ja->nr--;
|
||||
|
||||
memmove(&ja->buckets[pos],
|
||||
&ja->buckets[pos + 1],
|
||||
(ja->nr - pos) * sizeof(ja->buckets[0]));
|
||||
|
||||
memmove(&ja->bucket_seq[pos],
|
||||
&ja->bucket_seq[pos + 1],
|
||||
(ja->nr - pos) * sizeof(ja->bucket_seq[0]));
|
||||
|
||||
bch2_journal_space_available(j);
|
||||
}
|
||||
|
||||
kfree(new_buckets);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bch2_dev_journal_alloc(struct bch_dev *ca, bool new_fs)
|
||||
{
|
||||
struct bch_fs *c = ca->fs;
|
||||
|
|
|
|||
|
|
@ -444,8 +444,9 @@ struct journal_buf *bch2_next_write_buffer_flush_journal_buf(struct journal *, u
|
|||
void __bch2_journal_debug_to_text(struct printbuf *, struct journal *);
|
||||
void bch2_journal_debug_to_text(struct printbuf *, struct journal *);
|
||||
|
||||
int bch2_set_nr_journal_buckets(struct bch_fs *, struct bch_dev *,
|
||||
unsigned nr);
|
||||
int bch2_set_nr_journal_buckets(struct bch_fs *, struct bch_dev *, unsigned);
|
||||
int bch2_dev_journal_bucket_delete(struct bch_dev *, u64);
|
||||
|
||||
int bch2_dev_journal_alloc(struct bch_dev *, bool);
|
||||
int bch2_fs_journal_alloc(struct bch_fs *);
|
||||
|
||||
|
|
|
|||
|
|
@ -239,7 +239,8 @@ int __bch2_str_hash_check_key(struct btree_trans *trans,
|
|||
|
||||
for_each_btree_key_norestart(trans, iter, desc->btree_id,
|
||||
SPOS(hash_k.k->p.inode, hash, hash_k.k->p.snapshot),
|
||||
BTREE_ITER_slots, k, ret) {
|
||||
BTREE_ITER_slots|
|
||||
BTREE_ITER_with_updates, k, ret) {
|
||||
if (bkey_eq(k.k->p, hash_k.k->p))
|
||||
break;
|
||||
|
||||
|
|
@ -286,10 +287,11 @@ int __bch2_str_hash_check_key(struct btree_trans *trans,
|
|||
goto duplicate_entries;
|
||||
|
||||
ret = bch2_hash_delete_at(trans, *desc, hash_info, k_iter,
|
||||
BTREE_ITER_with_updates|
|
||||
BTREE_UPDATE_internal_snapshot_node) ?:
|
||||
bch2_fsck_update_backpointers(trans, s, *desc, hash_info, new) ?:
|
||||
bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc) ?:
|
||||
-BCH_ERR_transaction_restart_nested;
|
||||
-BCH_ERR_transaction_restart_commit;
|
||||
goto out;
|
||||
}
|
||||
fsck_err:
|
||||
|
|
@ -323,6 +325,6 @@ int __bch2_str_hash_check_key(struct btree_trans *trans,
|
|||
}
|
||||
|
||||
ret = bch2_trans_commit(trans, NULL, NULL, 0) ?:
|
||||
-BCH_ERR_transaction_restart_nested;
|
||||
-BCH_ERR_transaction_restart_commit;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user