diff options
author | NeilBrown <neilb@suse.de> | 2011-12-23 00:17:54 +0100 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-23 00:17:54 +0100 |
commit | c8ab903ea9d7309044910c33dc087418be84f9b5 (patch) | |
tree | 1113f320a71e50bc5ed22b7f6ca0ec1800b37b08 /drivers/md | |
parent | md/raid10: preferentially read from replacement device if possible. (diff) | |
download | linux-c8ab903ea9d7309044910c33dc087418be84f9b5.tar.xz linux-c8ab903ea9d7309044910c33dc087418be84f9b5.zip |
md/raid10: allow removal of failed replacement devices.
Enhance raid10_remove_disk to be able to remove ->replacement
as well as ->rdev
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid10.c | 57 |
1 files changed, 32 insertions, 25 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 5b886218110e..b2c8998e1397 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1429,34 +1429,41 @@ static int raid10_remove_disk(struct mddev *mddev, struct md_rdev *rdev) struct r10conf *conf = mddev->private; int err = 0; int number = rdev->raid_disk; - struct mirror_info *p = conf->mirrors+ number; + struct md_rdev **rdevp; + struct mirror_info *p = conf->mirrors + number; print_conf(conf); - if (rdev == p->rdev) { - if (test_bit(In_sync, &rdev->flags) || - atomic_read(&rdev->nr_pending)) { - err = -EBUSY; - goto abort; - } - /* Only remove faulty devices in recovery - * is not possible. - */ - if (!test_bit(Faulty, &rdev->flags) && - mddev->recovery_disabled != p->recovery_disabled && - enough(conf, -1)) { - 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; - goto abort; - } - err = md_integrity_register(mddev); + 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 faulty devices if recovery + * is not possible. + */ + if (!test_bit(Faulty, &rdev->flags) && + mddev->recovery_disabled != p->recovery_disabled && + enough(conf, -1)) { + err = -EBUSY; + goto abort; } + *rdevp = NULL; + synchronize_rcu(); + if (atomic_read(&rdev->nr_pending)) { + /* lost the race, try later */ + err = -EBUSY; + *rdevp = rdev; + goto abort; + } + err = md_integrity_register(mddev); + abort: print_conf(conf); |