]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/vdev_raidz_math_impl.h
Distributed Spare (dRAID) Feature
[mirror_zfs.git] / module / zfs / vdev_raidz_math_impl.h
index 89c2082c4ab93bec2d1a468483a520f9399c4013..35e016fc65a58102a669fc44317fd9593cd1a786 100644 (file)
@@ -26,6 +26,7 @@
 #define        _VDEV_RAIDZ_MATH_IMPL_H
 
 #include <sys/types.h>
+#include <sys/vdev_raidz_impl.h>
 
 #define        raidz_inline inline __attribute__((always_inline))
 #ifndef noinline
  * Functions calculate multiplication constants for data reconstruction.
  * Coefficients depend on RAIDZ geometry, indexes of failed child vdevs, and
  * used parity columns for reconstruction.
- * @rm                 RAIDZ map
+ * @rr                 RAIDZ row
  * @tgtidx             array of missing data indexes
  * @coeff              output array of coefficients. Array must be provided by
  *                     user and must hold minimum MUL_CNT values.
  */
 static noinline void
-raidz_rec_q_coeff(const raidz_map_t *rm, const int *tgtidx, unsigned *coeff)
+raidz_rec_q_coeff(const raidz_row_t *rr, const int *tgtidx, unsigned *coeff)
 {
-       const unsigned ncols = raidz_ncols(rm);
+       const unsigned ncols = rr->rr_cols;
        const unsigned x = tgtidx[TARGET_X];
 
        coeff[MUL_Q_X] = gf_exp2(255 - (ncols - x - 1));
 }
 
 static noinline void
-raidz_rec_r_coeff(const raidz_map_t *rm, const int *tgtidx, unsigned *coeff)
+raidz_rec_r_coeff(const raidz_row_t *rr, const int *tgtidx, unsigned *coeff)
 {
-       const unsigned ncols = raidz_ncols(rm);
+       const unsigned ncols = rr->rr_cols;
        const unsigned x = tgtidx[TARGET_X];
 
        coeff[MUL_R_X] = gf_exp4(255 - (ncols - x - 1));
 }
 
 static noinline void
-raidz_rec_pq_coeff(const raidz_map_t *rm, const int *tgtidx, unsigned *coeff)
+raidz_rec_pq_coeff(const raidz_row_t *rr, const int *tgtidx, unsigned *coeff)
 {
-       const unsigned ncols = raidz_ncols(rm);
+       const unsigned ncols = rr->rr_cols;
        const unsigned x = tgtidx[TARGET_X];
        const unsigned y = tgtidx[TARGET_Y];
        gf_t a, b, e;
@@ -76,9 +77,9 @@ raidz_rec_pq_coeff(const raidz_map_t *rm, const int *tgtidx, unsigned *coeff)
 }
 
 static noinline void
-raidz_rec_pr_coeff(const raidz_map_t *rm, const int *tgtidx, unsigned *coeff)
+raidz_rec_pr_coeff(const raidz_row_t *rr, const int *tgtidx, unsigned *coeff)
 {
-       const unsigned ncols = raidz_ncols(rm);
+       const unsigned ncols = rr->rr_cols;
        const unsigned x = tgtidx[TARGET_X];
        const unsigned y = tgtidx[TARGET_Y];
 
@@ -93,9 +94,9 @@ raidz_rec_pr_coeff(const raidz_map_t *rm, const int *tgtidx, unsigned *coeff)
 }
 
 static noinline void
-raidz_rec_qr_coeff(const raidz_map_t *rm, const int *tgtidx, unsigned *coeff)
+raidz_rec_qr_coeff(const raidz_row_t *rr, const int *tgtidx, unsigned *coeff)
 {
-       const unsigned ncols = raidz_ncols(rm);
+       const unsigned ncols = rr->rr_cols;
        const unsigned x = tgtidx[TARGET_X];
        const unsigned y = tgtidx[TARGET_Y];
 
@@ -114,9 +115,9 @@ raidz_rec_qr_coeff(const raidz_map_t *rm, const int *tgtidx, unsigned *coeff)
 }
 
 static noinline void
