md/raid1: prioritize adding disk to 'removed' mirror
authorLi Nan <linan122@huawei.com>
Tue, 27 Jun 2023 01:43:32 +0000 (09:43 +0800)
committerSong Liu <song@kernel.org>
Thu, 27 Jul 2023 07:13:30 +0000 (00:13 -0700)
New disk should be added to "removed" position first instead of to be a
replacement. Commit 6090368abcb4 ("md/raid10: prioritize adding disk to
'removed' mirror") has fixed this issue for raid10. Fix it for raid1 now.

Signed-off-by: Li Nan <linan122@huawei.com>
Reviewed-by: Yu Kuai <yukuai3@huawei.com>
Link: https://lore.kernel.org/r/20230627014332.3810102-1-linan666@huaweicloud.com
Signed-off-by: Song Liu <song@kernel.org>
drivers/md/raid1.c

index 06fa1580501f083bb8c34df63f29f1d23d8ea330..f834d99a36f6dda5e454b0991a00cf91db0744df 100644 (file)
@@ -1764,7 +1764,7 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
 {
        struct r1conf *conf = mddev->private;
        int err = -EEXIST;
-       int mirror = 0;
+       int mirror = 0, repl_slot = -1;
        struct raid1_info *p;
        int first = 0;
        int last = conf->raid_disks - 1;
@@ -1807,17 +1807,21 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
                        break;
                }
                if (test_bit(WantReplacement, &p->rdev->flags) &&
-                   p[conf->raid_disks].rdev == NULL) {
-                       /* Add this device as a replacement */
-                       clear_bit(In_sync, &rdev->flags);
-                       set_bit(Replacement, &rdev->flags);
-                       rdev->raid_disk = mirror;
-                       err = 0;
-                       conf->fullsync = 1;
-                       rcu_assign_pointer(p[conf->raid_disks].rdev, rdev);
-                       break;
-               }
+                   p[conf->raid_disks].rdev == NULL && repl_slot < 0)
+                       repl_slot = mirror;
        }
+
+       if (err && repl_slot >= 0) {
+               /* Add this device as a replacement */
+               p = conf->mirrors + repl_slot;
+               clear_bit(In_sync, &rdev->flags);
+               set_bit(Replacement, &rdev->flags);
+               rdev->raid_disk = repl_slot;
+               err = 0;
+               conf->fullsync = 1;
+               rcu_assign_pointer(p[conf->raid_disks].rdev, rdev);
+       }
+
        print_conf(conf);
        return err;
 }