diff options
author | NeilBrown <neilb@suse.de> | 2011-12-23 10:17:52 +1100 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-23 10:17:52 +1100 |
commit | 657e3e4d88461a5ab660dd87f8f773f55e748da4 (patch) | |
tree | 1eecf97f8e5eac95cf37b4f28e262a37dd3e116d | |
parent | 14a75d3e07c784c004b4b44b34af996b8e4ac453 (diff) | |
download | linux-657e3e4d88461a5ab660dd87f8f773f55e748da4.tar.gz linux-657e3e4d88461a5ab660dd87f8f773f55e748da4.tar.bz2 linux-657e3e4d88461a5ab660dd87f8f773f55e748da4.zip |
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) struct r5conf *conf = mddev->private; int err = 0; int number = rdev->raid_disk; + struct md_rdev **rdevp; struct disk_info *p = conf->disks + number; print_raid5_conf(conf); - if (rdev == p->rdev) { - if (number >= conf->raid_disks && - conf->reshape_progress == MaxSector) - clear_bit(In_sync, &rdev->flags); + if (rdev == p->rdev) + rdevp = &p->rdev; + else if (rdev == p->replacement) + rdevp = &p->replacement; + else + return 0; - if (test_bit(In_sync, &rdev->flags) || - atomic_read(&rdev->nr_pending)) { - err = -EBUSY; - goto abort; - } - /* Only remove non-faulty devices if recovery - * isn't possible. - */ - if (!test_bit(Faulty, &rdev->flags) && - mddev->recovery_disabled != conf->recovery_disabled && - !has_failed(conf) && - number < conf->raid_disks) { - err = -EBUSY; - goto abort; - } - p->rdev = NULL; - synchronize_rcu(); - if (atomic_read(&rdev->nr_pending)) { - /* lost the race, try later */ - err = -EBUSY; - p->rdev = rdev; - } + if (number >= conf->raid_disks && + conf->reshape_progress == MaxSector) + clear_bit(In_sync, &rdev->flags); + + if (test_bit(In_sync, &rdev->flags) || + atomic_read(&rdev->nr_pending)) { + err = -EBUSY; + goto abort; + } + /* Only remove non-faulty devices if recovery + * isn't possible. + */ + if (!test_bit(Faulty, &rdev->flags) && + mddev->recovery_disabled != conf->recovery_disabled && + !has_failed(conf) && + number < conf->raid_disks) { + err = -EBUSY; + goto abort; + } + *rdevp = NULL; + synchronize_rcu(); + if (atomic_read(&rdev->nr_pending)) { + /* lost the race, try later */ + err = -EBUSY; + *rdevp = rdev; } abort: |