btrfs-progs: raid56: Allow raid6 to recover data and P
authorQu Wenruo <quwenruo@cn.fujitsu.com>
Thu, 25 May 2017 06:21:49 +0000 (14:21 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 3 Jul 2017 11:35:11 +0000 (13:35 +0200)
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>
kernel-lib/raid56.c
kernel-lib/raid56.h

index dca8f8d..e078972 100644 (file)
@@ -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;
+}
index 2b3e901..39d4379 100644 (file)
@@ -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