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

From: Zizhi Wo

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


From: Zizhi Wo <wozizhi@xxxxxxxxxx>

raid10_takeover_raid0() sets mddev->resync_offset and dev_sectors 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() needs dev_sectors, so save it and restore it on failure; set
resync_offset only after setup_conf() succeeds.

Fixes: dab8b29248b3 ("md: Add support for Raid0->Raid10 takeover")
Signed-off-by: Zizhi Wo <wozizhi@xxxxxxxxxx>
---
drivers/md/raid10.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 1093c798d9dd..28b258ac5ea7 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -4179,36 +4179,43 @@ static int raid10_resize(struct mddev *mddev, sector_t sectors)

static void *raid10_takeover_raid0(struct mddev *mddev, sector_t size, int devs)
{
struct md_rdev *rdev;
struct r10conf *conf;
+ sector_t old_dev_sectors;

if (mddev->degraded > 0) {
pr_warn("md/raid10:%s: Error: degraded raid0!\n",
mdname(mddev));
return ERR_PTR(-EINVAL);
}
sector_div(size, devs);

+ /* Save for rollback if setup_conf() fails */
+ old_dev_sectors = mddev->dev_sectors;
+
/* Set new parameters */
mddev->new_level = 10;
/* new layout: far_copies = 1, near_copies = 2 */
mddev->new_layout = (1<<8) + 2;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->delta_disks = mddev->raid_disks;
mddev->raid_disks *= 2;
- /* make sure it will be not marked as dirty */
- mddev->resync_offset = MaxSector;
mddev->dev_sectors = size;

conf = setup_conf(mddev);
if (!IS_ERR(conf)) {
+ /* make sure it will be not marked as dirty */
+ mddev->resync_offset = MaxSector;
+
rdev_for_each(rdev, mddev)
if (rdev->raid_disk >= 0) {
rdev->new_raid_disk = rdev->raid_disk * 2;
rdev->sectors = size;
}
+ } else {
+ mddev->dev_sectors = old_dev_sectors;
}

return conf;
}

--
2.52.0