md: when a level change reduces the number of devices, remove the excess.
authorNeilBrown <neilb@suse.de>
Mon, 3 Aug 2009 00:59:55 +0000 (10:59 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 3 Aug 2009 00:59:55 +0000 (10:59 +1000)
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>
drivers/md/md.c

index 180949e94a7b2dc2c0a1a09e246204977dfafa15..c194955aecaeb4a284ad35f0779ea66a52ab95d8 100644 (file)
@@ -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));