aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid10.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-10-03 04:15:45 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-03 11:04:17 -0400
commit6814d5368d68341ec6b5e4ecd10ea5947130775a (patch)
tree07440216f8f1b94429eee8f79469e0b800505251 /drivers/md/raid10.c
parentb5c124af69119c1b5c1e728bd2e7b5b1fad9b7be (diff)
[PATCH] md: factor out part of raid10d into a separate function.
raid10d 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/raid10.c')
-rw-r--r--drivers/md/raid10.c213
1 files changed, 115 insertions, 98 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 016ddb831c9b..7bf5ce281c4d 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1350,9 +1350,119 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
1350 * 1350 *
1351 * 1. Retries failed read operations on working mirrors. 1351 * 1. Retries failed read operations on working mirrors.
1352 * 2. Updates the raid superblock when problems encounter. 1352 * 2. Updates the raid superblock when problems encounter.
1353 * 3. Performs writes following reads for array syncronising. 1353 * 3. Performs writes following reads for array synchronising.
1354 */ 1354 */
1355 1355
1356static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
1357{
1358 int sect = 0; /* Offset from r10_bio->sector */
1359 int sectors = r10_bio->sectors;
1360 mdk_rdev_t*rdev;
1361 while(sectors) {
1362 int s = sectors;
1363 int sl = r10_bio->read_slot;
1364 int success = 0;
1365 int start;
1366
1367 if (s > (PAGE_SIZE>>9))
1368 s = PAGE_SIZE >> 9;
1369
1370 rcu_read_lock();
1371 do {
1372 int d = r10_bio->devs[sl].devnum;
1373 rdev = rcu_dereference(conf->mirrors[d].rdev);
1374 if (rdev &&
1375 test_bit(In_sync, &rdev->flags)) {
1376 atomic_inc(&rdev->nr_pending);
1377 rcu_read_unlock();
1378 success = sync_page_io(rdev->bdev,
1379 r10_bio->devs[sl].addr +
1380 sect + rdev->data_offset,
1381 s<<9,
1382 conf->tmppage, READ);
1383 rdev_dec_pending(rdev, mddev);
1384 rcu_read_lock();
1385 if (success)
1386 break;
1387 }
1388 sl++;
1389 if (sl == conf->copies)
1390 sl = 0;
1391 } while (!success && sl != r10_bio->read_slot);
1392 rcu_read_unlock();
1393
1394 if (!success) {
1395 /* Cannot read from anywhere -- bye bye array */
1396 int dn = r10_bio->devs[r10_bio->read_slot].devnum;
1397 md_error(mddev, conf->mirrors[dn].rdev);
1398 break;
1399 }
1400
1401 start = sl;
1402 /* write it back and re-read */
1403 rcu_read_lock();
1404 while (sl != r10_bio->read_slot) {
1405 int d;
1406 if (sl==0)
1407 sl = conf->copies;
1408 sl--;
1409 d = r10_bio->devs[sl].devnum;
1410 rdev = rcu_dereference(conf->mirrors[d].rdev);
1411 if (rdev &&
1412 test_bit(In_sync, &rdev->flags)) {
1413 atomic_inc(&rdev->nr_pending);
1414 rcu_read_unlock();
1415 atomic_add(s, &rdev->corrected_errors);
1416 if (sync_page_io(rdev->bdev,
1417 r10_bio->devs[sl].addr +
1418 sect + rdev->data_offset,
1419 s<<9, conf->tmppage, WRITE)
1420 == 0)
1421 /* Well, this device is dead */
1422 md_error(mddev, rdev);
1423 rdev_dec_pending(rdev, mddev);
1424 rcu_read_lock();
1425 }
1426 }
1427 sl = start;
1428 while (sl != r10_bio->read_slot) {
1429 int d;
1430 if (sl==0)
1431 sl = conf->copies;
1432 sl--;
1433 d = r10_bio->devs[sl].devnum;
1434 rdev = rcu_dereference(conf->mirrors[d].rdev);
1435 if (rdev &&
1436 test_bit(In_sync, &rdev->flags)) {
1437 char b[BDEVNAME_SIZE];
1438 atomic_inc(&rdev->nr_pending);
1439 rcu_read_unlock();
1440 if (sync_page_io(rdev->bdev,
1441 r10_bio->devs[sl].addr +
1442 sect + rdev->data_offset,
1443 s<<9, conf->tmppage, READ) == 0)
1444 /* Well, this device is dead */
1445 md_error(mddev, rdev);
1446 else
1447 printk(KERN_INFO
1448 "raid10:%s: read error corrected"
1449 " (%d sectors at %llu on %s)\n",
1450 mdname(mddev), s,
1451 (unsigned long long)sect+
1452 rdev->data_offset,
1453 bdevname(rdev->bdev, b));
1454
1455 rdev_dec_pending(rdev, mddev);
1456 rcu_read_lock();
1457 }
1458 }
1459 rcu_read_unlock();
1460
1461 sectors -= s;
1462 sect += s;
1463 }
1464}
1465
1356static void raid10d(mddev_t *mddev) 1466static void raid10d(mddev_t *mddev)
1357{ 1467{
1358 r10bio_t *r10_bio; 1468 r10bio_t *r10_bio;
@@ -1413,105 +1523,12 @@ static void raid10d(mddev_t *mddev)
1413 * This is all done synchronously while the array is 1523 * This is all done synchronously while the array is
1414 * frozen. 1524 * frozen.
1415 */ 1525 */
1416 int sect = 0; /* Offset from r10_bio->sector */ 1526 if (mddev->ro == 0) {
1417 int sectors = r10_bio->sectors; 1527 freeze_array(conf);
1418 freeze_array(conf); 1528 fix_read_error(conf, mddev, r10_bio);
1419 if (mddev->ro == 0) while(sectors) { 1529 unfreeze_array(conf);
1420 int s = sectors;
1421 int sl = r10_bio->read_slot;
1422 int success = 0;
1423
1424 if (s > (PAGE_SIZE>>9))
1425 s = PAGE_SIZE >> 9;
1426
1427 rcu_read_lock();
1428 do {
1429 int d = r10_bio->devs[sl].devnum;
1430 rdev = rcu_dereference(conf->mirrors[d].rdev);
1431 if (rdev &&
1432 test_bit(In_sync, &rdev->flags)) {
1433 atomic_inc(&rdev->nr_pending);
1434 rcu_read_unlock();
1435 success = sync_page_io(rdev->bdev,
1436 r10_bio->devs[sl].addr +
1437 sect + rdev->data_offset,
1438 s<<9,
1439 conf->tmppage, READ);
1440 rdev_dec_pending(rdev, mddev);
1441 rcu_read_lock();
1442 if (success)
1443 break;
1444 }
1445 sl++;
1446 if (sl == conf->copies)
1447 sl = 0;
1448 } while (!success && sl != r10_bio->read_slot);
1449 rcu_read_unlock();
1450
1451 if (success) {
1452 int start = sl;
1453 /* write it back and re-read */
1454 rcu_read_lock();
1455 while (sl != r10_bio->read_slot) {
1456 int d;
1457 if (sl==0)
1458 sl = conf->copies;
1459 sl--;
1460 d = r10_bio->devs[sl].devnum;
1461 rdev = rcu_dereference(conf->mirrors[d].rdev);
1462 if (rdev &&
1463 test_bit(In_sync, &rdev->flags)) {
1464 atomic_inc(&rdev->nr_pending);
1465 rcu_read_unlock();
1466 atomic_add(s, &rdev->corrected_errors);
1467 if (sync_page_io(rdev->bdev,
1468 r10_bio->devs[sl].addr +
1469 sect + rdev->data_offset,
1470 s<<9, conf->tmppage, WRITE) == 0)
1471 /* Well, this device is dead */
1472 md_error(mddev, rdev);
1473 rdev_dec_pending(rdev, mddev);
1474 rcu_read_lock();
1475 }
1476 }
1477 sl = start;
1478 while (sl != r10_bio->read_slot) {
1479 int d;
1480 if (sl==0)
1481 sl = conf->copies;
1482 sl--;
1483 d = r10_bio->devs[sl].devnum;
1484 rdev = rcu_dereference(conf->mirrors[d].rdev);
1485 if (rdev &&
1486 test_bit(In_sync, &rdev->flags)) {
1487 atomic_inc(&rdev->nr_pending);
1488 rcu_read_unlock();
1489 if (sync_page_io(rdev->bdev,
1490 r10_bio->devs[sl].addr +
1491 sect + rdev->data_offset,
1492 s<<9, conf->tmppage, READ) == 0)
1493 /* Well, this device is dead */
1494 md_error(mddev, rdev);
1495 else
1496 printk(KERN_INFO "raid10:%s: read error corrected (%d sectors at %llu on %s)\n",
1497 mdname(mddev), s, (unsigned long long)(sect+rdev->data_offset), bdevname(rdev->bdev, b));
1498
1499 rdev_dec_pending(rdev, mddev);
1500 rcu_read_lock();
1501 }
1502 }
1503 rcu_read_unlock();
1504 } else {
1505 /* Cannot read from anywhere -- bye bye array */
1506 md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev);
1507 break;
1508 }
1509 sectors -= s;
1510 sect += s;
1511 } 1530 }
1512 1531
1513 unfreeze_array(conf);
1514
1515 bio = r10_bio->devs[r10_bio->read_slot].bio; 1532 bio = r10_bio->devs[r10_bio->read_slot].bio;
1516 r10_bio->devs[r10_bio->read_slot].bio = 1533 r10_bio->devs[r10_bio->read_slot].bio =
1517 mddev->ro ? IO_BLOCKED : NULL; 1534 mddev->ro ? IO_BLOCKED : NULL;