diff options
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/raid10.c | 213 |
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 | ||
1356 | static 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 | |||
1356 | static void raid10d(mddev_t *mddev) | 1466 | static 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; |