aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-12-22 18:17:57 -0500
committerNeilBrown <neilb@suse.de>2011-12-22 18:17:57 -0500
commitc19d57980b38a5bb613a898937a1cf85f422fb9b (patch)
treeddc9f7ae53a4cd0464240ec8c49c03d35823a103 /drivers/md
parent8c7a2c2bcfaf0ee29c74437a4814d1aa780d6a26 (diff)
md/raid1: recognise replacements when assembling arrays.
If a Replacement is seen, file it as such. If we see two replacements (or two normal devices) for the one slot, abort. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/raid1.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index f68075189df..6df0c41578a 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2453,14 +2453,20 @@ static struct r1conf *setup_conf(struct mddev *mddev)
2453 2453
2454 conf->poolinfo->mddev = mddev; 2454 conf->poolinfo->mddev = mddev;
2455 2455
2456 err = -EINVAL;
2456 spin_lock_init(&conf->device_lock); 2457 spin_lock_init(&conf->device_lock);
2457 list_for_each_entry(rdev, &mddev->disks, same_set) { 2458 list_for_each_entry(rdev, &mddev->disks, same_set) {
2458 int disk_idx = rdev->raid_disk; 2459 int disk_idx = rdev->raid_disk;
2459 if (disk_idx >= mddev->raid_disks 2460 if (disk_idx >= mddev->raid_disks
2460 || disk_idx < 0) 2461 || disk_idx < 0)
2461 continue; 2462 continue;
2462 disk = conf->mirrors + disk_idx; 2463 if (test_bit(Replacement, &rdev->flags))
2464 disk = conf->mirrors + conf->raid_disks + disk_idx;
2465 else
2466 disk = conf->mirrors + disk_idx;
2463 2467
2468 if (disk->rdev)
2469 goto abort;
2464 disk->rdev = rdev; 2470 disk->rdev = rdev;
2465 2471
2466 disk->head_position = 0; 2472 disk->head_position = 0;
@@ -2476,11 +2482,27 @@ static struct r1conf *setup_conf(struct mddev *mddev)
2476 conf->pending_count = 0; 2482 conf->pending_count = 0;
2477 conf->recovery_disabled = mddev->recovery_disabled - 1; 2483 conf->recovery_disabled = mddev->recovery_disabled - 1;
2478 2484
2485 err = -EIO;
2479 conf->last_used = -1; 2486 conf->last_used = -1;
2480 for (i = 0; i < conf->raid_disks * 2; i++) { 2487 for (i = 0; i < conf->raid_disks * 2; i++) {
2481 2488
2482 disk = conf->mirrors + i; 2489 disk = conf->mirrors + i;
2483 2490
2491 if (i < conf->raid_disks &&
2492 disk[conf->raid_disks].rdev) {
2493 /* This slot has a replacement. */
2494 if (!disk->rdev) {
2495 /* No original, just make the replacement
2496 * a recovering spare
2497 */
2498 disk->rdev =
2499 disk[conf->raid_disks].rdev;
2500 disk[conf->raid_disks].rdev = NULL;
2501 } else if (!test_bit(In_sync, &disk->rdev->flags))
2502 /* Original is not in_sync - bad */
2503 goto abort;
2504 }
2505
2484 if (!disk->rdev || 2506 if (!disk->rdev ||
2485 !test_bit(In_sync, &disk->rdev->flags)) { 2507 !test_bit(In_sync, &disk->rdev->flags)) {
2486 disk->head_position = 0; 2508 disk->head_position = 0;
@@ -2494,7 +2516,6 @@ static struct r1conf *setup_conf(struct mddev *mddev)
2494 conf->last_used = i; 2516 conf->last_used = i;
2495 } 2517 }
2496 2518
2497 err = -EIO;
2498 if (conf->last_used < 0) { 2519 if (conf->last_used < 0) {
2499 printk(KERN_ERR "md/raid1:%s: no operational mirrors\n", 2520 printk(KERN_ERR "md/raid1:%s: no operational mirrors\n",
2500 mdname(mddev)); 2521 mdname(mddev));