summaryrefslogtreecommitdiff
path: root/fs/bcachefs/btree_gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/btree_gc.c')
-rw-r--r--fs/bcachefs/btree_gc.c93
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;