diff options
-rw-r--r-- | drivers/md/raid1.c | 173 |
1 files changed, 95 insertions, 78 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 2817c477302d..13b59e6a6acb 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1368,6 +1368,95 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) | |||
1368 | * 3. Performs writes following reads for array syncronising. | 1368 | * 3. Performs writes following reads for array syncronising. |
1369 | */ | 1369 | */ |
1370 | 1370 | ||
1371 | static void fix_read_error(conf_t *conf, int read_disk, | ||
1372 | sector_t sect, int sectors) | ||
1373 | { | ||
1374 | mddev_t *mddev = conf->mddev; | ||
1375 | while(sectors) { | ||
1376 | int s = sectors; | ||
1377 | int d = read_disk; | ||
1378 | int success = 0; | ||
1379 | int start; | ||
1380 | mdk_rdev_t *rdev; | ||
1381 | |||
1382 | if (s > (PAGE_SIZE>>9)) | ||
1383 | s = PAGE_SIZE >> 9; | ||
1384 | |||
1385 | do { | ||
1386 | /* Note: no rcu protection needed here | ||
1387 | * as this is synchronous in the raid1d thread | ||
1388 | * which is the thread that might remove | ||
1389 | * a device. If raid1d ever becomes multi-threaded.... | ||
1390 | */ | ||
1391 | rdev = conf->mirrors[d].rdev; | ||
1392 | if (rdev && | ||
1393 | test_bit(In_sync, &rdev->flags) && | ||
1394 | sync_page_io(rdev->bdev, | ||
1395 | sect + rdev->data_offset, | ||
1396 | s<<9, | ||
1397 | conf->tmppage, READ)) | ||
1398 | success = 1; | ||
1399 | else { | ||
1400 | d++; | ||
1401 | if (d == conf->raid_disks) | ||
1402 | d = 0; | ||
1403 | } | ||
1404 | } while (!success && d != read_disk); | ||
1405 | |||
1406 | if (!success) { | ||
1407 | /* Cannot read from anywhere -- bye bye array */ | ||
1408 | md_error(mddev, conf->mirrors[read_disk].rdev); | ||
1409 | break; | ||
1410 | } | ||
1411 | /* write it back and re-read */ | ||
1412 | start = d; | ||
1413 | while (d != read_disk) { | ||
1414 | if (d==0) | ||
1415 | d = conf->raid_disks; | ||
1416 | d--; | ||
1417 | rdev = conf->mirrors[d].rdev; | ||
1418 | if (rdev && | ||
1419 | test_bit(In_sync, &rdev->flags)) { | ||
1420 | if (sync_page_io(rdev->bdev, | ||
1421 | sect + rdev->data_offset, | ||
1422 | s<<9, conf->tmppage, WRITE) | ||
1423 | == 0) | ||
1424 | /* Well, this device is dead */ | ||
1425 | md_error(mddev, rdev); | ||
1426 | } | ||
1427 | } | ||
1428 | d = start; | ||
1429 | while (d != read_disk) { | ||
1430 | char b[BDEVNAME_SIZE]; | ||
1431 | if (d==0) | ||
1432 | d = conf->raid_disks; | ||
1433 | d--; | ||
1434 | rdev = conf->mirrors[d].rdev; | ||
1435 | if (rdev && | ||
1436 | test_bit(In_sync, &rdev->flags)) { | ||
1437 | if (sync_page_io(rdev->bdev, | ||
1438 | sect + rdev->data_offset, | ||
1439 | s<<9, conf->tmppage, READ) | ||
1440 | == 0) | ||
1441 | /* Well, this device is dead */ | ||
1442 | md_error(mddev, rdev); | ||
1443 | else { | ||
1444 | atomic_add(s, &rdev->corrected_errors); | ||
1445 | printk(KERN_INFO | ||
1446 | "raid1:%s: read error corrected " | ||
1447 | "(%d sectors at %llu on %s)\n", | ||
1448 | mdname(mddev), s, | ||
1449 | (unsigned long long)sect + | ||
1450 | rdev->data_offset, | ||
1451 | bdevname(rdev->bdev, b)); | ||
1452 | } | ||
1453 | } | ||
1454 | } | ||
1455 | sectors -= s; | ||
1456 | sect += s; | ||
1457 | } | ||
1458 | } | ||
1459 | |||
1371 | static void raid1d(mddev_t *mddev) | 1460 | static void raid1d(mddev_t *mddev) |
1372 | { | 1461 | { |
1373 | r1bio_t *r1_bio; | 1462 | r1bio_t *r1_bio; |
@@ -1460,86 +1549,14 @@ static void raid1d(mddev_t *mddev) | |||
1460 | * This is all done synchronously while the array is | 1549 | * This is all done synchronously while the array is |
1461 | * frozen | 1550 | * frozen |
1462 | */ | 1551 | */ |
1463 | sector_t sect = r1_bio->sector; | 1552 | if (mddev->ro == 0) { |
1464 | int sectors = r1_bio->sectors; | 1553 | freeze_array(conf); |
1465 | freeze_array(conf); | 1554 | fix_read_error(conf, r1_bio->read_disk, |
1466 | if (mddev->ro == 0) while(sectors) { | 1555 | r1_bio->sector, |
1467 | int s = sectors; | 1556 | r1_bio->sectors); |
1468 | int d = r1_bio->read_disk; | 1557 | unfreeze_array(conf); |
1469 | int success = 0; | ||
1470 | |||
1471 | if (s > (PAGE_SIZE>>9)) | ||
1472 | s = PAGE_SIZE >> 9; | ||
1473 | |||
1474 | do { | ||
1475 | /* Note: no rcu protection needed here | ||
1476 | * as this is synchronous in the raid1d thread | ||
1477 | * which is the thread that might remove | ||
1478 | * a device. If raid1d ever becomes multi-threaded.... | ||
1479 | */ | ||
1480 | rdev = conf->mirrors[d].rdev; | ||
1481 | if (rdev && | ||
1482 | test_bit(In_sync, &rdev->flags) && | ||
1483 | sync_page_io(rdev->bdev, | ||
1484 | sect + rdev->data_offset, | ||
1485 | s<<9, | ||
1486 | conf->tmppage, READ)) | ||
1487 | success = 1; | ||
1488 | else { | ||
1489 | d++; | ||
1490 | if (d == conf->raid_disks) | ||
1491 | d = 0; | ||
1492 | } | ||
1493 | } while (!success && d != r1_bio->read_disk); | ||
1494 | |||
1495 | if (success) { | ||
1496 | /* write it back and re-read */ | ||
1497 | int start = d; | ||
1498 | while (d != r1_bio->read_disk) { | ||
1499 | if (d==0) | ||
1500 | d = conf->raid_disks; | ||
1501 | d--; | ||
1502 | rdev = conf->mirrors[d].rdev; | ||
1503 | if (rdev && | ||
1504 | test_bit(In_sync, &rdev->flags)) { | ||
1505 | if (sync_page_io(rdev->bdev, | ||
1506 | sect + rdev->data_offset, | ||
1507 | s<<9, conf->tmppage, WRITE) == 0) | ||
1508 | /* Well, this device is dead */ | ||
1509 | md_error(mddev, rdev); | ||
1510 | } | ||
1511 | } | ||
1512 | d = start; | ||
1513 | while (d != r1_bio->read_disk) { | ||
1514 | if (d==0) | ||
1515 | d = conf->raid_disks; | ||
1516 | d--; | ||
1517 | rdev = conf->mirrors[d].rdev; | ||
1518 | if (rdev && | ||
1519 | test_bit(In_sync, &rdev->flags)) { | ||
1520 | if (sync_page_io(rdev->bdev, | ||
1521 | sect + rdev->data_offset, | ||
1522 | s<<9, conf->tmppage, READ) == 0) | ||
1523 | /* Well, this device is dead */ | ||
1524 | md_error(mddev, rdev); | ||
1525 | else { | ||
1526 | atomic_add(s, &rdev->corrected_errors); | ||
1527 | printk(KERN_INFO "raid1:%s: read error corrected (%d sectors at %llu on %s)\n", | ||
1528 | mdname(mddev), s, (unsigned long long)(sect + rdev->data_offset), bdevname(rdev->bdev, b)); | ||
1529 | } | ||
1530 | } | ||
1531 | } | ||
1532 | } else { | ||
1533 | /* Cannot read from anywhere -- bye bye array */ | ||
1534 | md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev); | ||
1535 | break; | ||
1536 | } | ||
1537 | sectors -= s; | ||
1538 | sect += s; | ||
1539 | } | 1558 | } |
1540 | 1559 | ||
1541 | unfreeze_array(conf); | ||
1542 | |||
1543 | bio = r1_bio->bios[r1_bio->read_disk]; | 1560 | bio = r1_bio->bios[r1_bio->read_disk]; |
1544 | if ((disk=read_balance(conf, r1_bio)) == -1) { | 1561 | if ((disk=read_balance(conf, r1_bio)) == -1) { |
1545 | printk(KERN_ALERT "raid1: %s: unrecoverable I/O" | 1562 | printk(KERN_ALERT "raid1: %s: unrecoverable I/O" |