From: NeilBrown Date: Wed, 22 Jun 2005 00:17:09 +0000 (-0700) Subject: [PATCH] md: cause md/raid1 to "repack" working devices when number of drives is changed X-Git-Tag: v2.6.13-rc1~68^2~582^2~26 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ea9c07c6c6d1c14d9757dd8470dc4c85bbe9f28;p=linux-2.6 [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 Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 1db5de52d3..4947f599b6 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);