diff options
author | NeilBrown <neilb@cse.unsw.edu.au> | 2005-06-21 20:17:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-21 22:07:42 -0400 |
commit | 6ea9c07c6c6d1c14d9757dd8470dc4c85bbe9f28 (patch) | |
tree | 095cf6a6830902b01896618502f20a2a89f33273 /drivers/md | |
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>
Diffstat (limited to 'drivers/md')
-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 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); |