aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/raid10.c72
1 files changed, 61 insertions, 11 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 403f05ac1f2a..90e951730a23 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -397,14 +397,17 @@ static void raid10_end_write_request(struct bio *bio, int error)
397 int dec_rdev = 1; 397 int dec_rdev = 1;
398 struct r10conf *conf = r10_bio->mddev->private; 398 struct r10conf *conf = r10_bio->mddev->private;
399 int slot, repl; 399 int slot, repl;
400 struct md_rdev *rdev; 400 struct md_rdev *rdev = NULL;
401 401
402 dev = find_bio_disk(conf, r10_bio, bio, &slot, &repl); 402 dev = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
403 403
404 if (repl) 404 if (repl)
405 rdev = conf->mirrors[dev].replacement; 405 rdev = conf->mirrors[dev].replacement;
406 else 406 if (!rdev) {
407 smp_rmb();
408 repl = 0;
407 rdev = conf->mirrors[dev].rdev; 409 rdev = conf->mirrors[dev].rdev;
410 }
408 /* 411 /*
409 * this branch is our 'one mirror IO has finished' event handler: 412 * this branch is our 'one mirror IO has finished' event handler:
410 */ 413 */
@@ -1089,6 +1092,8 @@ retry_write:
1089 struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev); 1092 struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev);
1090 struct md_rdev *rrdev = rcu_dereference( 1093 struct md_rdev *rrdev = rcu_dereference(
1091 conf->mirrors[d].replacement); 1094 conf->mirrors[d].replacement);
1095 if (rdev == rrdev)
1096 rrdev = NULL;
1092 if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) { 1097 if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
1093 atomic_inc(&rdev->nr_pending); 1098 atomic_inc(&rdev->nr_pending);
1094 blocked_rdev = rdev; 1099 blocked_rdev = rdev;
@@ -1170,9 +1175,15 @@ retry_write:
1170 rdev_dec_pending(conf->mirrors[d].rdev, mddev); 1175 rdev_dec_pending(conf->mirrors[d].rdev, mddev);
1171 } 1176 }
1172 if (r10_bio->devs[j].repl_bio) { 1177 if (r10_bio->devs[j].repl_bio) {
1178 struct md_rdev *rdev;
1173 d = r10_bio->devs[j].devnum; 1179 d = r10_bio->devs[j].devnum;
1174 rdev_dec_pending( 1180 rdev = conf->mirrors[d].replacement;
1175 conf->mirrors[d].replacement, mddev); 1181 if (!rdev) {
1182 /* Race with remove_disk */
1183 smp_mb();
1184 rdev = conf->mirrors[d].rdev;
1185 }
1186 rdev_dec_pending(rdev, mddev);
1176 } 1187 }
1177 } 1188 }
1178 allow_barrier(conf); 1189 allow_barrier(conf);
@@ -1230,6 +1241,10 @@ retry_write:
1230 max_sectors); 1241 max_sectors);
1231 r10_bio->devs[i].repl_bio = mbio; 1242 r10_bio->devs[i].repl_bio = mbio;
1232 1243
1244 /* We are actively writing to the original device
1245 * so it cannot disappear, so the replacement cannot
1246 * become NULL here
1247 */
1233 mbio->bi_sector = (r10_bio->devs[i].addr+ 1248 mbio->bi_sector = (r10_bio->devs[i].addr+
1234 conf->mirrors[d].replacement->data_offset); 1249 conf->mirrors[d].replacement->data_offset);
1235 mbio->bi_bdev = conf->mirrors[d].replacement->bdev; 1250 mbio->bi_bdev = conf->mirrors[d].replacement->bdev;
@@ -1404,9 +1419,27 @@ static int raid10_spare_active(struct mddev *mddev)
1404 */ 1419 */
1405 for (i = 0; i < conf->raid_disks; i++) { 1420 for (i = 0; i < conf->raid_disks; i++) {
1406 tmp = conf->mirrors + i; 1421 tmp = conf->mirrors + i;
1407 if (tmp->rdev 1422 if (tmp->replacement
1408 && !test_bit(Faulty, &tmp->rdev->flags) 1423 && tmp->replacement->recovery_offset == MaxSector
1409 && !test_and_set_bit(In_sync, &tmp->rdev->flags)) { 1424 && !test_bit(Faulty, &tmp->replacement->flags)
1425 && !test_and_set_bit(In_sync, &tmp->replacement->flags)) {
1426 /* Replacement has just become active */
1427 if (!tmp->rdev
1428 || !test_and_clear_bit(In_sync, &tmp->rdev->flags))
1429 count++;
1430 if (tmp->rdev) {
1431 /* Replaced device not technically faulty,
1432 * but we need to be sure it gets removed
1433 * and never re-added.
1434 */
1435 set_bit(Faulty, &tmp->rdev->flags);
1436 sysfs_notify_dirent_safe(
1437 tmp->rdev->sysfs_state);
1438 }
1439 sysfs_notify_dirent_safe(tmp->replacement->sysfs_state);
1440 } else if (tmp->rdev
1441 && !test_bit(Faulty, &tmp->rdev->flags)
1442 && !test_and_set_bit(In_sync, &tmp->rdev->flags)) {
1410 count++; 1443 count++;
1411 sysfs_notify_dirent(tmp->rdev->sysfs_state); 1444 sysfs_notify_dirent(tmp->rdev->sysfs_state);
1412 } 1445 }
@@ -1506,6 +1539,7 @@ static int raid10_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
1506 */ 1539 */
1507 if (!test_bit(Faulty, &rdev->flags) && 1540 if (!test_bit(Faulty, &rdev->flags) &&
1508 mddev->recovery_disabled != p->recovery_disabled && 1541 mddev->recovery_disabled != p->recovery_disabled &&
1542 (!p->replacement || p->replacement == rdev) &&
1509 enough(conf, -1)) { 1543 enough(conf, -1)) {
1510 err = -EBUSY; 1544 err = -EBUSY;
1511 goto abort; 1545 goto abort;
@@ -1517,7 +1551,21 @@ static int raid10_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
1517 err = -EBUSY; 1551 err = -EBUSY;
1518 *rdevp = rdev; 1552 *rdevp = rdev;
1519 goto abort; 1553 goto abort;
1520 } 1554 } else if (p->replacement) {
1555 /* We must have just cleared 'rdev' */
1556 p->rdev = p->replacement;
1557 clear_bit(Replacement, &p->replacement->flags);
1558 smp_mb(); /* Make sure other CPUs may see both as identical
1559 * but will never see neither -- if they are careful.
1560 */
1561 p->replacement = NULL;
1562 clear_bit(WantReplacement, &rdev->flags);
1563 } else
1564 /* We might have just remove the Replacement as faulty
1565 * Clear the flag just in case
1566 */
1567 clear_bit(WantReplacement, &rdev->flags);
1568
1521 err = md_integrity_register(mddev); 1569 err = md_integrity_register(mddev);
1522 1570
1523abort: 1571abort:
@@ -1595,13 +1643,15 @@ static void end_sync_write(struct bio *bio, int error)
1595 int bad_sectors; 1643 int bad_sectors;
1596 int slot; 1644 int slot;
1597 int repl; 1645 int repl;
1598 struct md_rdev *rdev; 1646 struct md_rdev *rdev = NULL;
1599 1647
1600 d = find_bio_disk(conf, r10_bio, bio, &slot, &repl); 1648 d = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
1601 if (repl) 1649 if (repl)
1602 rdev = conf->mirrors[d].replacement; 1650 rdev = conf->mirrors[d].replacement;
1603 else 1651 if (!rdev) {
1652 smp_mb();
1604 rdev = conf->mirrors[d].rdev; 1653 rdev = conf->mirrors[d].rdev;
1654 }
1605 1655
1606 if (!uptodate) { 1656 if (!uptodate) {
1607 if (repl) 1657 if (repl)
@@ -2368,7 +2418,7 @@ static void handle_write_completed(struct r10conf *conf, struct r10bio *r10_bio)
2368 } 2418 }
2369 bio = r10_bio->devs[m].repl_bio; 2419 bio = r10_bio->devs[m].repl_bio;
2370 rdev = conf->mirrors[dev].replacement; 2420 rdev = conf->mirrors[dev].replacement;
2371 if (bio == IO_MADE_GOOD) { 2421 if (rdev && bio == IO_MADE_GOOD) {
2372 rdev_clear_badblocks( 2422 rdev_clear_badblocks(
2373 rdev, 2423 rdev,
2374 r10_bio->devs[m].addr, 2424 r10_bio->devs[m].addr,