diff options
-rw-r--r-- | drivers/md/raid5.c | 84 |
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); |