Merge branch 'topic/omap3isp' of git://git.kernel.org/pub/scm/linux/kernel/git/mcheha...
[firefly-linux-kernel-4.4.55.git] / fs / exofs / ore_raid.c
index d58a952e28bc774a0d6bca547de8c90ba643d629..7f20f25c232c453d631b817ad382d27fea83fba3 100644 (file)
@@ -218,20 +218,28 @@ static unsigned _sp2d_max_pg(struct __stripe_pages_2d *sp2d)
 static void _gen_xor_unit(struct __stripe_pages_2d *sp2d)
 {
        unsigned p;
+       unsigned tx_flags = ASYNC_TX_ACK;
+
+       if (sp2d->parity == 1)
+               tx_flags |= ASYNC_TX_XOR_ZERO_DST;
+
        for (p = 0; p < sp2d->pages_in_unit; p++) {
                struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
 
                if (!_1ps->write_count)
                        continue;
 
-               init_async_submit(&_1ps->submit,
-                       ASYNC_TX_XOR_ZERO_DST | ASYNC_TX_ACK,
+               init_async_submit(&_1ps->submit, tx_flags,
                        NULL, NULL, NULL, (addr_conv_t *)_1ps->scribble);
 
-               /* TODO: raid6 */
-               _1ps->tx = async_xor(_1ps->pages[sp2d->data_devs], _1ps->pages,
-                                    0, sp2d->data_devs, PAGE_SIZE,
-                                    &_1ps->submit);
+               if (sp2d->parity == 1)
+                       _1ps->tx = async_xor(_1ps->pages[sp2d->data_devs],
+                                               _1ps->pages, 0, sp2d->data_devs,
+                                               PAGE_SIZE, &_1ps->submit);
+               else /* parity == 2 */
+                       _1ps->tx = async_gen_syndrome(_1ps->pages, 0,
+                                               sp2d->data_devs + sp2d->parity,
+                                               PAGE_SIZE, &_1ps->submit);
        }
 
        for (p = 0; p < sp2d->pages_in_unit; p++) {
@@ -616,7 +624,7 @@ static int _read_4_write_execute(struct ore_io_state *ios)
 int _ore_add_parity_unit(struct ore_io_state *ios,
                            struct ore_striping_info *si,
                            struct ore_per_dev_state *per_dev,
-                           unsigned cur_len)
+                           unsigned cur_len, bool do_xor)
 {
        if (ios->reading) {
                if (per_dev->cur_sg >= ios->sgs_per_dev) {
@@ -641,9 +649,11 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
                        /* If first stripe, Read in all read4write pages
                         * (if needed) before we calculate the first parity.
                         */
-                       _read_4_write_first_stripe(ios);
+                       if (do_xor)
+                               _read_4_write_first_stripe(ios);
                }
-               if (!cur_len) /* If last stripe r4w pages of last stripe */
+               if (!cur_len && do_xor)
+                       /* If last stripe r4w pages of last stripe */
                        _read_4_write_last_stripe(ios);
                _read_4_write_execute(ios);
 
@@ -655,7 +665,7 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
                        ++(ios->cur_par_page);
                }
 
-               BUG_ON(si->cur_comp != sp2d->data_devs);
+               BUG_ON(si->cur_comp < sp2d->data_devs);
                BUG_ON(si->cur_pg + num_pages > sp2d->pages_in_unit);
 
                ret = _ore_add_stripe_unit(ios,  &array_start, 0, pages,
@@ -663,9 +673,10 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
                if (unlikely(ret))
                        return ret;
 
-               /* TODO: raid6 if (last_parity_dev) */
-               _gen_xor_unit(sp2d);
-               _sp2d_reset(sp2d, ios->r4w, ios->private);
+               if (do_xor) {
+                       _gen_xor_unit(sp2d);
+                       _sp2d_reset(sp2d, ios->r4w, ios->private);
+               }
        }
        return 0;
 }