diff options
author | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:54 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:54 -0500 |
commit | c8ab903ea9d7309044910c33dc087418be84f9b5 (patch) | |
tree | 1113f320a71e50bc5ed22b7f6ca0ec1800b37b08 /drivers | |
parent | abbf098e6e1e23d5d247b9eaaf325e67f67b0328 (diff) |
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')
-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) | |||
1429 | struct r10conf *conf = mddev->private; | 1429 | struct r10conf *conf = mddev->private; |
1430 | int err = 0; | 1430 | int err = 0; |
1431 | int number = rdev->raid_disk; | 1431 | int number = rdev->raid_disk; |
1432 | struct mirror_info *p = conf->mirrors+ number; | 1432 | struct md_rdev **rdevp; |
1433 | struct mirror_info *p = conf->mirrors + number; | ||
1433 | 1434 | ||
1434 | print_conf(conf); | 1435 | print_conf(conf); |
1435 | if (rdev == p->rdev) { | 1436 | if (rdev == p->rdev) |
1436 | if (test_bit(In_sync, &rdev->flags) || | 1437 | rdevp = &p->rdev; |
1437 | atomic_read(&rdev->nr_pending)) { | 1438 | else if (rdev == p->replacement) |
1438 | err = -EBUSY; | 1439 | rdevp = &p->replacement; |
1439 | goto abort; | 1440 | else |
1440 | } | 1441 | return 0; |
1441 | /* Only remove faulty devices in recovery | 1442 | |
1442 | * is not possible. | 1443 | if (test_bit(In_sync, &rdev->flags) || |
1443 | */ | 1444 | atomic_read(&rdev->nr_pending)) { |
1444 | if (!test_bit(Faulty, &rdev->flags) && | 1445 | err = -EBUSY; |
1445 | mddev->recovery_disabled != p->recovery_disabled && | 1446 | goto abort; |
1446 | enough(conf, -1)) { | 1447 | } |
1447 | err = -EBUSY; | 1448 | /* Only remove faulty devices if recovery |
1448 | goto abort; | 1449 | * is not possible. |
1449 | } | 1450 | */ |
1450 | p->rdev = NULL; | 1451 | if (!test_bit(Faulty, &rdev->flags) && |
1451 | synchronize_rcu(); | 1452 | mddev->recovery_disabled != p->recovery_disabled && |
1452 | if (atomic_read(&rdev->nr_pending)) { | 1453 | enough(conf, -1)) { |
1453 | /* lost the race, try later */ | 1454 | err = -EBUSY; |
1454 | err = -EBUSY; | 1455 | goto abort; |
1455 | p->rdev = rdev; | ||
1456 | goto abort; | ||
1457 | } | ||
1458 | err = md_integrity_register(mddev); | ||
1459 | } | 1456 | } |
1457 | *rdevp = NULL; | ||
1458 | synchronize_rcu(); | ||
1459 | if (atomic_read(&rdev->nr_pending)) { | ||
1460 | /* lost the race, try later */ | ||
1461 | err = -EBUSY; | ||
1462 | *rdevp = rdev; | ||
1463 | goto abort; | ||
1464 | } | ||
1465 | err = md_integrity_register(mddev); | ||
1466 | |||
1460 | abort: | 1467 | abort: |
1461 | 1468 | ||
1462 | print_conf(conf); | 1469 | print_conf(conf); |