diff options
author | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:57 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:57 -0500 |
commit | c19d57980b38a5bb613a898937a1cf85f422fb9b (patch) | |
tree | ddc9f7ae53a4cd0464240ec8c49c03d35823a103 /drivers/md | |
parent | 8c7a2c2bcfaf0ee29c74437a4814d1aa780d6a26 (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.c | 25 |
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)); |