[PATCH V2 3/6] md/raid5: don't leave mddev in an inconsistent state when takeover fails

From: Zizhi Wo

Date: Sun Oct 18 2026 - 21:16:03 EST


From: Zizhi Wo <wozizhi@xxxxxxxxxx>

raid45_takeover_raid0() sets mddev->dev_sectors and resync_offset before
setup_conf(), which can fail. level_store() does not roll those back, so a
failed takeover leaves the running raid0 with the wrong component size and
resync offset.

setup_conf() does not need dev_sectors, so set it and resync_offset only
after setup_conf() succeeds.

Fixes: 54071b3808ee ("md:Add support for Raid0->Raid5 takeover")
Signed-off-by: Zizhi Wo <wozizhi@xxxxxxxxxx>
---
drivers/md/raid5.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index b91545ce090d..55b936830726 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -8881,10 +8881,11 @@ static void raid5_quiesce(struct mddev *mddev, int quiesce)
}

static void *raid45_takeover_raid0(struct mddev *mddev, int level)
{
struct r0conf *raid0_conf = mddev->private;
+ struct r5conf *conf;
sector_t sectors;

/* for raid0 takeover only one zone is supported */
if (raid0_conf->nr_strip_zones > 1) {
pr_warn("md/raid:%s: cannot takeover raid0 with more than one zone.\n",
@@ -8892,20 +8893,24 @@ static void *raid45_takeover_raid0(struct mddev *mddev, int level)
return ERR_PTR(-EINVAL);
}

sectors = raid0_conf->strip_zone[0].zone_end;
sector_div(sectors, raid0_conf->strip_zone[0].nb_dev);
- mddev->dev_sectors = sectors;
mddev->new_level = level;
mddev->new_layout = ALGORITHM_PARITY_N;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->raid_disks += 1;
mddev->delta_disks = 1;
- /* make sure it will be not marked as dirty */
- mddev->resync_offset = MaxSector;

- return setup_conf(mddev);
+ conf = setup_conf(mddev);
+ if (!IS_ERR(conf)) {
+ mddev->dev_sectors = sectors;
+ /* make sure it will be not marked as dirty */
+ mddev->resync_offset = MaxSector;
+ }
+
+ return conf;
}

static void *raid5_takeover_raid1(struct mddev *mddev)
{
int chunksect;
--
2.52.0