diff options
| author | NeilBrown <neilb@suse.de> | 2006-10-03 04:15:45 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-03 11:04:17 -0400 |
| commit | 6814d5368d68341ec6b5e4ecd10ea5947130775a (patch) | |
| tree | 07440216f8f1b94429eee8f79469e0b800505251 | |
| parent | b5c124af69119c1b5c1e728bd2e7b5b1fad9b7be (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>
| -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; |
