aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid1.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@cse.unsw.edu.au>2005-06-21 20:17:09 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-21 22:07:42 -0400
commit6ea9c07c6c6d1c14d9757dd8470dc4c85bbe9f28 (patch)
tree095cf6a6830902b01896618502f20a2a89f33273 /drivers/md/raid1.c
parent58a606431a704b5c240c1429a5526fac81c9800a (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>
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r--drivers/md/raid1.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 1db5de52d376..4947f599b652 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)
1349 * We allocate a new r1bio_pool if we can. 1349 * We allocate a new r1bio_pool if we can.
1350 * Then raise a device barrier and wait until all IO stops. 1350 * Then raise a device barrier and wait until all IO stops.
1351 * Then resize conf->mirrors and swap in the new r1bio pool. 1351 * Then resize conf->mirrors and swap in the new r1bio pool.
1352 *
1353 * At the same time, we "pack" the devices so that all the missing
1354 * devices have the higher raid_disk numbers.
1352 */ 1355 */
1353 mempool_t *newpool, *oldpool; 1356 mempool_t *newpool, *oldpool;
1354 struct pool_info *newpoolinfo; 1357 struct pool_info *newpoolinfo;
1355 mirror_info_t *newmirrors; 1358 mirror_info_t *newmirrors;
1356 conf_t *conf = mddev_to_conf(mddev); 1359 conf_t *conf = mddev_to_conf(mddev);
1360 int cnt;
1357 1361
1358 int d; 1362 int d, d2;
1359 1363
1360 for (d= raid_disks; d < conf->raid_disks; d++) 1364 if (raid_disks < conf->raid_disks) {
1361 if (conf->mirrors[d].rdev) 1365 cnt=0;
1366 for (d= 0; d < conf->raid_disks; d++)
1367 if (conf->mirrors[d].rdev)
1368 cnt++;
1369 if (cnt > raid_disks)
1362 return -EBUSY; 1370 return -EBUSY;
1371 }
1363 1372
1364 newpoolinfo = kmalloc(sizeof(*newpoolinfo), GFP_KERNEL); 1373 newpoolinfo = kmalloc(sizeof(*newpoolinfo), GFP_KERNEL);
1365 if (!newpoolinfo) 1374 if (!newpoolinfo)
@@ -1390,8 +1399,12 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
1390 /* ok, everything is stopped */ 1399 /* ok, everything is stopped */
1391 oldpool = conf->r1bio_pool; 1400 oldpool = conf->r1bio_pool;
1392 conf->r1bio_pool = newpool; 1401 conf->r1bio_pool = newpool;
1393 for (d=0; d < raid_disks && d < conf->raid_disks; d++) 1402
1394 newmirrors[d] = conf->mirrors[d]; 1403 for (d=d2=0; d < conf->raid_disks; d++)
1404 if (conf->mirrors[d].rdev) {
1405 conf->mirrors[d].rdev->raid_disk = d2;
1406 newmirrors[d2++].rdev = conf->mirrors[d].rdev;
1407 }
1395 kfree(conf->mirrors); 1408 kfree(conf->mirrors);
1396 conf->mirrors = newmirrors; 1409 conf->mirrors = newmirrors;
1397 kfree(conf->poolinfo); 1410 kfree(conf->poolinfo);
@@ -1400,6 +1413,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
1400 mddev->degraded += (raid_disks - conf->raid_disks); 1413 mddev->degraded += (raid_disks - conf->raid_disks);
1401 conf->raid_disks = mddev->raid_disks = raid_disks; 1414 conf->raid_disks = mddev->raid_disks = raid_disks;
1402 1415
1416 conf->last_used = 0; /* just make sure it is in-range */
1403 spin_lock_irq(&conf->resync_lock); 1417 spin_lock_irq(&conf->resync_lock);
1404 conf->barrier--; 1418 conf->barrier--;
1405 spin_unlock_irq(&conf->resync_lock); 1419 spin_unlock_irq(&conf->resync_lock);