aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-12-22 18:17:53 -0500
committerNeilBrown <neilb@suse.de>2011-12-22 18:17:53 -0500
commit17045f52ac76d9cd1a120e52af5d83b570af4ba8 (patch)
tree2bbd692eaab68ffa60f3dcf6757752b9b89a7a9b /drivers/md/raid5.c
parentdd054fce88d33da1aa81d018db75b91b102a6959 (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.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index b443cd2459d..c80f8c2471c 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)) {