diff options
author | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:53 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:53 -0500 |
commit | 17045f52ac76d9cd1a120e52af5d83b570af4ba8 (patch) | |
tree | 2bbd692eaab68ffa60f3dcf6757752b9b89a7a9b /drivers/md/raid5.c | |
parent | dd054fce88d33da1aa81d018db75b91b102a6959 (diff) |
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) | |||
4847 | continue; | 4847 | continue; |
4848 | disk = conf->disks + raid_disk; | 4848 | disk = conf->disks + raid_disk; |
4849 | 4849 | ||
4850 | disk->rdev = rdev; | 4850 | if (test_bit(Replacement, &rdev->flags)) { |
4851 | if (disk->replacement) | ||
4852 | goto abort; | ||
4853 | disk->replacement = rdev; | ||
4854 | } else { | ||
4855 | if (disk->rdev) | ||
4856 | goto abort; | ||
4857 | disk->rdev = rdev; | ||
4858 | } | ||
4851 | 4859 | ||
4852 | if (test_bit(In_sync, &rdev->flags)) { | 4860 | if (test_bit(In_sync, &rdev->flags)) { |
4853 | char b[BDEVNAME_SIZE]; | 4861 | char b[BDEVNAME_SIZE]; |
@@ -4936,6 +4944,7 @@ static int run(struct mddev *mddev) | |||
4936 | int dirty_parity_disks = 0; | 4944 | int dirty_parity_disks = 0; |
4937 | struct md_rdev *rdev; | 4945 | struct md_rdev *rdev; |
4938 | sector_t reshape_offset = 0; | 4946 | sector_t reshape_offset = 0; |
4947 | int i; | ||
4939 | 4948 | ||
4940 | if (mddev->recovery_cp != MaxSector) | 4949 | if (mddev->recovery_cp != MaxSector) |
4941 | printk(KERN_NOTICE "md/raid:%s: not clean" | 4950 | printk(KERN_NOTICE "md/raid:%s: not clean" |
@@ -5025,12 +5034,25 @@ static int run(struct mddev *mddev) | |||
5025 | conf->thread = NULL; | 5034 | conf->thread = NULL; |
5026 | mddev->private = conf; | 5035 | mddev->private = conf; |
5027 | 5036 | ||
5028 | /* | 5037 | for (i = 0; i < conf->raid_disks && conf->previous_raid_disks; |
5029 | * 0 for a fully functional array, 1 or 2 for a degraded array. | 5038 | i++) { |
5030 | */ | 5039 | rdev = conf->disks[i].rdev; |
5031 | list_for_each_entry(rdev, &mddev->disks, same_set) { | 5040 | if (!rdev && conf->disks[i].replacement) { |
5032 | if (rdev->raid_disk < 0) | 5041 | /* The replacement is all we have yet */ |
5042 | rdev = conf->disks[i].replacement; | ||
5043 | conf->disks[i].replacement = NULL; | ||
5044 | clear_bit(Replacement, &rdev->flags); | ||
5045 | conf->disks[i].rdev = rdev; | ||
5046 | } | ||
5047 | if (!rdev) | ||
5033 | continue; | 5048 | continue; |
5049 | if (conf->disks[i].replacement && | ||
5050 | conf->reshape_progress != MaxSector) { | ||
5051 | /* replacements and reshape simply do not mix. */ | ||
5052 | printk(KERN_ERR "md: cannot handle concurrent " | ||
5053 | "replacement and reshape.\n"); | ||
5054 | goto abort; | ||
5055 | } | ||
5034 | if (test_bit(In_sync, &rdev->flags)) { | 5056 | if (test_bit(In_sync, &rdev->flags)) { |
5035 | working_disks++; | 5057 | working_disks++; |
5036 | continue; | 5058 | continue; |
@@ -5064,6 +5086,9 @@ static int run(struct mddev *mddev) | |||
5064 | dirty_parity_disks++; | 5086 | dirty_parity_disks++; |
5065 | } | 5087 | } |
5066 | 5088 | ||
5089 | /* | ||
5090 | * 0 for a fully functional array, 1 or 2 for a degraded array. | ||
5091 | */ | ||
5067 | mddev->degraded = calc_degraded(conf); | 5092 | mddev->degraded = calc_degraded(conf); |
5068 | 5093 | ||
5069 | if (has_failed(conf)) { | 5094 | if (has_failed(conf)) { |