From: NeilBrown Date: Wed, 9 Nov 2011 00:32:12 +0000 (+1100) Subject: md/raid1: handle activation of replacement device when recovery completes. X-Git-Tag: next-20111110~17^2~3 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=775bb42d0379fcf3dd2afedd3dbc488cf5a8d5f9;p=karo-tx-linux.git md/raid1: handle activation of replacement device when recovery completes. When recovery completes ->spare_active is called. This checks if the replacement is ready and if so it fails the original. Signed-off-by: NeilBrown --- diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 094819e026ac..b02217830be3 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1264,6 +1264,25 @@ static int raid1_spare_active(struct mddev *mddev) */ for (i = 0; i < conf->raid_disks; i++) { struct md_rdev *rdev = conf->mirrors[i].rdev; + struct md_rdev *repl = conf->mirrors[conf->raid_disks + i].rdev; + if (repl + && repl->recovery_offset == MaxSector + && !test_bit(Faulty, &repl->flags) + && !test_and_set_bit(In_sync, &repl->flags)) { + /* replacement has just become active */ + if (!rdev || + !test_and_clear_bit(In_sync, &rdev->flags)) + count++; + if (rdev) { + /* Replaced device not technically + * faulty, but we need to be sure + * it gets removed and never re-added + */ + set_bit(Faulty, &rdev->flags); + sysfs_notify_dirent_safe( + rdev->sysfs_state); + } + } if (rdev && !test_bit(Faulty, &rdev->flags) && !test_and_set_bit(In_sync, &rdev->flags)) { @@ -1361,10 +1380,21 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev) err = -EBUSY; p->rdev = rdev; goto abort; - } else { - clear_bit(Replacement, &rdev->flags); + } else if (conf->mirrors[conf->raid_disks + number].rdev) { + /* We just removed a device that is being replaced. + * Move down the replacement. We drain all IO before + * doing this to avoid confusion. + */ + struct md_rdev *repl = + conf->mirrors[conf->raid_disks + number].rdev; + raise_barrier(conf); + clear_bit(Replacement, &repl->flags); + p->rdev = repl; + conf->mirrors[conf->raid_disks + number].rdev = NULL; + lower_barrier(conf); + clear_bit(Replaceable, &rdev->flags); + } else clear_bit(Replaceable, &rdev->flags); - } err = md_integrity_register(mddev); } abort: