diff options
author | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:57 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-12-22 18:17:57 -0500 |
commit | 8c7a2c2bcfaf0ee29c74437a4814d1aa780d6a26 (patch) | |
tree | 74093a74ea43965f04502bc5d71b6976a74c7305 /drivers/md | |
parent | b014f14c81bc5db4e40e2a4db10998fd79c1c64c (diff) |
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 <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid1.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 3d9aa0c92821..f68075189df8 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1265,6 +1265,25 @@ static int raid1_spare_active(struct mddev *mddev) | |||
1265 | */ | 1265 | */ |
1266 | for (i = 0; i < conf->raid_disks; i++) { | 1266 | for (i = 0; i < conf->raid_disks; i++) { |
1267 | struct md_rdev *rdev = conf->mirrors[i].rdev; | 1267 | struct md_rdev *rdev = conf->mirrors[i].rdev; |
1268 | struct md_rdev *repl = conf->mirrors[conf->raid_disks + i].rdev; | ||
1269 | if (repl | ||
1270 | && repl->recovery_offset == MaxSector | ||
1271 | && !test_bit(Faulty, &repl->flags) | ||
1272 | && !test_and_set_bit(In_sync, &repl->flags)) { | ||
1273 | /* replacement has just become active */ | ||
1274 | if (!rdev || | ||
1275 | !test_and_clear_bit(In_sync, &rdev->flags)) | ||
1276 | count++; | ||
1277 | if (rdev) { | ||
1278 | /* Replaced device not technically | ||
1279 | * faulty, but we need to be sure | ||
1280 | * it gets removed and never re-added | ||
1281 | */ | ||
1282 | set_bit(Faulty, &rdev->flags); | ||
1283 | sysfs_notify_dirent_safe( | ||
1284 | rdev->sysfs_state); | ||
1285 | } | ||
1286 | } | ||
1268 | if (rdev | 1287 | if (rdev |
1269 | && !test_bit(Faulty, &rdev->flags) | 1288 | && !test_bit(Faulty, &rdev->flags) |
1270 | && !test_and_set_bit(In_sync, &rdev->flags)) { | 1289 | && !test_and_set_bit(In_sync, &rdev->flags)) { |
@@ -1362,10 +1381,21 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev) | |||
1362 | err = -EBUSY; | 1381 | err = -EBUSY; |
1363 | p->rdev = rdev; | 1382 | p->rdev = rdev; |
1364 | goto abort; | 1383 | goto abort; |
1365 | } else { | 1384 | } else if (conf->mirrors[conf->raid_disks + number].rdev) { |
1366 | clear_bit(Replacement, &rdev->flags); | 1385 | /* We just removed a device that is being replaced. |
1386 | * Move down the replacement. We drain all IO before | ||
1387 | * doing this to avoid confusion. | ||
1388 | */ | ||
1389 | struct md_rdev *repl = | ||
1390 | conf->mirrors[conf->raid_disks + number].rdev; | ||
1391 | raise_barrier(conf); | ||
1392 | clear_bit(Replacement, &repl->flags); | ||
1393 | p->rdev = repl; | ||
1394 | conf->mirrors[conf->raid_disks + number].rdev = NULL; | ||
1395 | lower_barrier(conf); | ||
1396 | clear_bit(WantReplacement, &rdev->flags); | ||
1397 | } else | ||
1367 | clear_bit(WantReplacement, &rdev->flags); | 1398 | clear_bit(WantReplacement, &rdev->flags); |
1368 | } | ||
1369 | err = md_integrity_register(mddev); | 1399 | err = md_integrity_register(mddev); |
1370 | } | 1400 | } |
1371 | abort: | 1401 | abort: |