diff options
author | NeilBrown <neilb@suse.de> | 2009-08-03 10:59:55 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-08-03 10:59:55 +1000 |
commit | 3a981b03f38dc3b8a69b77cbc679e66c1318a44a (patch) | |
tree | 7f8b0747385a02c793edd7df30d34c4c9c95b1a5 /drivers/md/md.c | |
parent | ac5e7113e74872928844d00085bd47c988f12728 (diff) | |
download | linux-3a981b03f38dc3b8a69b77cbc679e66c1318a44a.tar.gz linux-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>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 7 |
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)); |