From: Dan Williams <[EMAIL PROTECTED]>

Enable handle_stripe5 to pass off check parity operations to
raid5_do_soft_block_ops formerly handled by compute_parity5.

Changelog:
* removed handle_check_operations5.  All logic moved into handle_stripe5 so
that we do not need to go through the initiation logic to end the
operation.
* clear the uptodate bit on the parity block
* hold off check operations if a parity dependent operation is in flight
like a write

Signed-off-by: Dan Williams <[EMAIL PROTECTED]>
---

 drivers/md/raid5.c |   60 ++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 42 insertions(+), 18 deletions(-)

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e39d248..24ed4d8 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2121,35 +2121,59 @@ #endif
                        locked += handle_write_operations5(sh, rcw);
        }
 
-       /* maybe we need to check and possibly fix the parity for this stripe
-        * Any reads will already have been scheduled, so we just see if enough 
data
-        * is available
+       /* 1/ Maybe we need to check and possibly fix the parity for this 
stripe.
+        *    Any reads will already have been scheduled, so we just see if 
enough data
+        *    is available.
+        * 2/ Hold off parity checks while parity dependent operations are in 
flight
+        *    (RCW and RMW are protected by 'locked')
         */
-       if (syncing && locked == 0 &&
-           !test_bit(STRIPE_INSYNC, &sh->state)) {
+       if ((syncing && locked == 0 &&
+           !test_bit(STRIPE_INSYNC, &sh->state)) ||
+               test_bit(STRIPE_OP_CHECK, &sh->state)) {
+
                set_bit(STRIPE_HANDLE, &sh->state);
+               /* Take one of the following actions:
+                * 1/ start a check parity operation if (uptodate == disks)
+                * 2/ finish a check parity operation and act on the result
+                */
                if (failed == 0) {
-                       BUG_ON(uptodate != disks);
-                       compute_parity5(sh, CHECK_PARITY);
-                       uptodate--;
-                       if (page_is_zero(sh->dev[sh->pd_idx].page)) {
-                               /* parity is correct (on disc, not in buffer 
any more) */
-                               set_bit(STRIPE_INSYNC, &sh->state);
-                       } else {
-                               conf->mddev->resync_mismatches += 
STRIPE_SECTORS;
-                               if (test_bit(MD_RECOVERY_CHECK, 
&conf->mddev->recovery))
-                                       /* don't try to repair!! */
+                       if (!test_bit(STRIPE_OP_CHECK, &sh->state)) {
+                               BUG_ON(uptodate != disks);
+                               set_bit(STRIPE_OP_CHECK, &sh->state);
+                               set_bit(STRIPE_OP_CHECK_Gen, &sh->ops.state);
+                               clear_bit(R5_UPTODATE, 
&sh->dev[sh->pd_idx].flags);
+                               sh->ops.pending++;
+                               uptodate--;
+                       } else if (test_and_clear_bit(STRIPE_OP_CHECK_Done, 
&sh->ops.state)) {
+                               clear_bit(STRIPE_OP_CHECK, &sh->state);
+
+                               if (test_and_clear_bit(STRIPE_OP_CHECK_IsZero,
+                                                       &sh->ops.state))
+                                       /* parity is correct (on disc, not in 
buffer any more) */
                                        set_bit(STRIPE_INSYNC, &sh->state);
                                else {
-                                       compute_block(sh, sh->pd_idx);
-                                       uptodate++;
+                                       conf->mddev->resync_mismatches += 
STRIPE_SECTORS;
+                                       if (test_bit(MD_RECOVERY_CHECK, 
&conf->mddev->recovery))
+                                               /* don't try to repair!! */
+                                               set_bit(STRIPE_INSYNC, 
&sh->state);
+                                       else {
+                                               compute_block(sh, sh->pd_idx);
+                                               uptodate++;
+                                       }
                                }
                        }
                }
-               if (!test_bit(STRIPE_INSYNC, &sh->state)) {
+
+               /* Wait for check parity operations to complete
+                * before write-back
+                */
+               if (!test_bit(STRIPE_INSYNC, &sh->state) &&
+                       !test_bit(STRIPE_OP_CHECK, &sh->state)) {
+
                        /* either failed parity check, or recovery is happening 
*/
                        if (failed==0)
                                failed_num = sh->pd_idx;
+
                        dev = &sh->dev[failed_num];
                        BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
                        BUG_ON(uptodate != disks);
-
To unsubscribe from this list: send the line "unsubscribe linux-raid" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to