diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2024-03-16 22:45:30 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2024-03-22 17:03:20 -0400 |
commit | fca84f2f5836fe34b43514a75cff9162bdd1c5c1 (patch) | |
tree | 6abf9b86c115a3e50f54b78775ce4b1bab65a777 | |
parent | ff14df27df54781c9516df246e1ba88c7b6fd587 (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.c | 15 |
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; } } |