Reshape needs to specify a backup file when it can't update data offset of member disks. For this situation, first, it starts reshape and then it kicks off mdadm-grow-continue service which does backup job and monitors the reshape process. The service is a new process, so it needs to read superblock from member disks to get information. But in the first step, it doesn't update new level in superblock. So in the second step, the new level that systemd service reads from superblock is wrong. It can't change to the right new level after reshape finishes. This interface is used to update new level during reshape progress. Reproduce steps: mdadm -CR /dev/md0 -l6 -n4 /dev/loop[0-3] mdadm --wait /dev/md0 mdadm /dev/md0 --grow -l5 --backup=backup cat /proc/mdstat Personalities : [raid6] [raid5] [raid4] [raid0] [raid1] [raid10] md0 : active raid6 loop3[3] loop2[2] loop1[1] loop0[0] Test case 07changelevels from mdadm regression tests can trigger this problem. Signed-off-by: Xiao Ni <xni@xxxxxxxxxx> --- V3: explain more about the root cause V2: add detail about test information drivers/md/md.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/md/md.c b/drivers/md/md.c index d3a837506a36..3c354e7a7825 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4141,6 +4141,34 @@ level_store(struct mddev *mddev, const char *buf, size_t len) static struct md_sysfs_entry md_level = __ATTR(level, S_IRUGO|S_IWUSR, level_show, level_store); +static ssize_t +new_level_show(struct mddev *mddev, char *page) +{ + return sprintf(page, "%d\n", mddev->new_level); +} + +static ssize_t +new_level_store(struct mddev *mddev, const char *buf, size_t len) +{ + unsigned int n; + int err; + + err = kstrtouint(buf, 10, &n); + if (err < 0) + return err; + err = mddev_lock(mddev); + if (err) + return err; + + mddev->new_level = n; + md_update_sb(mddev, 1); + + mddev_unlock(mddev); + return len; +} +static struct md_sysfs_entry md_new_level = +__ATTR(new_level, 0664, new_level_show, new_level_store); + static ssize_t layout_show(struct mddev *mddev, char *page) { @@ -5666,6 +5694,7 @@ __ATTR(serialize_policy, S_IRUGO | S_IWUSR, serialize_policy_show, static struct attribute *md_default_attrs[] = { &md_level.attr, + &md_new_level.attr, &md_layout.attr, &md_raid_disks.attr, &md_uuid.attr, -- 2.32.0 (Apple Git-132)