aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/raid5.c84
1 files changed, 65 insertions, 19 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 42439a4c1c51..810cf831edda 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2471,26 +2471,67 @@ static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh,
2471 struct stripe_head_state *s, int disks) 2471 struct stripe_head_state *s, int disks)
2472{ 2472{
2473 set_bit(STRIPE_HANDLE, &sh->state); 2473 set_bit(STRIPE_HANDLE, &sh->state);
2474 if (s->failed == 0) { 2474 /* Take one of the following actions:
2475 BUG_ON(s->uptodate != disks); 2475 * 1/ start a check parity operation if (uptodate == disks)
2476 compute_parity5(sh, CHECK_PARITY); 2476 * 2/ finish a check parity operation and act on the result
2477 s->uptodate--; 2477 * 3/ skip to the writeback section if we previously
2478 if (page_is_zero(sh->dev[sh->pd_idx].page)) { 2478 * initiated a recovery operation
2479 /* parity is correct (on disc, not in buffer any more) 2479 */
2480 */ 2480 if (s->failed == 0 &&
2481 set_bit(STRIPE_INSYNC, &sh->state); 2481 !test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
2482 } else { 2482 if (!test_and_set_bit(STRIPE_OP_CHECK, &sh->ops.pending)) {
2483 conf->mddev->resync_mismatches += STRIPE_SECTORS; 2483 BUG_ON(s->uptodate != disks);
2484 if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) 2484 clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
2485 /* don't try to repair!! */ 2485 sh->ops.count++;
2486 s->uptodate--;
2487 } else if (
2488 test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) {
2489 clear_bit(STRIPE_OP_CHECK, &sh->ops.ack);
2490 clear_bit(STRIPE_OP_CHECK, &sh->ops.pending);
2491
2492 if (sh->ops.zero_sum_result == 0)
2493 /* parity is correct (on disc,
2494 * not in buffer any more)
2495 */
2486 set_bit(STRIPE_INSYNC, &sh->state); 2496 set_bit(STRIPE_INSYNC, &sh->state);
2487 else { 2497 else {
2488 compute_block(sh, sh->pd_idx); 2498 conf->mddev->resync_mismatches +=
2489 s->uptodate++; 2499 STRIPE_SECTORS;
2500 if (test_bit(
2501 MD_RECOVERY_CHECK, &conf->mddev->recovery))
2502 /* don't try to repair!! */
2503 set_bit(STRIPE_INSYNC, &sh->state);
2504 else {
2505 set_bit(STRIPE_OP_COMPUTE_BLK,
2506 &sh->ops.pending);
2507 set_bit(STRIPE_OP_MOD_REPAIR_PD,
2508 &sh->ops.pending);
2509 set_bit(R5_Wantcompute,
2510 &sh->dev[sh->pd_idx].flags);
2511 sh->ops.target = sh->pd_idx;
2512 sh->ops.count++;
2513 s->uptodate++;
2514 }
2490 } 2515 }
2491 } 2516 }
2492 } 2517 }
2493 if (!test_bit(STRIPE_INSYNC, &sh->state)) { 2518
2519 /* check if we can clear a parity disk reconstruct */
2520 if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) &&
2521 test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) {
2522
2523 clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending);
2524 clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete);
2525 clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack);
2526 clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending);
2527 }
2528
2529 /* Wait for check parity and compute block operations to complete
2530 * before write-back
2531 */
2532 if (!test_bit(STRIPE_INSYNC, &sh->state) &&
2533 !test_bit(STRIPE_OP_CHECK, &sh->ops.pending) &&
2534 !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) {
2494 struct r5dev *dev; 2535 struct r5dev *dev;
2495 /* either failed parity check, or recovery is happening */ 2536 /* either failed parity check, or recovery is happening */
2496 if (s->failed == 0) 2537 if (s->failed == 0)
@@ -2855,12 +2896,17 @@ static void handle_stripe5(struct stripe_head *sh)
2855 handle_issuing_new_write_requests5(conf, sh, &s, disks); 2896 handle_issuing_new_write_requests5(conf, sh, &s, disks);
2856 2897
2857 /* maybe we need to check and possibly fix the parity for this stripe 2898 /* maybe we need to check and possibly fix the parity for this stripe
2858 * Any reads will already have been scheduled, so we just see if enough data 2899 * Any reads will already have been scheduled, so we just see if enough
2859 * is available 2900 * data is available. The parity check is held off while parity
2901 * dependent operations are in flight.
2860 */ 2902 */
2861 if (s.syncing && s.locked == 0 && 2903 if ((s.syncing && s.locked == 0 &&
2862 !test_bit(STRIPE_INSYNC, &sh->state)) 2904 !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending) &&
2905 !test_bit(STRIPE_INSYNC, &sh->state)) ||
2906 test_bit(STRIPE_OP_CHECK, &sh->ops.pending) ||
2907 test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending))
2863 handle_parity_checks5(conf, sh, &s, disks); 2908 handle_parity_checks5(conf, sh, &s, disks);
2909
2864 if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) { 2910 if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
2865 md_done_sync(conf->mddev, STRIPE_SECTORS,1); 2911 md_done_sync(conf->mddev, STRIPE_SECTORS,1);
2866 clear_bit(STRIPE_SYNCING, &sh->state); 2912 clear_bit(STRIPE_SYNCING, &sh->state);