diff options
author | NeilBrown <neilb@suse.de> | 2013-06-24 14:08:41 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-06-24 14:08:41 +1000 |
commit | 6fb8746e4ad9d5be3f2f1e31f1982007646f2258 (patch) | |
tree | e1155e3f1a0ae115afeb7c1ad6c88cd7ac14032a /Grow.c | |
parent | 9030d55ff24b38b5f60ed00f508ecfb7b4307ba0 (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.c | 39 |
1 files changed, 39 insertions, 0 deletions
@@ -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; |