-raidz_rec_pqr_coeff(const raidz_map_t *rm, const int *tgtidx, unsigned *coeff)
+raidz_rec_pqr_coeff(const raidz_row_t *rr, const int *tgtidx, unsigned *coeff)
 {
-       const unsigned ncols = raidz_ncols(rm);
+       const unsigned ncols = rr->rr_cols;
        const unsigned x = tgtidx[TARGET_X];
        const unsigned y = tgtidx[TARGET_Y];
        const unsigned z = tgtidx[TARGET_Z];
@@ -347,26 +348,26 @@ raidz_mul_abd_cb(void *dc, size_t size, void *private)
 /*
  * Generate P parity (RAIDZ1)
  *
- * @rm RAIDZ map
+ * @rr RAIDZ row
  */
 static raidz_inline void
-raidz_generate_p_impl(raidz_map_t * const rm)
+raidz_generate_p_impl(raidz_row_t * const rr)
 {
        size_t c;
-       const size_t ncols = raidz_ncols(rm);
-       const size_t psize = rm->rm_col[CODE_P].rc_size;
-       abd_t *pabd = rm->rm_col[CODE_P].rc_abd;
+       const size_t ncols = rr->rr_cols;
+       const size_t psize = rr->rr_col[CODE_P].rc_size;
+       abd_t *pabd = rr->rr_col[CODE_P].rc_abd;
        size_t size;
        abd_t *dabd;
 
        raidz_math_begin();
 
        /* start with first data column */
-       raidz_copy(pabd, rm->rm_col[1].rc_abd, psize);
+       raidz_copy(pabd, rr->rr_col[1].rc_abd, psize);
 
        for (c = 2; c < ncols; c++) {
-               dabd = rm->rm_col[c].rc_abd;
-               size = rm->rm_col[c].rc_size;
+               dabd = rr->rr_col[c].rc_abd;
+               size = rr->rr_col[c].rc_size;
 
                /* add data column */
                raidz_add(pabd, dabd, size);
@@ -414,29 +415,29 @@ raidz_gen_pq_add(void **c, const void *dc, const size_t csize,
 /*
  * Generate PQ parity (RAIDZ2)
  *
- * @rm RAIDZ map
+ * @rr RAIDZ row
  */
 static raidz_inline void
-raidz_generate_pq_impl(raidz_map_t * const rm)
+raidz_generate_pq_impl(raidz_row_t * const rr)
 {
        size_t c;
-       const size_t ncols = raidz_ncols(rm);
-       const size_t csize = rm->rm_col[CODE_P].rc_size;
+       const size_t ncols = rr->rr_cols;
+       const size_t csize = rr->rr_col[CODE_P].rc_size;
        size_t dsize;
        abd_t *dabd;
        abd_t *cabds[] = {
-               rm->rm_col[CODE_P].rc_abd,
-               rm->rm_col[CODE_Q].rc_abd
+               rr->rr_col[CODE_P].rc_abd,
+               rr->rr_col[CODE_Q].rc_abd
        };
 
        raidz_math_begin();
 
-       raidz_copy(cabds[CODE_P], rm->rm_col[2].rc_abd, csize);
-       raidz_copy(cabds[CODE_Q], rm->rm_col[2].rc_abd, csize);
+       raidz_copy(cabds[CODE_P], rr->rr_col[2].rc_abd, csize);
+       raidz_copy(cabds[CODE_Q], rr->rr_col[2].rc_abd, csize);
 
        for (c = 3; c < ncols; c++) {
-               dabd = rm->rm_col[c].rc_abd;
-               dsize = rm->rm_col[c].rc_size;
+               dabd = rr->rr_col[c].rc_abd;
+               dsize = rr->rr_col[c].rc_size;
 
                abd_raidz_gen_iterate(cabds, dabd, csize, dsize, 2,
                    raidz_gen_pq_add);
@@ -487,31 +488,31 @@ raidz_gen_pqr_add(void **c, const void *dc, const size_t csize,
 /*
  * Generate PQR parity (RAIDZ2)
  *
- * @rm RAIDZ map
+ * @rr RAIDZ row
  */
 static raidz_inline void
-raidz_generate_pqr_impl(raidz_map_t * const rm)
+raidz_generate_pqr_impl(raidz_row_t * const rr)
 {
        size_t c;
-       const size_t ncols = raidz_ncols(rm);
-       const size_t csize = rm->rm_col[CODE_P].rc_size;
+       const size_t ncols = rr->rr_cols;
+       const size_t csize = rr->rr_col[CODE_P].rc_size;
        size_t dsize;
        abd_t *dabd;
        abd_t *cabds[] = {
-               rm->rm_col[CODE_P].rc_abd,
-               rm->rm_col[CODE_Q].rc_abd,
-               rm->rm_col[CODE_R].rc_abd
+               rr->rr_col[CODE_P].rc_abd,
+               rr->rr_col[CODE_Q].rc_abd,
+               rr->rr_col[CODE_R].rc_abd
        };
 
        raidz_math_begin();
 
-       raidz_copy(cabds[CODE_P], rm->rm_col[3].rc_abd, csize);
-       raidz_copy(cabds[CODE_Q], rm->rm_col[3].rc_abd, csize);
-       raidz_copy(cabds[CODE_R], rm->rm_col[3].rc_abd, csize);
+       raidz_copy(cabds[CODE_P], rr->rr_col[3].rc_abd, csize);
+       raidz_copy(cabds[CODE_Q], rr->rr_col[3].rc_abd, csize);
+       raidz_copy(cabds[CODE_R], rr->rr_col[3].rc_abd, csize);
 
        for (c = 4; c < ncols; c++) {
-               dabd = rm->rm_col[c].rc_abd;
-               dsize = rm->rm_col[c].rc_size;
+               dabd = rr->rr_col[c].rc_abd;
+               dsize = rr->rr_col[c].rc_size;
 
                abd_raidz_gen_iterate(cabds, dabd, csize, dsize, 3,
                    raidz_gen_pqr_add);
@@ -579,33 +580,36 @@ raidz_generate_pqr_impl(raidz_map_t * const rm)
  * @syn_method raidz_add_abd()
  * @rec_method not applicable
  *
- * @rm         RAIDZ map
+ * @rr         RAIDZ row
  * @tgtidx     array of missing data indexes
  */
 static raidz_inline int
-raidz_reconstruct_p_impl(raidz_map_t *rm, const int *tgtidx)
+raidz_reconstruct_p_impl(raidz_row_t *rr, const int *tgtidx)
 {
        size_t c;
-       const size_t firstdc = raidz_parity(rm);
-       const size_t ncols = raidz_ncols(rm);
+       const size_t firstdc = rr->rr_firstdatacol;
+       const size_t ncols = rr->rr_cols;
        const size_t x = tgtidx[TARGET_X];
-       const size_t xsize = rm->rm_col[x].rc_size;
-       abd_t *xabd = rm->rm_col[x].rc_abd;
+       const size_t xsize = rr->rr_col[x].rc_size;
+       abd_t *xabd = rr->rr_col[x].rc_abd;
        size_t size;
        abd_t *dabd;
 
+       if (xabd == NULL)
+               return (1 << CODE_P);
+
        raidz_math_begin();
 
        /* copy P into target */
-       raidz_copy(xabd, rm->rm_col[CODE_P].rc_abd, xsize);
+       raidz_copy(xabd, rr->rr_col[CODE_P].rc_abd, xsize);
 
        /* generate p_syndrome */
        for (c = firstdc; c < ncols; c++) {
                if (c == x)
                        continue;
 
-               dabd = rm->rm_col[c].rc_abd;
-               size = MIN(rm->rm_col[c].rc_size, xsize);
+               dabd = rr->rr_col[c].rc_abd;
+               size = MIN(rr->rr_col[c].rc_size, xsize);
 
                raidz_add(xabd, dabd, size);
        }
@@ -653,30 +657,33 @@ raidz_syn_q_abd(void **xc, const void *dc, const size_t xsize,
  * @syn_method raidz_add_abd()
  * @rec_method raidz_mul_abd_cb()
  *
- * @rm         RAIDZ map
+ * @rr         RAIDZ row
  * @tgtidx     array of missing data indexes
  */
 static raidz_inline int
-raidz_reconstruct_q_impl(raidz_map_t *rm, const int *tgtidx)
+raidz_reconstruct_q_impl(raidz_row_t *rr, const int *tgtidx)
 {
        size_t c;
        size_t dsize;
        abd_t *dabd;
-       const size_t firstdc = raidz_parity(rm);
-       const size_t ncols = raidz_ncols(rm);
+       const size_t firstdc = rr->rr_firstdatacol;
+       const size_t ncols = rr->rr_cols;
        const size_t x = tgtidx[TARGET_X];
-       abd_t *xabd = rm->rm_col[x].rc_abd;
-       const size_t xsize = rm->rm_col[x].rc_size;
+       abd_t *xabd = rr->rr_col[x].rc_abd;
+       const size_t xsize = rr->rr_col[x].rc_size;
        abd_t *tabds[] = { xabd };
 
+       if (xabd == NULL)
+               return (1 << CODE_Q);
+
        unsigned coeff[MUL_CNT];
-       raidz_rec_q_coeff(rm, tgtidx, coeff);
+       raidz_rec_q_coeff(rr, tgtidx, coeff);
 
        raidz_math_begin();
 
        /* Start with first data column if present */
        if (firstdc != x) {
-               raidz_copy(xabd, rm->rm_col[firstdc].rc_abd, xsize);
+               raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
        } else {
                raidz_zero(xabd, xsize);
        }
@@ -687,8 +694,8 @@ raidz_reconstruct_q_impl(raidz_map_t *rm, const int *tgtidx)
                        dabd = NULL;
                        dsize = 0;
                } else {
-                       dabd = rm->rm_col[c].rc_abd;
-                       dsize = rm->rm_col[c].rc_size;
+                       dabd = rr->rr_col[c].rc_abd;
+                       dsize = rr->rr_col[c].rc_size;
                }
 
                abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 1,
@@ -696,7 +703,7 @@ raidz_reconstruct_q_impl(raidz_map_t *rm, const int *tgtidx)
        }
 
        /* add Q to the syndrome */
-       raidz_add(xabd, rm->rm_col[CODE_Q].rc_abd, xsize);
+       raidz_add(xabd, rr->rr_col[CODE_Q].rc_abd, xsize);
 
        /* transform the syndrome */
        abd_iterate_func(xabd, 0, xsize, raidz_mul_abd_cb, (void*) coeff);
@@ -744,30 +751,33 @@ raidz_syn_r_abd(void **xc, const void *dc, const size_t tsize,
  * @syn_method raidz_add_abd()
  * @rec_method raidz_mul_abd_cb()
  *
- * @rm         RAIDZ map
+ * @rr         RAIDZ rr
  * @tgtidx     array of missing data indexes
  */
 static raidz_inline int
-raidz_reconstruct_r_impl(raidz_map_t *rm, const int *tgtidx)
+raidz_reconstruct_r_impl(raidz_row_t *rr, const int *tgtidx)
 {
        size_t c;
        size_t dsize;
        abd_t *dabd;
-       const size_t firstdc = raidz_parity(rm);
-       const size_t ncols = raidz_ncols(rm);
+       const size_t firstdc = rr->rr_firstdatacol;
+       const size_t ncols = rr->rr_cols;
        const size_t x = tgtidx[TARGET_X];
-       const size_t xsize = rm->rm_col[x].rc_size;
-       abd_t *xabd = rm->rm_col[x].rc_abd;
+       const size_t xsize = rr->rr_col[x].rc_size;
+       abd_t *xabd = rr->rr_col[x].rc_abd;
        abd_t *tabds[] = { xabd };
 
+       if (xabd == NULL)
+               return (1 << CODE_R);
+
        unsigned coeff[MUL_CNT];
-       raidz_rec_r_coeff(rm, tgtidx, coeff);
+       raidz_rec_r_coeff(rr, tgtidx, coeff);
 
        raidz_math_begin();
 
        /* Start with first data column if present */
        if (firstdc != x) {
-               raidz_copy(xabd, rm->rm_col[firstdc].rc_abd, xsize);
+               raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
        } else {
                raidz_zero(xabd, xsize);
        }
@@ -779,8 +789,8 @@ raidz_reconstruct_r_impl(raidz_map_t *rm, const int *tgtidx)
                        dabd = NULL;
                        dsize = 0;
                } else {
-                       dabd = rm->rm_col[c].rc_abd;
-                       dsize = rm->rm_col[c].rc_size;
+                       dabd = rr->rr_col[c].rc_abd;
+                       dsize = rr->rr_col[c].rc_size;
                }
 
                abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 1,
@@ -788,7 +798,7 @@ raidz_reconstruct_r_impl(raidz_map_t *rm, const int *tgtidx)
        }
 
        /* add R to the syndrome */
-       raidz_add(xabd, rm->rm_col[CODE_R].rc_abd, xsize);
+       raidz_add(xabd, rr->rr_col[CODE_R].rc_abd, xsize);
 
        /* transform the syndrome */
        abd_iterate_func(xabd, 0, xsize, raidz_mul_abd_cb, (void *)coeff);
@@ -881,31 +891,34 @@ raidz_rec_pq_abd(void **tc, const size_t tsize, void **c,
  * @syn_method raidz_syn_pq_abd()
  * @rec_method raidz_rec_pq_abd()
  *
- * @rm         RAIDZ map
+ * @rr         RAIDZ row
  * @tgtidx     array of missing data indexes
  */
 static raidz_inline int
-raidz_reconstruct_pq_impl(raidz_map_t *rm, const int *tgtidx)
+raidz_reconstruct_pq_impl(raidz_row_t *rr, const int *tgtidx)
 {
        size_t c;
        size_t dsize;
        abd_t *dabd;
-       const size_t firstdc = raidz_parity(rm);
-       const size_t ncols = raidz_ncols(rm);
+       const size_t firstdc = rr->rr_firstdatacol;
+       const size_t ncols = rr->rr_cols;
        const size_t x = tgtidx[TARGET_X];
        const size_t y = tgtidx[TARGET_Y];
-       const size_t xsize = rm->rm_col[x].rc_size;
-       const size_t ysize = rm->rm_col[y].rc_size;
-       abd_t *xabd = rm->rm_col[x].rc_abd;
-       abd_t *yabd = rm->rm_col[y].rc_abd;
+       const size_t xsize = rr->rr_col[x].rc_size;
+       const size_t ysize = rr->rr_col[y].rc_size;
+       abd_t *xabd = rr->rr_col[x].rc_abd;
+       abd_t *yabd = rr->rr_col[y].rc_abd;
        abd_t *tabds[2] = { xabd, yabd };
        abd_t *cabds[] = {
-               rm->rm_col[CODE_P].rc_abd,
-               rm->rm_col[CODE_Q].rc_abd
+               rr->rr_col[CODE_P].rc_abd,
+               rr->rr_col[CODE_Q].rc_abd
        };
 
+       if (xabd == NULL)
+               return ((1 << CODE_P) | (1 << CODE_Q));
+
        unsigned coeff[MUL_CNT];
-       raidz_rec_pq_coeff(rm, tgtidx, coeff);
+       raidz_rec_pq_coeff(rr, tgtidx, coeff);
 
        /*
         * Check if some of targets is shorter then others
@@ -921,8 +934,8 @@ raidz_reconstruct_pq_impl(raidz_map_t *rm, const int *tgtidx)
 
        /* Start with first data column if present */
        if (firstdc != x) {
-               raidz_copy(xabd, rm->rm_col[firstdc].rc_abd, xsize);
-               raidz_copy(yabd, rm->rm_col[firstdc].rc_abd, xsize);
+               raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
+               raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, xsize);
        } else {
                raidz_zero(xabd, xsize);
                raidz_zero(yabd, xsize);
@@ -934,8 +947,8 @@ raidz_reconstruct_pq_impl(raidz_map_t *rm, const int *tgtidx)
                        dabd = NULL;
                        dsize = 0;
                } else {
-                       dabd = rm->rm_col[c].rc_abd;
-                       dsize = rm->rm_col[c].rc_size;
+                       dabd = rr->rr_col[c].rc_abd;
+                       dsize = rr->rr_col[c].rc_size;
                }
 
                abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 2,
@@ -946,7 +959,7 @@ raidz_reconstruct_pq_impl(raidz_map_t *rm, const int *tgtidx)
 
        /* Copy shorter targets back to the original abd buffer */
        if (ysize < xsize)
-               raidz_copy(rm->rm_col[y].rc_abd, yabd, ysize);
+               raidz_copy(rr->rr_col[y].rc_abd, yabd, ysize);
 
        raidz_math_end();
 
@@ -1038,30 +1051,34 @@ raidz_rec_pr_abd(void **t, const size_t tsize, void **c,
  * @syn_method raidz_syn_pr_abd()
  * @rec_method raidz_rec_pr_abd()
  *
- * @rm         RAIDZ map
+ * @rr         RAIDZ row
  * @tgtidx     array of missing data indexes
  */
 static raidz_inline int
-raidz_reconstruct_pr_impl(raidz_map_t *rm, const int *tgtidx)
+raidz_reconstruct_pr_impl(raidz_row_t *rr, const int *tgtidx)
 {
        size_t c;
        size_t dsize;
        abd_t *dabd;
-       const size_t firstdc = raidz_parity(rm);
-       const size_t ncols = raidz_ncols(rm);
+       const size_t firstdc = rr->rr_firstdatacol;
+       const size_t ncols = rr->rr_cols;
        const size_t x = tgtidx[0];
        const size_t y = tgtidx[1];
-       const size_t xsize = rm->rm_col[x].rc_size;
-       const size_t ysize = rm->rm_col[y].rc_size;
-       abd_t *xabd = rm->rm_col[x].rc_abd;
-       abd_t *yabd = rm->rm_col[y].rc_abd;
+       const size_t xsize = rr->rr_col[x].rc_size;
+       const size_t ysize = rr->rr_col[y].rc_size;
+       abd_t *xabd = rr->rr_col[x].rc_abd;
+       abd_t *yabd = rr->rr_col[y].rc_abd;
        abd_t *tabds[2] = { xabd, yabd };
        abd_t *cabds[] = {
-               rm->rm_col[CODE_P].rc_abd,
-               rm->rm_col[CODE_R].rc_abd
+               rr->rr_col[CODE_P].rc_abd,
+               rr->rr_col[CODE_R].rc_abd
        };
+
+       if (xabd == NULL)
+               return ((1 << CODE_P) | (1 << CODE_R));
+
        unsigned coeff[MUL_CNT];
-       raidz_rec_pr_coeff(rm, tgtidx, coeff);
+       raidz_rec_pr_coeff(rr, tgtidx, coeff);
 
        /*
         * Check if some of targets are shorter then others.
@@ -1077,8 +1094,8 @@ raidz_reconstruct_pr_impl(raidz_map_t *rm, const int *tgtidx)
 
        /* Start with first data column if present */
        if (firstdc != x) {
-               raidz_copy(xabd, rm->rm_col[firstdc].rc_abd, xsize);
-               raidz_copy(yabd, rm->rm_col[firstdc].rc_abd, xsize);
+               raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
+               raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, xsize);
        } else {
                raidz_zero(xabd, xsize);
                raidz_zero(yabd, xsize);
@@ -1090,8 +1107,8 @@ raidz_reconstruct_pr_impl(raidz_map_t *rm, const int *tgtidx)
                        dabd = NULL;
                        dsize = 0;
                } else {
-                       dabd = rm->rm_col[c].rc_abd;
-                       dsize = rm->rm_col[c].rc_size;
+                       dabd = rr->rr_col[c].rc_abd;
+                       dsize = rr->rr_col[c].rc_size;
                }
 
                abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 2,
@@ -1104,14 +1121,14 @@ raidz_reconstruct_pr_impl(raidz_map_t *rm, const int *tgtidx)
         * Copy shorter targets back to the original abd buffer
         */
        if (ysize < xsize)
-               raidz_copy(rm->rm_col[y].rc_abd, yabd, ysize);
+               raidz_copy(rr->rr_col[y].rc_abd, yabd, ysize);
 
        raidz_math_end();
 
        if (ysize < xsize)
                abd_free(yabd);
 
-       return ((1 << CODE_P) | (1 << CODE_Q));
+       return ((1 << CODE_P) | (1 << CODE_R));
 }
 
 
@@ -1201,30 +1218,34 @@ raidz_rec_qr_abd(void **t, const size_t tsize, void **c,
  * @syn_method raidz_syn_qr_abd()
  * @rec_method raidz_rec_qr_abd()
  *
- * @rm         RAIDZ map
+ * @rr         RAIDZ row
  * @tgtidx     array of missing data indexes
  */
 static raidz_inline int
-raidz_reconstruct_qr_impl(raidz_map_t *rm, const int *tgtidx)
+raidz_reconstruct_qr_impl(raidz_row_t *rr, const int *tgtidx)
 {
        size_t c;
        size_t dsize;
        abd_t *dabd;
-       const size_t firstdc = raidz_parity(rm);
-       const size_t ncols = raidz_ncols(rm);
+       const size_t firstdc = rr->rr_firstdatacol;
+       const size_t ncols = rr->rr_cols;
        const size_t x = tgtidx[TARGET_X];
        const size_t y = tgtidx[TARGET_Y];
-       const size_t xsize = rm->rm_col[x].rc_size;
-       const size_t ysize = rm->rm_col[y].rc_size;
-       abd_t *xabd = rm->rm_col[x].rc_abd;
-       abd_t *yabd = rm->rm_col[y].rc_abd;
+       const size_t xsize = rr->rr_col[x].rc_size;
+       const size_t ysize = rr->rr_col[y].rc_size;
+       abd_t *xabd = rr->rr_col[x].rc_abd;
+       abd_t *yabd = rr->rr_col[y].rc_abd;
        abd_t *tabds[2] = { xabd, yabd };
        abd_t *cabds[] = {
-               rm->rm_col[CODE_Q].rc_abd,
-               rm->rm_col[CODE_R].rc_abd
+               rr->rr_col[CODE_Q].rc_abd,
+               rr->rr_col[CODE_R].rc_abd
        };
+
+       if (xabd == NULL)
+               return ((1 << CODE_Q) | (1 << CODE_R));
+
        unsigned coeff[MUL_CNT];
-       raidz_rec_qr_coeff(rm, tgtidx, coeff);
+       raidz_rec_qr_coeff(rr, tgtidx, coeff);
 
        /*
         * Check if some of targets is shorter then others
@@ -1240,8 +1261,8 @@ raidz_reconstruct_qr_impl(raidz_map_t *rm, const int *tgtidx)
 
        /* Start with first data column if present */
        if (firstdc != x) {
-               raidz_copy(xabd, rm->rm_col[firstdc].rc_abd, xsize);
-               raidz_copy(yabd, rm->rm_col[firstdc].rc_abd, xsize);
+               raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
+               raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, xsize);
        } else {
                raidz_zero(xabd, xsize);
                raidz_zero(yabd, xsize);
@@ -1253,8 +1274,8 @@ raidz_reconstruct_qr_impl(raidz_map_t *rm, const int *tgtidx)
                        dabd = NULL;
                        dsize = 0;
                } else {
-                       dabd = rm->rm_col[c].rc_abd;
-                       dsize = rm->rm_col[c].rc_size;
+                       dabd = rr->rr_col[c].rc_abd;
+                       dsize = rr->rr_col[c].rc_size;
                }
 
                abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 2,
@@ -1267,7 +1288,7 @@ raidz_reconstruct_qr_impl(raidz_map_t *rm, const int *tgtidx)
         * Copy shorter targets back to the original abd buffer
         */
        if (ysize < xsize)
-               raidz_copy(rm->rm_col[y].rc_abd, yabd, ysize);
+               raidz_copy(rr->rr_col[y].rc_abd, yabd, ysize);
 
        raidz_math_end();
 
@@ -1384,34 +1405,38 @@ raidz_rec_pqr_abd(void **t, const size_t tsize, void **c,
  * @syn_method raidz_syn_pqr_abd()
  * @rec_method raidz_rec_pqr_abd()
  *
- * @rm         RAIDZ map
+ * @rr         RAIDZ row
  * @tgtidx     array of missing data indexes
  */
 static raidz_inline int
-raidz_reconstruct_pqr_impl(raidz_map_t *rm, const int *tgtidx)
+raidz_reconstruct_pqr_impl(raidz_row_t *rr, const int *tgtidx)
 {
        size_t c;
        size_t dsize;
        abd_t *dabd;
-       const size_t firstdc = raidz_parity(rm);
-       const size_t ncols = raidz_ncols(rm);
+       const size_t firstdc = rr->rr_firstdatacol;
+       const size_t ncols = rr->rr_cols;
        const size_t x = tgtidx[TARGET_X];
        const size_t y = tgtidx[TARGET_Y];
        const size_t z = tgtidx[TARGET_Z];
-       const size_t xsize = rm->rm_col[x].rc_size;
-       const size_t ysize = rm->rm_col[y].rc_size;
-       const size_t zsize = rm->rm_col[z].rc_size;
-       abd_t *xabd = rm->rm_col[x].rc_abd;
-       abd_t *yabd = rm->rm_col[y].rc_abd;
-       abd_t *zabd = rm->rm_col[z].rc_abd;
+       const size_t xsize = rr->rr_col[x].rc_size;
+       const size_t ysize = rr->rr_col[y].rc_size;
+       const size_t zsize = rr->rr_col[z].rc_size;
+       abd_t *xabd = rr->rr_col[x].rc_abd;
+       abd_t *yabd = rr->rr_col[y].rc_abd;
+       abd_t *zabd = rr->rr_col[z].rc_abd;
        abd_t *tabds[] = { xabd, yabd, zabd };
        abd_t *cabds[] = {
-               rm->rm_col[CODE_P].rc_abd,
-               rm->rm_col[CODE_Q].rc_abd,
-               rm->rm_col[CODE_R].rc_abd
+               rr->rr_col[CODE_P].rc_abd,
+               rr->rr_col[CODE_Q].rc_abd,
+               rr->rr_col[CODE_R].rc_abd
        };
+
+       if (xabd == NULL)
+               return ((1 << CODE_P) | (1 << CODE_Q) | (1 << CODE_R));
+
        unsigned coeff[MUL_CNT];
-       raidz_rec_pqr_coeff(rm, tgtidx, coeff);
+       raidz_rec_pqr_coeff(rr, tgtidx, coeff);
 
        /*
         * Check if some of targets is shorter then others
@@ -1431,9 +1456,9 @@ raidz_reconstruct_pqr_impl(raidz_map_t *rm, const int *tgtidx)
 
        /* Start with first data column if present */
        if (firstdc != x) {
-               raidz_copy(xabd, rm->rm_col[firstdc].rc_abd, xsize);
-               raidz_copy(yabd, rm->rm_col[firstdc].rc_abd, xsize);
-               raidz_copy(zabd, rm->rm_col[firstdc].rc_abd, xsize);
+               raidz_copy(xabd, rr->rr_col[firstdc].rc_abd, xsize);
+               raidz_copy(yabd, rr->rr_col[firstdc].rc_abd, xsize);
+               raidz_copy(zabd, rr->rr_col[firstdc].rc_abd, xsize);
        } else {
                raidz_zero(xabd, xsize);
                raidz_zero(yabd, xsize);
@@ -1446,8 +1471,8 @@ raidz_reconstruct_pqr_impl(raidz_map_t *rm, const int *tgtidx)
                        dabd = NULL;
                        dsize = 0;
                } else {
-                       dabd = rm->rm_col[c].rc_abd;
-                       dsize = rm->rm_col[c].rc_size;
+                       dabd = rr->rr_col[c].rc_abd;
+                       dsize = rr->rr_col[c].rc_size;
                }
 
                abd_raidz_gen_iterate(tabds, dabd, xsize, dsize, 3,
@@ -1460,9 +1485,9 @@ raidz_reconstruct_pqr_impl(raidz_map_t *rm, const int *tgtidx)
         * Copy shorter targets back to the original abd buffer
         */
        if (ysize < xsize)
-               raidz_copy(rm->rm_col[y].rc_abd, yabd, ysize);
+               raidz_copy(rr->rr_col[y].rc_abd, yabd, ysize);
        if (zsize < xsize)
-               raidz_copy(rm->rm_col[z].rc_abd, zabd, zsize);
+               raidz_copy(rr->rr_col[z].rc_abd, zabd, zsize);
 
        raidz_math_end();