summaryrefslogtreecommitdiff
path: root/kernel-lib
diff options
context:
space:
mode:
authorQu Wenruo <quwenruo@cn.fujitsu.com>2017-05-25 14:21:49 +0800
committerDavid Sterba <dsterba@suse.com>2017-07-03 13:35:11 +0200
commit008bbd88420390fd83de41baa6b17a7d7d5b92de (patch)
tree861429bab3e1cf7cb609cc92b72c089665c1e1ff /kernel-lib
parent9604ce49d651176349421e4f63916cd7b7c5b09c (diff)
btrfs-progs: raid56: Allow raid6 to recover data and P
Copied from kernel lib/raid6/recov.c. Minor modifications includes: - Rename from raid6_datap_recov_intx() to raid5_recov_datap() - Rename parameter from faila to dest1 Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'kernel-lib')
-rw-r--r--kernel-lib/raid56.c41
-rw-r--r--kernel-lib/raid56.h3
2 files changed, 44 insertions, 0 deletions
diff --git a/kernel-lib/raid56.c b/kernel-lib/raid56.c
index dca8f8d4..e078972b 100644
--- a/kernel-lib/raid56.c
+++ b/kernel-lib/raid56.c
@@ -239,3 +239,44 @@ int raid6_recov_data2(int nr_devs, size_t stripe_len, int dest1, int dest2,
free(zero_mem2);
return ret;
}
+
+/*
+ * Raid 6 recover code copied from kernel lib/raid6/recov.c
+ * - rename from raid6_datap_recov_intx1()
+ * - parameter changed from faila to dest1
+ */
+int raid6_recov_datap(int nr_devs, size_t stripe_len, int dest1, void **data)
+{
+ u8 *p, *q, *dq;
+ const u8 *qmul; /* Q multiplier table */
+ char *zero_mem;
+
+ p = (u8 *)data[nr_devs - 2];
+ q = (u8 *)data[nr_devs - 1];
+
+ zero_mem = calloc(1, stripe_len);
+ if (!zero_mem)
+ return -ENOMEM;
+
+ /* Compute syndrome with zero for the missing data page
+ Use the dead data page as temporary storage for delta q */
+ dq = (u8 *)data[dest1];
+ data[dest1] = (void *)zero_mem;
+ data[nr_devs - 1] = dq;
+
+ raid6_gen_syndrome(nr_devs, stripe_len, data);
+
+ /* Restore pointer table */
+ data[dest1] = dq;
+ data[nr_devs - 1] = q;
+
+ /* Now, pick the proper data tables */
+ qmul = raid6_gfmul[raid6_gfinv[raid6_gfexp[dest1]]];
+
+ /* Now do it... */
+ while ( stripe_len-- ) {
+ *p++ ^= *dq = qmul[*q ^ *dq];
+ q++; dq++;
+ }
+ return 0;
+}
diff --git a/kernel-lib/raid56.h b/kernel-lib/raid56.h
index 2b3e9010..39d43792 100644
--- a/kernel-lib/raid56.h
+++ b/kernel-lib/raid56.h
@@ -41,4 +41,7 @@ extern const u8 raid6_gfexi[256] __attribute__((aligned(256)));
int raid6_recov_data2(int nr_devs, size_t stripe_len, int dest1, int dest2,
void **data);
+/* Recover data and P */
+int raid6_recov_datap(int nr_devs, size_t stripe_len, int dest1, void **data);
+
#endif