From 9b9209ccb3b5628e26a7e5c1366a5d58ed59a13e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 9 Nov 2011 11:32:08 +1100 Subject: [PATCH] md/raid5: If there is a spare and a replaceable device, start replacement. When attempting to add a spare to a RAID[456] array, also consider adding it as a replacement for a replaceable device. This requires that common md code attempt hot_add even when the array is not formally degraded. Signed-off-by: NeilBrown --- drivers/md/md.c | 34 ++++++++++++++++------------------ drivers/md/raid5.c | 16 ++++++++++++++-- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 7d8271d0c19f..d15643cca767 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7391,25 +7391,23 @@ static int remove_and_add_spares(struct mddev *mddev) } } - if (mddev->degraded) { - list_for_each_entry(rdev, &mddev->disks, same_set) { - if (rdev->raid_disk >= 0 && - !test_bit(In_sync, &rdev->flags) && - !test_bit(Faulty, &rdev->flags)) + list_for_each_entry(rdev, &mddev->disks, same_set) { + if (rdev->raid_disk >= 0 && + !test_bit(In_sync, &rdev->flags) && + !test_bit(Faulty, &rdev->flags)) + spares++; + if (rdev->raid_disk < 0 + && !test_bit(Faulty, &rdev->flags)) { + rdev->recovery_offset = 0; + if (mddev->pers-> + hot_add_disk(mddev, rdev) == 0) { + if (sysfs_link_rdev(mddev, rdev)) + /* failure here is OK */; spares++; - if (rdev->raid_disk < 0 - && !test_bit(Faulty, &rdev->flags)) { - rdev->recovery_offset = 0; - if (mddev->pers-> - hot_add_disk(mddev, rdev) == 0) { - if (sysfs_link_rdev(mddev, rdev)) - /* failure here is OK */; - spares++; - md_new_event(mddev); - set_bit(MD_CHANGE_DEVS, &mddev->flags); - } else - break; - } + md_new_event(mddev); + set_bit(MD_CHANGE_DEVS, &mddev->flags); + } else + break; } } return spares; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 7789e413cafa..78d3115e5770 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5360,8 +5360,9 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) disk = rdev->saved_raid_disk; else disk = first; - for ( ; disk <= last ; disk++) - if ((p=conf->disks + disk)->rdev == NULL) { + for ( ; disk <= last ; disk++) { + p = conf->disks + disk; + if (p->rdev == NULL) { clear_bit(In_sync, &rdev->flags); rdev->raid_disk = disk; err = 0; @@ -5370,6 +5371,17 @@ static int raid5_add_disk(struct mddev *mddev, struct md_rdev *rdev) rcu_assign_pointer(p->rdev, rdev); break; } + if (test_bit(Replaceable, &p->rdev->flags) && + p->replacement == NULL) { + clear_bit(In_sync, &rdev->flags); + set_bit(Replacement, &rdev->flags); + rdev->raid_disk = disk; + err = 0; + conf->fullsync = 1; + rcu_assign_pointer(p->replacement, rdev); + break; + } + } print_raid5_conf(conf); return err; } -- 2.39.5