diff options
author | NeilBrown <neilb@suse.de> | 2012-07-02 21:46:53 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2012-07-02 21:46:53 -0400 |
commit | 5cfb22a1f83e4f04c0a4df89b60053a077222e2b (patch) | |
tree | 9312c806fb3fb245beb0dd6669569f88a79a8b7d | |
parent | fc448a18ae6219af9a73257b1fbcd009efab4a81 (diff) |
md/raid5: prefer replacing failed devices over want-replacement devices.
If a RAID5 has both a failed device and a device marked as
'WantReplacement', then we should preferentially replace the failed
device.
However the current code replaces whichever is found first.
So split into 2 loops, check fail failed/missing first, and only check
for WantReplacement if nothing is failed or missing.
Reported-by: majianpeng <majianpeng@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/md/raid5.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index d26767246d26..95fcbbf3d6c9 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -5465,10 +5465,9 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) | |||
5465 | if (rdev->saved_raid_disk >= 0 && | 5465 | if (rdev->saved_raid_disk >= 0 && |
5466 | rdev->saved_raid_disk >= first && | 5466 | rdev->saved_raid_disk >= first && |
5467 | conf->disks[rdev->saved_raid_disk].rdev == NULL) | 5467 | conf->disks[rdev->saved_raid_disk].rdev == NULL) |
5468 | disk = rdev->saved_raid_disk; | 5468 | first = rdev->saved_raid_disk; |
5469 | else | 5469 | |
5470 | disk = first; | 5470 | for (disk = first; disk <= last; disk++) { |
5471 | for ( ; disk <= last ; disk++) { | ||
5472 | p = conf->disks + disk; | 5471 | p = conf->disks + disk; |
5473 | if (p->rdev == NULL) { | 5472 | if (p->rdev == NULL) { |
5474 | clear_bit(In_sync, &rdev->flags); | 5473 | clear_bit(In_sync, &rdev->flags); |
@@ -5477,8 +5476,11 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) | |||
5477 | if (rdev->saved_raid_disk != disk) | 5476 | if (rdev->saved_raid_disk != disk) |
5478 | conf->fullsync = 1; | 5477 | conf->fullsync = 1; |
5479 | rcu_assign_pointer(p->rdev, rdev); | 5478 | rcu_assign_pointer(p->rdev, rdev); |
5480 | break; | 5479 | goto out; |
5481 | } | 5480 | } |
5481 | } | ||
5482 | for (disk = first; disk <= last; disk++) { | ||
5483 | p = conf->disks + disk; | ||
5482 | if (test_bit(WantReplacement, &p->rdev->flags) && | 5484 | if (test_bit(WantReplacement, &p->rdev->flags) && |
5483 | p->replacement == NULL) { | 5485 | p->replacement == NULL) { |
5484 | clear_bit(In_sync, &rdev->flags); | 5486 | clear_bit(In_sync, &rdev->flags); |
@@ -5490,6 +5492,7 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) | |||
5490 | break; | 5492 | break; |
5491 | } | 5493 | } |
5492 | } | 5494 | } |
5495 | out: | ||
5493 | print_raid5_conf(conf); | 5496 | print_raid5_conf(conf); |
5494 | return err; | 5497 | return err; |
5495 | } | 5498 | } |