From: NeilBrown Date: Mon, 24 Jun 2013 04:08:41 +0000 (+1000) Subject: Grow: remove excess drives when converting to RAID0. X-Git-Tag: mdadm-3.3-rc1~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6fb8746e4ad9d5be3f2f1e31f1982007646f2258;p=thirdparty%2Fmdadm.git Grow: remove excess drives when converting to RAID0. When converting to RAID0, all spares and non-data drives need to be removed first. It is possible that the first HOT_REMOVE_DISK will fail because the personality hasn't let go of it yet, so retry a few times. Signed-off-by: NeilBrown --- diff --git a/Grow.c b/Grow.c index 8c4bd412..1dec2641 100644 --- a/Grow.c +++ b/Grow.c @@ -2769,6 +2769,45 @@ static int reshape_array(char *container, int fd, char *devname, if (c == NULL) goto release; + if (reshape.level == 0 && + (array.level >= 4 && array.level <= 6)) { + /* To convert to RAID0 we need to fail and + * remove any non-data devices. */ + int found = 0; + if (array.level == 5 && + array.layout != ALGORITHM_PARITY_N) + goto release; + if (array.level == 6 && + array.layout != ALGORITHM_PARITY_N_6) + goto release; + sysfs_set_str(info, NULL,"sync_action", "idle"); + for (d = 0; + d < MAX_DISKS && found < array.nr_disks; + d++) { + int cnt; + mdu_disk_info_t disk; + disk.number = d; + if (ioctl(fd, GET_DISK_INFO, &disk) < 0) + continue; + if (disk.major == 0 && disk.minor == 0) + continue; + found++; + if ((disk.state & (1 << MD_DISK_ACTIVE)) + && disk.raid_disk < reshape.after.data_disks) + /* keep this */ + continue; + ioctl(fd, SET_DISK_FAULTY, + makedev(disk.major, disk.minor)); + cnt = 5; + while (ioctl(fd, HOT_REMOVE_DISK, + makedev(disk.major, disk.minor)) < 0 + && errno == EBUSY + && cnt--) { + usleep(10000); + } + } + } + err = sysfs_set_str(info, NULL, "level", c); if (err) { err = errno;