[PATCH 13/21] bcachefs: rebalance now supports changing checksum type

Kent Overstreet <[email protected]> Sun, 24 Aug 2025 08:37:50 -0400
Newsgroups org.kernel.vger.linux-bcachefs
Message-ID <[email protected]>
We had a user report with a filesystem where data has been written out
with the incorrect checksum type - including no checksum.

That means we need to check/repair such cases, and rebalance is
responsible for handling io path option propagation to extents; thus,
rebalance needs to support checksum type.

Signed-off-by: Kent Overstreet <[email protected]>
---
 fs/bcachefs/rebalance.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c
index 0d1abb0eeb88..a2fb2f1cec70 100644
--- a/fs/bcachefs/rebalance.c
+++ b/fs/bcachefs/rebalance.c
@@ -47,10 +47,12 @@ static void bch2_bkey_needs_rebalance(struct bch_fs *c, struct bkey_s_c k,
 				      struct bch_inode_opts *io_opts,
 				      unsigned *move_ptrs,
 				      unsigned *compress_ptrs,
+				      unsigned *csum_ptrs,
 				      u64 *sectors)
 {
 	*move_ptrs	= 0;
 	*compress_ptrs	= 0;
+	*csum_ptrs	= 0;
 	*sectors	= 0;
 
 	struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
@@ -66,6 +68,9 @@ static void bch2_bkey_needs_rebalance(struct bch_fs *c, struct bkey_s_c k,
 		bch2_compression_opt_to_type(io_opts
 					     ? io_opts->background_compression
 					     : rb_opts->background_compression);
+	unsigned csum_type = bch2_csum_opt_to_type(io_opts
+						   ? io_opts->data_checksum
+						   : rb_opts->data_checksum, true);
 	unsigned target = io_opts
 		? io_opts->background_target
 		: rb_opts->background_target;
@@ -87,6 +92,9 @@ static void bch2_bkey_needs_rebalance(struct bch_fs *c, struct bkey_s_c k,
 			if (p.crc.compression_type != compression_type)
 				*compress_ptrs |= ptr_idx;
 
+			if (p.crc.csum_type != csum_type)
+				*csum_ptrs |= ptr_idx;
+
 			if (target && !bch2_dev_in_target(c, p.ptr.dev, target))
 				*move_ptrs |= ptr_idx;
 		}
@@ -95,11 +103,11 @@ static void bch2_bkey_needs_rebalance(struct bch_fs *c, struct bkey_s_c k,
 	}
 
 	if (unwritten)
-		*compress_ptrs = 0;
+		*compress_ptrs = *csum_ptrs = 0;
 	if (incompressible)
 		*compress_ptrs = 0;
 
-	unsigned rb_ptrs = *move_ptrs | *compress_ptrs;
+	unsigned rb_ptrs = *move_ptrs | *compress_ptrs | *csum_ptrs;
 
 	if (!rb_ptrs)
 		return;
@@ -116,9 +124,10 @@ u64 bch2_bkey_sectors_need_rebalance(struct bch_fs *c, struct bkey_s_c k)
 {
 	unsigned move_ptrs	= 0;
 	unsigned compress_ptrs	= 0;
+	unsigned csum_ptrs	= 0;
 	u64 sectors		= 0;
 
-	bch2_bkey_needs_rebalance(c, k, NULL, &move_ptrs, &compress_ptrs, &sectors);
+	bch2_bkey_needs_rebalance(c, k, NULL, &move_ptrs, &compress_ptrs, &csum_ptrs, &sectors);
 	return sectors;
 }
 
@@ -128,10 +137,11 @@ static unsigned bch2_bkey_ptrs_need_rebalance(struct bch_fs *c,
 {
 	unsigned move_ptrs	= 0;
 	unsigned compress_ptrs	= 0;
+	unsigned csum_ptrs	= 0;
 	u64 sectors		= 0;
 
-	bch2_bkey_needs_rebalance(c, k, opts, &move_ptrs, &compress_ptrs, &sectors);
-	return move_ptrs|compress_ptrs;
+	bch2_bkey_needs_rebalance(c, k, opts, &move_ptrs, &compress_ptrs, &csum_ptrs, &sectors);
+	return move_ptrs|compress_ptrs|csum_ptrs;
 }
 
 static inline bool bkey_should_have_rb_opts(struct bch_fs *c,
@@ -509,9 +519,10 @@ static struct bkey_s_c next_rebalance_extent(struct btree_trans *trans,
 
 		unsigned move_ptrs	= 0;
 		unsigned compress_ptrs	= 0;
+		unsigned csum_ptrs	= 0;
 		u64 sectors		= 0;
 
-		bch2_bkey_needs_rebalance(c, k, opts, &move_ptrs, &compress_ptrs, &sectors);
+		bch2_bkey_needs_rebalance(c, k, opts, &move_ptrs, &compress_ptrs, &csum_ptrs, &sectors);
 
 		if (move_ptrs) {
 			prt_str(&buf, "move=");
@@ -529,6 +540,14 @@ static struct bkey_s_c next_rebalance_extent(struct btree_trans *trans,
 			prt_newline(&buf);
 		}
 
+		if (csum_ptrs) {
+			prt_str(&buf, "csum=");
+			bch2_prt_csum_opt(&buf, opts->data_checksum);
+			prt_str(&buf, " ");
+			bch2_prt_u64_base2(&buf, csum_ptrs);
+			prt_newline(&buf);
+		}
+
 		trace_rebalance_extent(c, buf.buf);
 	}
 	count_event(c, rebalance_extent);
-- 
2.50.1