summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-03-16 22:45:30 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2024-03-22 17:03:20 -0400
commitfca84f2f5836fe34b43514a75cff9162bdd1c5c1 (patch)
tree6abf9b86c115a3e50f54b78775ce4b1bab65a777
parentff14df27df54781c9516df246e1ba88c7b6fd587 (diff)
bcachefs: Handle empty btree roots in topology repair
With the new btree node scan code, we can now recover from corrupt btree roots - simply create a new fake root at depth 1, and then insert all the leaves we found. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/btree_gc.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c
index 6b99f2024780..0e0b7c2868fd 100644
--- a/fs/bcachefs/btree_gc.c
+++ b/fs/bcachefs/btree_gc.c
@@ -552,10 +552,12 @@ int bch2_check_topology(struct bch_fs *c)
struct btree_root *r = bch2_btree_id_root(c, i);
if (r->error) {
- bch2_btree_root_alloc_fake(c, i, r->level);
+ bch2_btree_root_alloc_fake(c, i, 1);
+ r->alive = false;
r->error = 0;
- ret = bch2_repair_missing_btree_node(c, i, r->level, POS_MIN, SPOS_MAX);
+ bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX);
+ ret = bch2_repair_missing_btree_node(c, i, 0, POS_MIN, SPOS_MAX);
if (ret)
break;
}
@@ -567,8 +569,13 @@ int bch2_check_topology(struct bch_fs *c)
six_unlock_read(&b->c.lock);
if (ret == DROP_THIS_NODE) {
- bch_err(c, "empty btree root - repair unimplemented");
- ret = -BCH_ERR_fsck_repair_unimplemented;
+ bch_err(c, "empty btree root %s", bch2_btree_id_str(i));
+ bch2_btree_node_hash_remove(&c->btree_cache, b);
+ mutex_lock(&c->btree_cache.lock);
+ list_move(&b->list, &c->btree_cache.freeable);
+ mutex_unlock(&c->btree_cache.lock);
+ bch2_btree_root_alloc_fake(c, i, 0);
+ ret = 0;
}
}