diff options
author | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:52 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:52 -0500 |
commit | 657e3e4d88461a5ab660dd87f8f773f55e748da4 (patch) | |
tree | 1eecf97f8e5eac95cf37b4f28e262a37dd3e116d | |
parent | 14a75d3e07c784c004b4b44b34af996b8e4ac453 (diff) |
md/raid5: allow removal for failed replacement devices.
Enhance raid5_remove_disk to be able to remove ->replacement
as well as ->rdev.
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/md/raid5.c | 58 |
1 files changed, 32 insertions, 26 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2ae63c5b1c25..e5795d39d418 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -5086,36 +5086,42 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev) | |||
5086 | struct r5conf *conf = mddev->private; | 5086 | struct r5conf *conf = mddev->private; |
5087 | int err = 0; | 5087 | int err = 0; |
5088 | int number = rdev->raid_disk; | 5088 | int number = rdev->raid_disk; |
5089 | struct md_rdev **rdevp; | ||
5089 | struct disk_info *p = conf->disks + number; | 5090 | struct disk_info *p = conf->disks + number; |
5090 | 5091 | ||
5091 | print_raid5_conf(conf); | 5092 | print_raid5_conf(conf); |
5092 | if (rdev == p->rdev) { | 5093 | if (rdev == p->rdev) |
5093 | if (number >= conf->raid_disks && | 5094 | rdevp = &p->rdev; |
5094 | conf->reshape_progress == MaxSector) | 5095 | else if (rdev == p->replacement) |
5095 | clear_bit(In_sync, &rdev->flags); | 5096 | rdevp = &p->replacement; |
5097 | else | ||
5098 | return 0; | ||
5096 | 5099 | ||
5097 | if (test_bit(In_sync, &rdev->flags) || | 5100 | if (number >= conf->raid_disks && |
5098 | atomic_read(&rdev->nr_pending)) { | 5101 | conf->reshape_progress == MaxSector) |
5099 | err = -EBUSY; | 5102 | clear_bit(In_sync, &rdev->flags); |
5100 | goto abort; | 5103 | |
5101 | } | 5104 | if (test_bit(In_sync, &rdev->flags) || |
5102 | /* Only remove non-faulty devices if recovery | 5105 | atomic_read(&rdev->nr_pending)) { |
5103 | * isn't possible. | 5106 | err = -EBUSY; |
5104 | */ | 5107 | goto abort; |
5105 | if (!test_bit(Faulty, &rdev->flags) && | 5108 | } |
5106 | mddev->recovery_disabled != conf->recovery_disabled && | 5109 | /* Only remove non-faulty devices if recovery |
5107 | !has_failed(conf) && | 5110 | * isn't possible. |
5108 | number < conf->raid_disks) { | 5111 | */ |
5109 | err = -EBUSY; | 5112 | if (!test_bit(Faulty, &rdev->flags) && |
5110 | goto abort; | 5113 | mddev->recovery_disabled != conf->recovery_disabled && |
5111 | } | 5114 | !has_failed(conf) && |
5112 | p->rdev = NULL; | 5115 | number < conf->raid_disks) { |
5113 | synchronize_rcu(); | 5116 | err = -EBUSY; |
5114 | if (atomic_read(&rdev->nr_pending)) { | 5117 | goto abort; |
5115 | /* lost the race, try later */ | 5118 | } |
5116 | err = -EBUSY; | 5119 | *rdevp = NULL; |
5117 | p->rdev = rdev; | 5120 | synchronize_rcu(); |
5118 | } | 5121 | if (atomic_read(&rdev->nr_pending)) { |
5122 | /* lost the race, try later */ | ||
5123 | err = -EBUSY; | ||
5124 | *rdevp = rdev; | ||
5119 | } | 5125 | } |
5120 | abort: | 5126 | abort: |
5121 | 5127 | ||