summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-08-03 10:59:55 +1000
committerGreg Kroah-Hartman <gregkh@suse.de>2009-08-16 14:18:46 -0700
commite5cac86942fcfdca931c219723028207954c2cce (patch)
tree348b107a158d71363a1237fa533a842670a83ce7
parent886aa89355b0034c2325708441801350e16a085e (diff)
md: when a level change reduces the number of devices, remove the excess.
commit 3a981b03f38dc3b8a69b77cbc679e66c1318a44a upstream. 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. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@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 eb1b73f69e00..6021dea894da 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2680,6 +2680,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)
@@ -2759,6 +2760,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));