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 | |
| 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>
| -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 f68075189df8..6df0c41578af 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)); |
