Linux bcachefs list
 help / color / mirror / Atom feed
* [PATCH] bcachefs: fix gen_valid check in bch2_trigger_pointer() during GC after reconstruct_alloc
@ 2026-09-19 15:43 denuvo
  0 siblings, 0 replies; only message in thread
From: denuvo @ 2026-09-19 15:43 UTC (permalink / raw)
  To: Linux Bcachefs

Hi,

I'd like to bring attention to a fix for a bug in the GC recovery path that occurs after using -o dangerously_reconstruct_alloc (or mounting with no_alloc_info).

Problem:
After bch2_reconstruct_alloc() clears the allocation btree (kill_btree), bch2_gc_alloc_start() initializes ca->buckets_gc with zeroed memory (gen_valid = 0, generation = 0). During the subsequent check_allocations pass, bch2_gc_btrees() walks btree nodes referencing buckets, and bch2_trigger_pointer() (under BTREE_TRIGGER_gc) calls __mark_pointer() without first checking g->gen_valid. This leads bch2_bucket_ref_update() to compare the pointer's generation against an uninitialized bucket generation of 0, gen_after() evaluates true, and a fatal bucket_ref_update error is raised, forcing an emergency read-only remount and aborting recovery.

Even though bch2_reconstruct_alloc() silences BCH_FSCK_ERR_ptr_gen_newer_than_bucket_gen, bucket_ref_update_err() is called with fatal = true, which unconditionally invokes __bch2_inconsistent_error(), so the silencing has no effect here.

Fix:
In bch2_trigger_pointer(), under BTREE_TRIGGER_gc:
1. Check g->gen_valid before calling __mark_pointer().
2. If gen_valid is 0 (as after reconstruct_alloc), set g->gen_valid = 1 and adopt the pointer's generation into g->generation.
3. If gen_valid is 1 but the pointer generation is newer (gen_after), update g->generation to match.

This mirrors the logic already used later in bch2_check_fix_ptr(), but applies it earlier, during the initial GC btree pass, so that check_allocations can complete successfully instead of aborting recovery.

Fixes #910 (https://github.com/koverstreet/bcachefs-tools/issues/910)
PR: https://github.com/koverstreet/bcachefs-tools/pull/926

Happy to address any review feedback.

Thanks,
Filip P.

---

From 667d9c06c1f8fa2eb943804f5067b30a4a9f02b7 Mon Sep 17 00:00:00 2001
From: hotline1337 <denuvo@tuta.io>
Date: Fri, 18 Sep 2026 17:26:19 +0200
Subject: [PATCH] fix: bcachefs: reconstruct_alloc GC trigger gen mismatch
 crash

---
 fs/alloc/buckets.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/fs/alloc/buckets.c b/fs/alloc/buckets.c
index 83e98551f..7917bcb4b 100644
--- a/fs/alloc/buckets.c
+++ b/fs/alloc/buckets.c
@@ -381,6 +381,23 @@ static int bch2_trigger_pointer(struct btree_trans *trans,
 		struct bch_alloc_v4 old, new;
 
 		scoped_guard(bucket_lock, g) {
+			/*
+			 * After reconstruct_alloc the alloc btree is empty so
+			 * gc_buckets start with gen_valid=0 / generation=0.
+			 * Adopt the generation from the pointer we're marking
+			 * so that __mark_pointer → bch2_bucket_ref_update
+			 * doesn't see a gen mismatch and go emergency RO.
+			 *
+			 * Same logic as bch2_check_fix_ptr() in check_data.c,
+			 * but earlier in the recovery sequence.
+			 */
+			if (!g->gen_valid) {
+				g->gen_valid	= 1;
+				g->generation	= p.ptr.generation;
+			} else if (gen_after(p.ptr.generation, g->generation)) {
+				g->generation	= p.ptr.generation;
+			}
+
 			old = new = bucket_m_to_alloc(*g);
 			try(__mark_pointer(trans, ca, k, &p, *sectors, bp.v.data_type, &new, insert));
 			alloc_to_bucket(g, new);
-- 
2.55.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-09-19 15:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-19 15:43 [PATCH] bcachefs: fix gen_valid check in bch2_trigger_pointer() during GC after reconstruct_alloc denuvo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox