md/raid5: move more common code into handle_stripe
authorNeilBrown <neilb@suse.de>
Wed, 27 Jul 2011 01:00:36 +0000 (11:00 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 27 Jul 2011 01:00:36 +0000 (11:00 +1000)
Apart from 'prexor' which can only be set for RAID5, and
'qd_idx' which can only be meaningful for RAID6, these two
chunks of code are nearly the same.

So combine them into one adding a test to call either
handle_parity_checks5 or handle_parity_checks6 as appropriate.

Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Namhyung Kim <namhyung@gmail.com>
drivers/md/raid5.c

index a301897..cf60b15 100644 (file)
@@ -1756,7 +1756,7 @@ static sector_t raid5_compute_sector(raid5_conf_t *conf, sector_t r_sector,
        /*
         * Select the parity disk based on the user selected algorithm.
         */
-       pd_idx = qd_idx = ~0;
+       pd_idx = qd_idx = -1;
        switch(conf->level) {
        case 4:
                pd_idx = data_disks;
@@ -2903,7 +2903,6 @@ static int handle_stripe5(struct stripe_head *sh, struct stripe_head_state *s)
        raid5_conf_t *conf = sh->raid_conf;
        int disks = sh->disks, i;
        struct r5dev *dev;
-       int prexor;
 
        /* Now to look around and see what can be done */
        rcu_read_lock();
@@ -3026,56 +3025,6 @@ static int handle_stripe5(struct stripe_head *sh, struct stripe_head_state *s)
            (s->syncing && (s->uptodate + s->compute < disks)) || s->expanding)
                handle_stripe_fill(sh, s, disks);
 
-       /* Now we check to see if any write operations have recently
-        * completed
-        */
-       prexor = 0;
-       if (sh->reconstruct_state == reconstruct_state_prexor_drain_result)
-               prexor = 1;
-       if (sh->reconstruct_state == reconstruct_state_drain_result ||
-           sh->reconstruct_state == reconstruct_state_prexor_drain_result) {
-               sh->reconstruct_state = reconstruct_state_idle;
-
-               /* All the 'written' buffers and the parity block are ready to
-                * be written back to disk
-                */
-               BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
-               for (i = disks; i--; ) {
-                       dev = &sh->dev[i];
-                       if (test_bit(R5_LOCKED, &dev->flags) &&
-                               (i == sh->pd_idx || dev->written)) {
-                               pr_debug("Writing block %d\n", i);
-                               set_bit(R5_Wantwrite, &dev->flags);
-                               if (prexor)
-                                       continue;
-                               if (!test_bit(R5_Insync, &dev->flags) ||
-                                   (i == sh->pd_idx && s->failed == 0))
-                                       set_bit(STRIPE_INSYNC, &sh->state);
-                       }
-               }
-               if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-                       s->dec_preread_active = 1;
-       }
-
-       /* Now to consider new write requests and what else, if anything
-        * should be read.  We do not handle new writes when:
-        * 1/ A 'write' operation (copy+xor) is already in flight.
-        * 2/ A 'check' operation is in flight, as it may clobber the parity
-        *    block.
-        */
-       if (s->to_write && !sh->reconstruct_state && !sh->check_state)
-               handle_stripe_dirtying(conf, sh, s, disks);
-
-       /* 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.  The parity check is held off while parity
-        * dependent operations are in flight.
-        */
-       if (sh->check_state ||
-           (s->syncing && s->locked == 0 &&
-            !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
-            !test_bit(STRIPE_INSYNC, &sh->state)))
-               handle_parity_checks5(conf, sh, s, disks);
        return 0;
 }
 
@@ -3217,54 +3166,6 @@ static int handle_stripe6(struct stripe_head *sh, struct stripe_head_state *s)
            (s->syncing && (s->uptodate + s->compute < disks)) || s->expanding)
                handle_stripe_fill(sh, s, disks);
 
-       /* Now we check to see if any write operations have recently
-        * completed
-        */
-       if (sh->reconstruct_state == reconstruct_state_drain_result) {
-
-               sh->reconstruct_state = reconstruct_state_idle;
-               /* All the 'written' buffers and the parity blocks are ready to
-                * be written back to disk
-                */
-               BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
-               BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[qd_idx].flags));
-               for (i = disks; i--; ) {
-                       dev = &sh->dev[i];
-                       if (test_bit(R5_LOCKED, &dev->flags) &&
-                           (i == sh->pd_idx || i == qd_idx ||
-                            dev->written)) {
-                               pr_debug("Writing block %d\n", i);
-                               BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
-                               set_bit(R5_Wantwrite, &dev->flags);
-                               if (!test_bit(R5_Insync, &dev->flags) ||
-                                   ((i == sh->pd_idx || i == qd_idx) &&
-                                     s->failed == 0))
-                                       set_bit(STRIPE_INSYNC, &sh->state);
-                       }
-               }
-               if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-                       s->dec_preread_active = 1;
-       }
-
-       /* Now to consider new write requests and what else, if anything
-        * should be read.  We do not handle new writes when:
-        * 1/ A 'write' operation (copy+gen_syndrome) is already in flight.
-        * 2/ A 'check' operation is in flight, as it may clobber the parity
-        *    block.
-        */
-       if (s->to_write && !sh->reconstruct_state && !sh->check_state)
-               handle_stripe_dirtying(conf, sh, s, disks);
-
-       /* 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.  The parity check is held off while parity
-        * dependent operations are in flight.
-        */
-       if (sh->check_state ||
-           (s->syncing && s->locked == 0 &&
-            !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
-            !test_bit(STRIPE_INSYNC, &sh->state)))
-               handle_parity_checks6(conf, sh, s, disks);
        return 0;
 }
 
@@ -3273,6 +3174,8 @@ static void handle_stripe(struct stripe_head *sh)
        struct stripe_head_state s;
        int done;
        int i;
+       int prexor;
+       int disks = sh->disks;
        raid5_conf_t *conf = sh->raid_conf;
 
        clear_bit(STRIPE_HANDLE, &sh->state);
@@ -3310,6 +3213,64 @@ static void handle_stripe(struct stripe_head *sh)
        if (done)
                goto finish;
 
+       /* Now we check to see if any write operations have recently
+        * completed
+        */
+       prexor = 0;
+       if (sh->reconstruct_state == reconstruct_state_prexor_drain_result)
+               prexor = 1;
+       if (sh->reconstruct_state == reconstruct_state_drain_result ||
+           sh->reconstruct_state == reconstruct_state_prexor_drain_result) {
+               sh->reconstruct_state = reconstruct_state_idle;
+
+               /* All the 'written' buffers and the parity block are ready to
+                * be written back to disk
+                */
+               BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
+               BUG_ON(sh->qd_idx >= 0 &&
+                      !test_bit(R5_UPTODATE, &sh->dev[sh->qd_idx].flags));
+               for (i = disks; i--; ) {
+                       struct r5dev *dev = &sh->dev[i];
+                       if (test_bit(R5_LOCKED, &dev->flags) &&
+                               (i == sh->pd_idx || i == sh->qd_idx ||
+                                dev->written)) {
+                               pr_debug("Writing block %d\n", i);
+                               set_bit(R5_Wantwrite, &dev->flags);
+                               if (prexor)
+                                       continue;
+                               if (!test_bit(R5_Insync, &dev->flags) ||
+                                   ((i == sh->pd_idx || i == sh->qd_idx)  &&
+                                    s.failed == 0))
+                                       set_bit(STRIPE_INSYNC, &sh->state);
+                       }
+               }
+               if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
+                       s.dec_preread_active = 1;
+       }
+
+       /* Now to consider new write requests and what else, if anything
+        * should be read.  We do not handle new writes when:
+        * 1/ A 'write' operation (copy+xor) is already in flight.
+        * 2/ A 'check' operation is in flight, as it may clobber the parity
+        *    block.
+        */
+       if (s.to_write && !sh->reconstruct_state && !sh->check_state)
+               handle_stripe_dirtying(conf, sh, &s, disks);
+
+       /* 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.  The parity check is held off while parity
+        * dependent operations are in flight.
+        */
+       if (sh->check_state ||
+           (s.syncing && s.locked == 0 &&
+            !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
+            !test_bit(STRIPE_INSYNC, &sh->state))) {
+               if (conf->level == 6)
+                       handle_parity_checks6(conf, sh, &s, disks);
+               else
+                       handle_parity_checks5(conf, sh, &s, disks);
+       }
 
        if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
                md_done_sync(conf->mddev, STRIPE_SECTORS, 1);