* [PATCH] bcachefs: btree_id_can_reconstruct(), btree_id_recovers_from_scan()
@ 2025-08-04 17:12 Kent Overstreet
0 siblings, 0 replies; only message in thread
From: Kent Overstreet @ 2025-08-04 17:12 UTC (permalink / raw)
To: linux-bcachefs; +Cc: Kent Overstreet
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 <kent.overstreet@linux.dev>
---
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
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2025-08-04 17:12 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-04 17:12 [PATCH] bcachefs: btree_id_can_reconstruct(), btree_id_recovers_from_scan() Kent Overstreet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).