]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
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)
committerGreg Kroah-Hartman <gregkh@suse.de>
Sun, 16 Aug 2009 21:18:46 +0000 (14:18 -0700)
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>
drivers/md/md.c

index eb1b73f69e00c8f68578786771265510f103065b..6021dea894da5b2e87506986e8c11a6ec57105a5 100644 (file)
@@ -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));