Mainly copied from kernel code, with minor modification to follow the
new naming schema.

Signed-off-by: Qu Wenruo <quwen...@cn.fujitsu.com>
---
 raid56.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 raid56.h |  4 ++++
 2 files changed, 67 insertions(+)

diff --git a/raid56.c b/raid56.c
index 8c79c45..599533e 100644
--- a/raid56.c
+++ b/raid56.c
@@ -28,6 +28,7 @@
 #include "disk-io.h"
 #include "volumes.h"
 #include "utils.h"
+#include "raid56.h"
 
 /*
  * This is the C data type to use
@@ -170,3 +171,65 @@ int raid5_gen_result(int nr_devs, size_t stripe_len, int 
dest, void **data)
        }
        return 0;
 }
+
+int raid6_recov_data2(int nr_devs, size_t stripe_len, int dest1, int dest2,
+                     void **data)
+{
+       u8 *p, *q, *dp, *dq;
+       u8 px, qx, db;
+       const u8 *pbmul;        /* P multiplier table for B data */
+       const u8 *qmul;         /* Q multiplier table (for both) */
+       char *zero_mem1, *zero_mem2;
+       int ret = 0;
+
+       /* Early check */
+       if (dest1 < 0 || dest1 >= nr_devs - 2 ||
+           dest2 < 0 || dest2 >= nr_devs - 2 || dest1 >= dest2)
+               return -EINVAL;
+
+       zero_mem1 = calloc(1, stripe_len);
+       zero_mem2 = calloc(1, stripe_len);
+       if (!zero_mem1 || !zero_mem2) {
+               free(zero_mem1);
+               free(zero_mem2);
+               return -ENOMEM;
+       }
+
+       p = (u8 *)data[nr_devs - 2];
+       q = (u8 *)data[nr_devs - 1];
+
+       /* Compute syndrome with zero for the missing data pages
+          Use the dead data pages as temporary storage for
+          delta p and delta q */
+       dp = (u8 *)data[dest1];
+       data[dest1] = (void *)zero_mem1;
+       data[nr_devs - 2] = dp;
+       dq = (u8 *)data[dest2];
+       data[dest2] = (void *)zero_mem2;
+       data[nr_devs - 1] = dq;
+
+       raid6_gen_syndrome(nr_devs, stripe_len, data);
+
+       /* Restore pointer table */
+       data[dest1]   = dp;
+       data[dest2]   = dq;
+       data[nr_devs - 2] = p;
+       data[nr_devs - 1] = q;
+
+       /* Now, pick the proper data tables */
+       pbmul = raid6_gfmul[raid6_gfexi[dest2 - dest1]];
+       qmul  = raid6_gfmul[raid6_gfinv[raid6_gfexp[dest1]^raid6_gfexp[dest2]]];
+
+       /* Now do it... */
+       while ( stripe_len-- ) {
+               px    = *p ^ *dp;
+               qx    = qmul[*q ^ *dq];
+               *dq++ = db = pbmul[px] ^ qx; /* Reconstructed B */
+               *dp++ = db ^ px; /* Reconstructed A */
+               p++; q++;
+       }
+
+       free(zero_mem1);
+       free(zero_mem2);
+       return ret;
+}
diff --git a/raid56.h b/raid56.h
index a05c14b..46fd3a9 100644
--- a/raid56.h
+++ b/raid56.h
@@ -19,6 +19,10 @@
 void raid6_gen_syndrome(int disks, size_t bytes, void **ptrs);
 int raid5_gen_result(int nr_devs, size_t stripe_len, int dest, void **data);
 
+/* Recover 2 data */
+int raid6_recov_data2(int nr_devs, size_t stripe_len, int dest1, int dest2,
+                     void **data);
+
 /* Galois field tables */
 extern const u8 raid6_gfmul[256][256] __attribute__((aligned(256)));
 extern const u8 raid6_vgfmul[256][32] __attribute__((aligned(256)));
-- 
2.10.1



--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to