raid5-ppl: partial parity calculation optimization
authorArtur Paszkiewicz <artur.paszkiewicz@intel.com>
Tue, 4 Apr 2017 11:13:58 +0000 (13:13 +0200)
committerShaohua Li <shli@fb.com>
Mon, 10 Apr 2017 19:01:37 +0000 (12:01 -0700)
In case of read-modify-write, partial partity is the same as the result
of ops_run_prexor5(), so we can just copy sh->dev[pd_idx].page into
sh->ppl_page instead of calculating it again.

Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: Shaohua Li <shli@fb.com>
drivers/md/raid5-ppl.c
drivers/md/raid5.c

index 71968cf..4eb0ebc 100644 (file)
@@ -153,7 +153,7 @@ ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu,
                       struct dma_async_tx_descriptor *tx)
 {
        int disks = sh->disks;
-       struct page **xor_srcs = flex_array_get(percpu->scribble, 0);
+       struct page **srcs = flex_array_get(percpu->scribble, 0);
        int count = 0, pd_idx = sh->pd_idx, i;
        struct async_submit_ctl submit;
 
@@ -166,18 +166,18 @@ ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu,
         * differently.
         */
        if (sh->reconstruct_state == reconstruct_state_prexor_drain_run) {
-               /* rmw: xor old data and parity from updated disks */
-               for (i = disks; i--;) {
-                       struct r5dev *dev = &sh->dev[i];
-                       if (test_bit(R5_Wantdrain, &dev->flags) || i == pd_idx)
-                               xor_srcs[count++] = dev->page;
-               }
+               /*
+                * rmw: xor old data and parity from updated disks
+                * This is calculated earlier by ops_run_prexor5() so just copy
+                * the parity dev page.
+                */
+               srcs[count++] = sh->dev[pd_idx].page;
        } else if (sh->reconstruct_state == reconstruct_state_drain_run) {
                /* rcw: xor data from all not updated disks */
                for (i = disks; i--;) {
                        struct r5dev *dev = &sh->dev[i];
                        if (test_bit(R5_UPTODATE, &dev->flags))
-                               xor_srcs[count++] = dev->page;
+                               srcs[count++] = dev->page;
                }
        } else {
                return tx;
@@ -188,10 +188,10 @@ ops_run_partial_parity(struct stripe_head *sh, struct raid5_percpu *percpu,
                          + sizeof(struct page *) * (sh->disks + 2));
 
        if (count == 1)
-               tx = async_memcpy(sh->ppl_page, xor_srcs[0], 0, 0, PAGE_SIZE,
+               tx = async_memcpy(sh->ppl_page, srcs[0], 0, 0, PAGE_SIZE,
                                  &submit);
        else
-               tx = async_xor(sh->ppl_page, xor_srcs, 0, count, PAGE_SIZE,
+               tx = async_xor(sh->ppl_page, srcs, 0, count, PAGE_SIZE,
                               &submit);
 
        return tx;
index e04d7b1..f3692ff 100644 (file)
@@ -2079,9 +2079,6 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
                        async_tx_ack(tx);
        }
 
-       if (test_bit(STRIPE_OP_PARTIAL_PARITY, &ops_request))
-               tx = ops_run_partial_parity(sh, percpu, tx);
-
        if (test_bit(STRIPE_OP_PREXOR, &ops_request)) {
                if (level < 6)
                        tx = ops_run_prexor5(sh, percpu, tx);
@@ -2089,6 +2086,9 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
                        tx = ops_run_prexor6(sh, percpu, tx);
        }
 
+       if (test_bit(STRIPE_OP_PARTIAL_PARITY, &ops_request))
+               tx = ops_run_partial_parity(sh, percpu, tx);
+
        if (test_bit(STRIPE_OP_BIODRAIN, &ops_request)) {
                tx = ops_run_biodrain(sh, tx);
                overlap_clear++;