diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2017-05-25 14:21:49 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2017-07-03 13:35:11 +0200 |
commit | 008bbd88420390fd83de41baa6b17a7d7d5b92de (patch) | |
tree | 861429bab3e1cf7cb609cc92b72c089665c1e1ff /kernel-lib | |
parent | 9604ce49d651176349421e4f63916cd7b7c5b09c (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.c | 41 | ||||
-rw-r--r-- | kernel-lib/raid56.h | 3 |
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 |