diff options
author | NeilBrown <neilb@suse.de> | 2011-12-23 03:17:53 +0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-23 03:17:53 +0400 |
commit | 17045f52ac76d9cd1a120e52af5d83b570af4ba8 (patch) | |
tree | 2bbd692eaab68ffa60f3dcf6757752b9b89a7a9b /drivers/md/raid5.c | |
parent | dd054fce88d33da1aa81d018db75b91b102a6959 (diff) | |
download | linux-17045f52ac76d9cd1a120e52af5d83b570af4ba8.tar.xz |
md/raid5: recognise replacements when assembling array.
If a Replacement is seen, file it as such.
If we see two replacements (or two normal devices) for the one slot,
abort.
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index b443cd2459df..c80f8c2471cc 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4847,7 +4847,15 @@ static struct r5conf *setup_conf(struct mddev *mddev) continue; disk = conf->disks + raid_disk; - disk->rdev = rdev; + if (test_bit(Replacement, &rdev->flags)) { + if (disk->replacement) + goto abort; + disk->replacement = rdev; + } else { + if (disk->rdev) + goto abort; + disk->rdev = rdev; + } if (test_bit(In_sync, &rdev->flags)) { char b[BDEVNAME_SIZE]; @@ -4936,6 +4944,7 @@ static int run(struct mddev *mddev) int dirty_parity_disks = 0; struct md_rdev *rdev; sector_t reshape_offset = 0; + int i; if (mddev->recovery_cp != MaxSector) printk(KERN_NOTICE "md/raid:%s: not clean" @@ -5025,12 +5034,25 @@ static int run(struct mddev *mddev) conf->thread = NULL; mddev->private = conf; - /* - * 0 for a fully functional array, 1 or 2 for a degraded array. - */ - list_for_each_entry(rdev, &mddev->disks, same_set) { - if (rdev->raid_disk < 0) + for (i = 0; i < conf->raid_disks && conf->previous_raid_disks; + i++) { + rdev = conf->disks[i].rdev; + if (!rdev && conf->disks[i].replacement) { + /* The replacement is all we have yet */ + rdev = conf->disks[i].replacement; + conf->disks[i].replacement = NULL; + clear_bit(Replacement, &rdev->flags); + conf->disks[i].rdev = rdev; + } + if (!rdev) continue; + if (conf->disks[i].replacement && + conf->reshape_progress != MaxSector) { + /* replacements and reshape simply do not mix. */ + printk(KERN_ERR "md: cannot handle concurrent " + "replacement and reshape.\n"); + goto abort; + } if (test_bit(In_sync, &rdev->flags)) { working_disks++; continue; @@ -5064,6 +5086,9 @@ static int run(struct mddev *mddev) dirty_parity_disks++; } + /* + * 0 for a fully functional array, 1 or 2 for a degraded array. + */ mddev->degraded = calc_degraded(conf); if (has_failed(conf)) { |