[PATCH v4 1/3] md/raid5: freeze and interrupt reshape when handling failed reshape
From: Doug V Johnson
Date: Fri Oct 16 2026 - 00:26:19 EST
Set the reshape freeze flag to prevent automatic reshape resumption
and interrupt the current reshape with md_sync_error() so that a
reshape always stops no matter how the failed reshape is triggered.
Previously, if there were no faulty or out of sync devices but there
was an unrecoverable read, the reshape continued and was not cancelled
after handle_failed_reshape(). This caused some data corruption as
block writes were cancelled but the reshape nonetheless continued.
Prior to Chen's fix, the kernel would deadlock with a failed stripe
read. That case also caused some data corruption, so Chen's patch
did not introduce corruption in this case.
An example test case showing how this happened before this fix is
demonstrated by the following:
Simplified example (schematic logical sector numbers):
1. Before reshape, destination D contains data for logical 20-27.
The new geometry will use D for logical 100-107.
2. Inject bad-block metadata on enough members that the old source
stripe cannot be reconstructed. Logical sector 100 now returns
a read error; sectors 101-107 are still readable.
3. Reshape tries to read the source block for logical 100-107.
The bad-block records prevent a successful read/reconstruction.
Failure cleanup cancels the destination write:
Source: logical 100-107 --X--> destination D
still contains data for 20-27
4. Without interruption, reshape continues and completes.
The new mapping now sends reads of logical 100-107 to D.
5. Reading logical 100-107 succeeds, but returns data for 20-27.
Previously readable sectors 101-107 now return wrong data.
Code that injects bad blocks to demonstrate this problem before and
after Chen's fix as well as after this patch can be found here:
Link: https://github.com/dougvj/md-raid-reshape-badblock-corruption-test
Fixes: 788e4139463f ("md/raid5: fix reshape deadlock while failed devices more than max degraded")
Link: https://patch.msgid.link/20260624075824.2601110-1-chencheng@xxxxxxxxx
Assisted-by: LLM
Signed-off-by: Doug V Johnson <me@xxxxxxxxx>
---
drivers/md/raid5.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index b91545ce090d..86ea65559576 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3773,6 +3773,10 @@ static void handle_failed_reshape(struct r5conf *conf, struct stripe_head *sh,
bool was_expanding = test_and_clear_bit(STRIPE_EXPANDING, &sh->state);
bool was_ready = test_and_clear_bit(STRIPE_EXPAND_READY, &sh->state);
+ /* Freeze reshaping to prevent data loss */
+ set_bit(MD_RECOVERY_FROZEN, &conf->mddev->recovery);
+ md_sync_error(conf->mddev);
+
if (was_expanding || was_ready) {
atomic_dec(&conf->reshape_stripes);
wake_up(&conf->wait_for_reshape);
--
2.54.0