aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid1.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-10-03 04:15:51 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-03 11:04:17 -0400
commit867868fb557eb2a2120b80779468fa372584ddb0 (patch)
treefeb35d5c59cf4d22a14ee04d285c132429e88b06 /drivers/md/raid1.c
parent2d2063ceae73660d5142f4754d50a75b655fd1f9 (diff)
[PATCH] md: Factor out part of raid1d into a separate function
raid1d has toooo many nested block, so take the fix_read_error functionality out into a separate function. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r--drivers/md/raid1.c173
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
1371static 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
1371static void raid1d(mddev_t *mddev) 1460static 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"