Add new helpers to clarify (and fix) repair strategies for different btrees, and kill incorrect btree_id_is_alloc() use - it's not for deciding how to repair.
btree node scan was incorrectly skipping BTREE_ID_alloc: while we can reconstruct this one from scratch, it will fail by OOM on huge filesystems, it's better to try btree node scan first Signed-off-by: Kent Overstreet <[email protected]> --- fs/bcachefs/bcachefs_format.h | 32 ++++++++++++++++++++++++++++++-- fs/bcachefs/btree_gc.c | 23 +---------------------- fs/bcachefs/btree_node_scan.c | 4 ++-- fs/bcachefs/recovery.c | 2 +- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index a8f59522e258..19961b4f30b8 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -1438,9 +1438,9 @@ enum btree_id { */ #define BTREE_ID_NR_MAX 63 -static inline bool btree_id_is_alloc(enum btree_id id) +static inline bool btree_id_is_alloc(enum btree_id btree) { - switch (id) { + switch (btree) { case BTREE_ID_alloc: case BTREE_ID_backpointers: case BTREE_ID_need_discard: @@ -1454,6 +1454,34 @@ static inline bool btree_id_is_alloc(enum btree_id id) } } +/* We can reconstruct these btrees from information in other btrees */ +static inline bool btree_id_can_reconstruct(enum btree_id btree) +{ + if (btree_id_is_alloc(btree)) + return true; + + switch (btree) { + case BTREE_ID_snapshot_trees: + case BTREE_ID_deleted_inodes: + case BTREE_ID_logged_ops: + case BTREE_ID_rebalance_work: + case BTREE_ID_subvolume_children: + return true; + default: + return false; + } +} + +/* + * We can reconstruct BTREE_ID_alloc, but reconstucting it from scratch is not + * so cheap and OOMs on huge filesystems (until we have online + * check_allocations) + */ +static inline bool btree_id_recovers_from_scan(enum btree_id btree) +{ + return btree == BTREE_ID_alloc || !btree_id_can_reconstruct(btree); +} + #define BTREE_MAX_DEPTH 4U /* Btree nodes */ diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index 6b91649688da..cbf567679a85 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() @@ -576,7 +555,7 @@ static int bch2_check_root(struct btree_trans *trans, enum btree_id btree, if (!ret) { __fsck_err(trans, - FSCK_CAN_FIX|(!btree_id_important(btree) ? FSCK_AUTOFIX : 0), + 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); diff --git a/fs/bcachefs/btree_node_scan.c b/fs/bcachefs/btree_node_scan.c index 4b7b5ca74ba1..6b747c053e91 100644 --- a/fs/bcachefs/btree_node_scan.c +++ b/fs/bcachefs/btree_node_scan.c @@ -149,7 +149,7 @@ static void try_read_btree_node(struct find_btree_nodes *f, struct bch_dev *ca, bch2_encrypt(c, BSET_CSUM_TYPE(&bn->keys), nonce, &bn->flags, bytes); } - if (btree_id_is_alloc(BTREE_NODE_ID(bn))) + if (btree_id_can_reconstruct(BTREE_NODE_ID(bn))) return; if (BTREE_NODE_LEVEL(bn) >= BTREE_MAX_DEPTH) @@ -534,7 +534,7 @@ int bch2_btree_has_scanned_nodes(struct bch_fs *c, enum btree_id btree) int bch2_get_scanned_nodes(struct bch_fs *c, enum btree_id btree, unsigned level, struct bpos node_min, struct bpos node_max) { - if (btree_id_is_alloc(btree)) + if (btree_id_recovers_from_scan(btree)) return 0; struct find_btree_nodes *f = &c->found_btree_nodes; diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 21aa2edb13ac..29e81f96db0f 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -607,7 +607,7 @@ static int read_btree_roots(struct bch_fs *c) c, btree_root_read_error, "error reading btree root %s: %s", buf.buf, bch2_err_str(ret))) { - if (btree_id_is_alloc(i)) + if (btree_id_can_reconstruct(i)) r->error = 0; ret = 0; } -- 2.50.1
