summaryrefslogtreecommitdiff
path: root/Grow.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2013-06-24 14:08:41 +1000
committerNeilBrown <neilb@suse.de>2013-06-24 14:08:41 +1000
commit6fb8746e4ad9d5be3f2f1e31f1982007646f2258 (patch)
treee1155e3f1a0ae115afeb7c1ad6c88cd7ac14032a /Grow.c
parent9030d55ff24b38b5f60ed00f508ecfb7b4307ba0 (diff)
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 <neilb@suse.de>
Diffstat (limited to 'Grow.c')
-rw-r--r--Grow.c39
1 files changed, 39 insertions, 0 deletions
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;