diff options
author | NeilBrown <neilb@cse.unsw.edu.au> | 2005-06-21 17:17:09 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-21 19:07:42 -0700 |
commit | 6ea9c07c6c6d1c14d9757dd8470dc4c85bbe9f28 (patch) | |
tree | 095cf6a6830902b01896618502f20a2a89f33273 | |
parent | 58a606431a704b5c240c1429a5526fac81c9800a (diff) |
[PATCH] md: cause md/raid1 to "repack" working devices when number of drives is changed
i.e. missing or failed drives are moved to the end of the list. The means
a 3 drive md array with the first drive missing can be shrunk to a two
drive array. Currently that isn't possible.
Also, the "last_used" device number might be out-of-range after the number
of devices is reduced, so we set it to 0.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/md/raid1.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 1db5de52d37..4947f599b65 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1349,17 +1349,26 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) * We allocate a new r1bio_pool if we can. * Then raise a device barrier and wait until all IO stops. * Then resize conf->mirrors and swap in the new r1bio pool. + * + * At the same time, we "pack" the devices so that all the missing + * devices have the higher raid_disk numbers. */ mempool_t *newpool, *oldpool; struct pool_info *newpoolinfo; mirror_info_t *newmirrors; conf_t *conf = mddev_to_conf(mddev); + int cnt; - int d; + int d, d2; - for (d= raid_disks; d < conf->raid_disks; d++) - if (conf->mirrors[d].rdev) + if (raid_disks < conf->raid_disks) { + cnt=0; + for (d= 0; d < conf->raid_disks; d++) + if (conf->mirrors[d].rdev) + cnt++; + if (cnt > raid_disks) return -EBUSY; + } newpoolinfo = kmalloc(sizeof(*newpoolinfo), GFP_KERNEL); if (!newpoolinfo) @@ -1390,8 +1399,12 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) /* ok, everything is stopped */ oldpool = conf->r1bio_pool; conf->r1bio_pool = newpool; - for (d=0; d < raid_disks && d < conf->raid_disks; d++) - newmirrors[d] = conf->mirrors[d]; + + for (d=d2=0; d < conf->raid_disks; d++) + if (conf->mirrors[d].rdev) { + conf->mirrors[d].rdev->raid_disk = d2; + newmirrors[d2++].rdev = conf->mirrors[d].rdev; + } kfree(conf->mirrors); conf->mirrors = newmirrors; kfree(conf->poolinfo); @@ -1400,6 +1413,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) mddev->degraded += (raid_disks - conf->raid_disks); conf->raid_disks = mddev->raid_disks = raid_disks; + conf->last_used = 0; /* just make sure it is in-range */ spin_lock_irq(&conf->resync_lock); conf->barrier--; spin_unlock_irq(&conf->resync_lock); |