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); |
