md/raid10: allow removal of failed replacement devices.
authorNeilBrown <neilb@suse.de>
Thu, 22 Dec 2011 23:17:54 +0000 (10:17 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 22 Dec 2011 23:17:54 +0000 (10:17 +1100)
Enhance raid10_remove_disk to be able to remove ->replacement
as well as ->rdev

Signed-off-by: NeilBrown <neilb@suse.de>
drivers/md/raid10.c

index 5b886218110edfe09ad136005aa9819ca2336b8b..b2c8998e13973229915c0f0438f18115f1b68144 100644 (file)
@@ -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);