summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-08-03 04:59:55 +0400
committerNeilBrown <neilb@suse.de>2009-08-03 04:59:55 +0400
commit3a981b03f38dc3b8a69b77cbc679e66c1318a44a (patch)
tree7f8b0747385a02c793edd7df30d34c4c9c95b1a5
parentac5e7113e74872928844d00085bd47c988f12728 (diff)
downloadlinux-3a981b03f38dc3b8a69b77cbc679e66c1318a44a.tar.xz
md: when a level change reduces the number of devices, remove the excess.
When an array is changed from RAID6 to RAID5, fewer drives are needed. So any device that is made superfluous by the level conversion must be marked as not-active. For the RAID6->RAID5 conversion, this will be a drive which only has 'Q' blocks on it. Cc: stable@kernel.org Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--drivers/md/md.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 180949e94a7b..c194955aecae 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2695,6 +2695,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
ssize_t rv = len;
struct mdk_personality *pers;
void *priv;
+ mdk_rdev_t *rdev;
if (mddev->pers == NULL) {
if (len == 0)
@@ -2774,6 +2775,12 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
mddev_suspend(mddev);
mddev->pers->stop(mddev);
module_put(mddev->pers->owner);
+ /* Invalidate devices that are now superfluous */
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (rdev->raid_disk >= mddev->raid_disks) {
+ rdev->raid_disk = -1;
+ clear_bit(In_sync, &rdev->flags);
+ }
mddev->pers = pers;
mddev->private = priv;
strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));