diff options
Diffstat (limited to 'fs/bcachefs/btree_gc.c')
-rw-r--r-- | fs/bcachefs/btree_gc.c | 93 |
1 files changed, 41 insertions, 52 deletions
diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index 6b91649688da..43f294284d57 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -44,27 +44,6 @@ #include <linux/rcupdate.h> #include <linux/sched/task.h> -/* - * Returns true if it's a btree we can easily reconstruct, or otherwise won't - * cause data loss if it's missing: - */ -static bool btree_id_important(enum btree_id btree) -{ - if (btree_id_is_alloc(btree)) - return false; - - switch (btree) { - case BTREE_ID_quotas: - case BTREE_ID_snapshot_trees: - case BTREE_ID_logged_ops: - case BTREE_ID_rebalance_work: - case BTREE_ID_subvolume_children: - return false; - default: - return true; - } -} - static const char * const bch2_gc_phase_strs[] = { #define x(n) #n, GC_PHASES() @@ -377,7 +356,7 @@ again: bch2_btree_and_journal_iter_init_node_iter(trans, &iter, b); iter.prefetch = true; - while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) { + while ((k = bch2_btree_and_journal_iter_peek(c, &iter)).k) { BUG_ON(bpos_lt(k.k->p, b->data->min_key)); BUG_ON(bpos_gt(k.k->p, b->data->max_key)); @@ -491,7 +470,7 @@ again: bch2_btree_and_journal_iter_init_node_iter(trans, &iter, b); iter.prefetch = true; - while ((k = bch2_btree_and_journal_iter_peek(&iter)).k) { + while ((k = bch2_btree_and_journal_iter_peek(c, &iter)).k) { bch2_bkey_buf_reassemble(&cur_k, c, k); bch2_btree_and_journal_iter_advance(&iter); @@ -557,45 +536,55 @@ fsck_err: return ret; } -static int bch2_check_root(struct btree_trans *trans, enum btree_id btree, +static int bch2_topology_check_root(struct btree_trans *trans, enum btree_id btree, bool *reconstructed_root) { struct bch_fs *c = trans->c; struct btree_root *r = bch2_btree_id_root(c, btree); - CLASS(printbuf, buf)(); - int ret = 0; - - bch2_btree_id_to_text(&buf, btree); - if (r->error) { - bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf); + if (!r->error) + return 0; - ret = bch2_btree_has_scanned_nodes(c, btree); - if (ret < 0) - goto err; + CLASS(printbuf, buf)(); + int ret = 0; - if (!ret) { - __fsck_err(trans, - FSCK_CAN_FIX|(!btree_id_important(btree) ? FSCK_AUTOFIX : 0), - btree_root_unreadable_and_scan_found_nothing, - "no nodes found for btree %s, continue?", buf.buf); + if (!btree_id_recovers_from_scan(btree)) { + r->alive = false; + r->error = 0; + bch2_btree_root_alloc_fake_trans(trans, btree, 0); + ret = bch2_btree_lost_data(c, &buf, btree); + bch2_print_str(c, KERN_NOTICE, buf.buf); + goto out; + } - r->alive = false; - r->error = 0; - bch2_btree_root_alloc_fake_trans(trans, btree, 0); - } else { - r->alive = false; - r->error = 0; - bch2_btree_root_alloc_fake_trans(trans, btree, 1); + bch2_btree_id_to_text(&buf, btree); + bch_info(c, "btree root %s unreadable, must recover from scan", buf.buf); - bch2_shoot_down_journal_keys(c, btree, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX); - ret = bch2_get_scanned_nodes(c, btree, 0, POS_MIN, SPOS_MAX); - if (ret) - return ret; - } + ret = bch2_btree_has_scanned_nodes(c, btree); + if (ret < 0) + goto err; - *reconstructed_root = true; + if (!ret) { + __fsck_err(trans, + FSCK_CAN_FIX|(btree_id_can_reconstruct(btree) ? FSCK_AUTOFIX : 0), + btree_root_unreadable_and_scan_found_nothing, + "no nodes found for btree %s, continue?", buf.buf); + + r->alive = false; + r->error = 0; + bch2_btree_root_alloc_fake_trans(trans, btree, 0); + } else { + r->alive = false; + r->error = 0; + bch2_btree_root_alloc_fake_trans(trans, btree, 1); + + bch2_shoot_down_journal_keys(c, btree, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX); + ret = bch2_get_scanned_nodes(c, btree, 0, POS_MIN, SPOS_MAX); + if (ret) + return ret; } +out: + *reconstructed_root = true; err: fsck_err: bch_err_fn(c, ret); @@ -613,7 +602,7 @@ int bch2_check_topology(struct bch_fs *c) for (unsigned i = 0; i < btree_id_nr_alive(c) && !ret; i++) { bool reconstructed_root = false; recover: - ret = lockrestart_do(trans, bch2_check_root(trans, i, &reconstructed_root)); + ret = lockrestart_do(trans, bch2_topology_check_root(trans, i, &reconstructed_root)); if (ret) break; |