mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Reviews again raid comments.
This commit is contained in:
parent
9c04a93b42
commit
2456e88132
1 changed files with 90 additions and 90 deletions
180
raid.c
180
raid.c
|
|
@ -16,57 +16,57 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* The RAID5/RAID6 support was originally derived from the libraid6 library
|
||||
* The RAID5 and RAID6 support were originally derived from the libraid6 library
|
||||
* by H. Peter Anvin released with license "GPL2 or any later version"
|
||||
* used in the Linux Kernel 2.6.38.
|
||||
* This support was later completely rewritten (many times), but the
|
||||
* H. Peter Anvin's Copyright may still apply.
|
||||
*
|
||||
* The RAIDTP/RAIDQP/RAIDPP/RAIDHP support is original work implemented
|
||||
* from scratch.
|
||||
* The RAIDTP (Triple Parity), RAIDQP (Quad parity), RAIDPP (Penta Parity) and
|
||||
* RAIDHP (Hexa parity) support is original work implemented from scratch.
|
||||
*
|
||||
* The RAID5 and RAID6 support works like the one implemented in the Linux
|
||||
* Kernel RAID and it's based on the Anvin's paper "The mathematics of RAID-6" [1].
|
||||
* For RAID5 and RAID6 it works like the Linux Kernel RAID and it's based on
|
||||
* the Anvin's paper "The mathematics of RAID-6" [1].
|
||||
*
|
||||
* We compute the parity in the Galois Field GF(2^8) with the primitive
|
||||
* polynomial x^8 + x^4 + x^3 + x^2 + 1 (285 decimal), starting from a set
|
||||
* of n disk Di with 0<=i<n, using the equations:
|
||||
* of N disk Di with 0<=i<N, using the equations:
|
||||
*
|
||||
* P = sum(Di)
|
||||
* Q = sum(2^i * Di) with 0<=i<n
|
||||
* Q = sum(2^i * Di) with 0<=i<N
|
||||
*
|
||||
* To support RAIDTP (Triple Parity), it was first evaluated (and then dropped),
|
||||
* to use an extension of the same approach, with additional parity
|
||||
* coefficients set as powers of 4 with equations:
|
||||
* To support RAIDTP (Triple Parity), it was first evaluated, and then dropped,
|
||||
* the use of an extension of the same approach, with additional parity
|
||||
* coefficients set as powers of 4, with equations:
|
||||
*
|
||||
* P = sum(Di)
|
||||
* Q = sum(2^i * Di)
|
||||
* R = sum(4^i * Di) with 0<=i<n
|
||||
* R = sum(4^i * Di) with 0<=i<N
|
||||
*
|
||||
* This method is the same used by ZFS to implement its RAIDTP support,
|
||||
* This method is also the same used by ZFS to implement its RAIDZ3 support,
|
||||
* it works well, and it's very efficient.
|
||||
*
|
||||
* Unfortunately, the same approach doesn't work for RAIDQP (Quad Parity).
|
||||
* Using the parity coefficients set as power of 8 with equations:
|
||||
* Using additional parity coefficients set as power of 8 with equations:
|
||||
*
|
||||
* P = sum(Di)
|
||||
* Q = sum(2^i * Di)
|
||||
* R = sum(4^i * Di)
|
||||
* S = sum(8^i * Di) with 0<=i<n
|
||||
* S = sum(8^i * Di) with 0<=i<N
|
||||
*
|
||||
* we don't have a system of independent linear equations, and in some cases
|
||||
* the equations are not solvable.
|
||||
*
|
||||
* This approach is expected to fail at some point, because the Vandermonde
|
||||
* matrix used to compute the parity has no guarantee to have all its
|
||||
* matrix used to compute the parity has no guarantee to have all
|
||||
* submatrices not singular [2, Chap 11, Problem 7] and this is a requirement
|
||||
* to have a MDS code [2, Chap 11, Theorem 8].
|
||||
* to have a MDS (Maximum Distance Separable) code [2, Chap 11, Theorem 8].
|
||||
*
|
||||
* If it surprises that even using a Vandermonde matrix we don't have a
|
||||
* MDS code, consider that the matrix A we use to compute the parity, is
|
||||
* not the MDS generator matrix G, but only a submatrix of it. The generator
|
||||
* matrix G is the concatenation of I and A, as G = [I | A], where I is
|
||||
* the identity matrix.
|
||||
* not the MDS generator matrix G, but only a submatrix of it.
|
||||
* The generator matrix G is the concatenation of I and A, as G = [I | A],
|
||||
* where I is the identity matrix.
|
||||
* Setting the matrix G as Vandermonde matrix would have guaranteed to have
|
||||
* a MDS code, but setting only A as a Vandermonde matrix doesn't give
|
||||
* this guarantee.
|
||||
|
|
@ -74,11 +74,11 @@
|
|||
* Using the primitive polynomial 285, RAIDQP works for up to 21 data disks
|
||||
* with parity coefficients "1,2,4,8". Changing polynomial to one of 391/451/463/487,
|
||||
* it works for up to 27 disks with the same parity coefficients.
|
||||
* Using different parity coefficients "5,13,27,35" it's possible to
|
||||
* Using different parity coefficients, like "5,13,27,35", it's possible to
|
||||
* make it working for up to 33 disks. But no more.
|
||||
*
|
||||
* To support more disks it's possible to use the Galois Field GF(2^16) with
|
||||
* primitive polynomial 100087 or 122563 that supports up to Hexa (6) Parity
|
||||
* To support more disks it's possible to use GF(2^16) with primitive
|
||||
* polynomial 100087 or 122563 that supports up to Hexa (6) Parity
|
||||
* with parity coefficients 1,2,4,8,16,32 for up to 89 disks.
|
||||
*
|
||||
* To overcome these limitations we instead use an Extended Cauchy Matrix [3][4]
|
||||
|
|
@ -88,17 +88,17 @@
|
|||
* any number of parities and for any number of disks.
|
||||
*
|
||||
* The problem of this approach is that the coefficients of the equations
|
||||
* are not powers of the same value easy to compute.
|
||||
* We need to use multiplication tables to implement the parity computation,
|
||||
* instead of the parallel approach described in [1].
|
||||
* are not powers of the same value, not allowing to use the fast implementation
|
||||
* described in the Anvin's paper [1].
|
||||
*
|
||||
* Hopefully there is a method to implement parallel multiplication
|
||||
* with tables using SSSE3 instructions [1][5]. Method competitive with
|
||||
* the RAIDTP parity computation using power coefficients.
|
||||
* Hopefully there is a method to implement parallel multiplications
|
||||
* using SSSE3 instructions [1][5]. Method already competitive with the computation
|
||||
* of RAIDTP parity using power coefficients.
|
||||
*
|
||||
* Another important property of the Extended Cauchy matrix is that we can
|
||||
* setup the first two rows with coeffients equal at the RAID5 and RAID6
|
||||
* approach described in [1], resulting in a compatible extension.
|
||||
* setup the first two rows with power coeffients equal at the RAID5 and RAID6
|
||||
* approach described in Anvin's paper [1], resulting in a compatible extension,
|
||||
* and requiring SSSE3 instructions only if RAIDTP is used.
|
||||
*
|
||||
* We also "normalize" the matrix, multipling each row for a constant
|
||||
* factor to make the first column with all 1.
|
||||
|
|
@ -120,50 +120,27 @@
|
|||
*
|
||||
* This matrix can be extended to support any number of parities, just adding
|
||||
* additional rows, (but removing one column for each row added), without
|
||||
* the changing the already existing rows, and always maintaining the
|
||||
* guarantee to always have all square submatrices not singular.
|
||||
* the changing the already existing rows.
|
||||
* (see mktables.c for more details in how the matrix is generated)
|
||||
*
|
||||
* Resulting speed in x64, with 24 data disks, using a stripe of 256 KiB,
|
||||
* for a Core i7-3740QM CPU @ 2.7GHz is:
|
||||
*
|
||||
* int8 int32 int64 sse2 sse2e ssse3 ssse3e
|
||||
* raid5 9042 16698 26734
|
||||
* raid6 3205 5478 13987 16287
|
||||
* raidTP 828 6802 7186
|
||||
* raidQP 637 5483 5843
|
||||
* raidPP 513 4325 4629
|
||||
* raidHP 428 3479 3866
|
||||
*
|
||||
* Values are in MiB/s of data processed, not counting written parity.
|
||||
*
|
||||
* For comparison, a similar implementation using the power coeffients approach
|
||||
* in the same condition, is only a little faster (16%) for RAIDTP with power
|
||||
* coefficient "4", and equal for RAIDQP, that gets faster (10%) only using
|
||||
* AVX instructions.
|
||||
*
|
||||
* int32 int64 sse2 sse2e ssse3 ssse3e avxe
|
||||
* raidTP 1406 2522 7240 7886 8071 8358
|
||||
* raidQP 773 1375 4573 4678 5457 5778 6468
|
||||
*
|
||||
* In details parity is computed as:
|
||||
* In details, parity is computed as:
|
||||
*
|
||||
* P = sum(Di)
|
||||
* Q = sum(2^i * Di)
|
||||
* R = sum(A[2,i] * Di)
|
||||
* S = sum(A[3,i] * Di)
|
||||
* T = sum(A[4,i] * Di)
|
||||
* U = sum(A[5,i] * Di) with 0<=i<n
|
||||
* U = sum(A[5,i] * Di) with 0<=i<N
|
||||
*
|
||||
* To recover from a failure of six disks at indexes x,y,z,h,v,w,
|
||||
* with 0<=x<y<z<h<v<w<n, we compute the parity of the available n-6 disks as:
|
||||
* with 0<=x<y<z<h<v<w<N, we compute the parity of the available N-6 disks as:
|
||||
*
|
||||
* Pa = sum(Di)
|
||||
* Qa = sum(2^i * Di)
|
||||
* Ra = sum(A[2,i] * Di)
|
||||
* Sa = sum(A[3,i] * Di)
|
||||
* Ta = sum(A[4,i] * Di)
|
||||
* Ua = sum(A[5,i] * Di) with 0<=i<n,i!=x,i!=y,i!=z,i!=h,i!=v,i!=w.
|
||||
* Ua = sum(A[5,i] * Di) with 0<=i<N,i!=x,i!=y,i!=z,i!=h,i!=v,i!=w.
|
||||
*
|
||||
* And if we define:
|
||||
*
|
||||
|
|
@ -186,6 +163,29 @@
|
|||
* A linear system always solvable because the coefficients matrix is always
|
||||
* not singular due the properties of the matrix A[].
|
||||
*
|
||||
* Resulting speed in x64, with 24 data disks, using a stripe of 256 KiB,
|
||||
* for a Core i7-3740QM CPU @ 2.7GHz is:
|
||||
*
|
||||
* int8 int32 int64 sse2 sse2e ssse3 ssse3e
|
||||
* raid5 9042 16698 26734
|
||||
* raid6 3205 5478 13987 16287
|
||||
* raidTP 828 6802 7186
|
||||
* raidQP 637 5483 5843
|
||||
* raidPP 513 4325 4629
|
||||
* raidHP 428 3479 3866
|
||||
*
|
||||
* Values are in MiB/s of data processed, not counting generated parity.
|
||||
*
|
||||
* For comparison, a similar implementation using the power coeffients approach
|
||||
* in the same condition, is only a little faster (16%) for RAIDTP with power
|
||||
* coefficient "4", and equal for RAIDQP with power coefficient "8".
|
||||
* RAIDQP became faster (10%) only using AVX instructions, thanks of the better
|
||||
* registers allocation that AVX three operands PSHUFB makes possible.
|
||||
*
|
||||
* int32 int64 sse2 sse2e ssse3 ssse3e avxe
|
||||
* raidTP 1406 2522 7240 7886 8071 8358
|
||||
* raidQP 773 1375 4573 4678 5457 5778 6468
|
||||
*
|
||||
* References:
|
||||
* [1] Anvin, "The mathematics of RAID-6", 2004
|
||||
* [2] MacWilliams, Sloane, "The Theory of Error-Correcting Codes", 1977
|
||||
|
|
@ -420,10 +420,10 @@ void raid6_int64(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
static const struct raid_16_const {
|
||||
static const struct gfconst16 {
|
||||
unsigned char poly[16];
|
||||
unsigned char mask[16];
|
||||
} raid_16_const __attribute__((aligned(32))) = {
|
||||
} gfconst16 __attribute__((aligned(32))) = {
|
||||
{ 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d },
|
||||
{ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f }
|
||||
};
|
||||
|
|
@ -442,7 +442,7 @@ void raid6_sse2(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
p = vbuf[data];
|
||||
q = vbuf[data+1];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
|
||||
|
||||
for(i=0;i<size;i+=32) {
|
||||
asm volatile("movdqa %0,%%xmm0" : : "m" (vbuf[l][i]));
|
||||
|
|
@ -495,7 +495,7 @@ void raid6_sse2ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
p = vbuf[data];
|
||||
q = vbuf[data+1];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm15" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.poly[0]));
|
||||
|
||||
for(i=0;i<size;i+=64) {
|
||||
asm volatile("movdqa %0,%%xmm0" : : "m" (vbuf[l][i]));
|
||||
|
|
@ -609,8 +609,8 @@ void raidTP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
q = vbuf[data+1];
|
||||
r = vbuf[data+2];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
|
||||
for(i=0;i<size;i+=16) {
|
||||
asm volatile("pxor %xmm0,%xmm0");
|
||||
|
|
@ -668,8 +668,8 @@ void raidTP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
q = vbuf[data+1];
|
||||
r = vbuf[data+2];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm11" : : "m" (raid_16_const.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm11" : : "m" (gfconst16.mask[0]));
|
||||
|
||||
for(i=0;i<size;i+=32) {
|
||||
asm volatile("pxor %xmm0,%xmm0");
|
||||
|
|
@ -798,7 +798,7 @@ void raidQP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
asm volatile("pxor %xmm2,%xmm2");
|
||||
asm volatile("pxor %xmm3,%xmm3");
|
||||
for(d=l;d>=0;--d) {
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[d][i]));
|
||||
|
||||
asm volatile("pxor %xmm5,%xmm5");
|
||||
|
|
@ -807,7 +807,7 @@ void raidQP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
asm volatile("pand %xmm7,%xmm5");
|
||||
asm volatile("pxor %xmm5,%xmm1");
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
|
||||
asm volatile("pxor %xmm4,%xmm0");
|
||||
asm volatile("pxor %xmm4,%xmm1");
|
||||
|
|
@ -872,8 +872,8 @@ void raidQP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
asm volatile("pxor %xmm10,%xmm10");
|
||||
asm volatile("pxor %xmm11,%xmm11");
|
||||
for(d=l;d>=0;--d) {
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm15" : : "m" (raid_16_const.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[d][i]));
|
||||
asm volatile("movdqa %0,%%xmm12" : : "m" (vbuf[d][i+16]));
|
||||
|
||||
|
|
@ -1023,7 +1023,7 @@ void raidPP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
for(d=l;d>=0;--d) {
|
||||
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[d][i]));
|
||||
asm volatile("movdqa %0,%%xmm6" : : "m" (p0[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
|
||||
|
||||
asm volatile("pxor %xmm5,%xmm5");
|
||||
asm volatile("pcmpgtb %xmm0,%xmm5");
|
||||
|
|
@ -1035,7 +1035,7 @@ void raidPP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
asm volatile("pxor %xmm4,%xmm6");
|
||||
asm volatile("movdqa %%xmm6,%0" : "=m" (p0));
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
asm volatile("movdqa %xmm4,%xmm5");
|
||||
asm volatile("psraw $4,%xmm5");
|
||||
asm volatile("pand %xmm7,%xmm4");
|
||||
|
|
@ -1097,8 +1097,8 @@ void raidPP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
s = vbuf[data+3];
|
||||
t = vbuf[data+4];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm14" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm15" : : "m" (raid_16_const.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm14" : : "m" (gfconst16.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.mask[0]));
|
||||
|
||||
for(i=0;i<size;i+=16) {
|
||||
asm volatile("pxor %xmm0,%xmm0");
|
||||
|
|
@ -1243,7 +1243,7 @@ void raidHP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
for(d=l;d>=0;--d) {
|
||||
asm volatile("movdqa %0,%%xmm5" : : "m" (p0[0]));
|
||||
asm volatile("movdqa %0,%%xmm6" : : "m" (q0[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
|
||||
|
||||
asm volatile("pxor %xmm4,%xmm4");
|
||||
asm volatile("pcmpgtb %xmm6,%xmm4");
|
||||
|
|
@ -1258,7 +1258,7 @@ void raidHP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
asm volatile("movdqa %%xmm5,%0" : "=m" (p0));
|
||||
asm volatile("movdqa %%xmm6,%0" : "=m" (q0));
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
asm volatile("movdqa %xmm4,%xmm5");
|
||||
asm volatile("psraw $4,%xmm5");
|
||||
asm volatile("pand %xmm7,%xmm4");
|
||||
|
|
@ -1331,8 +1331,8 @@ void raidHP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
t = vbuf[data+4];
|
||||
u = vbuf[data+5];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm14" : : "m" (raid_16_const.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm15" : : "m" (raid_16_const.mask[0]));
|
||||
asm volatile("movdqa %0,%%xmm14" : : "m" (gfconst16.poly[0]));
|
||||
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.mask[0]));
|
||||
|
||||
for(i=0;i<size;i+=16) {
|
||||
asm volatile("pxor %xmm0,%xmm0");
|
||||
|
|
@ -1834,7 +1834,7 @@ static void raid6_recov_2data(const int* d, const int* e, unsigned char** vbuf,
|
|||
unsigned char* qa;
|
||||
const unsigned char* T[2];
|
||||
|
||||
/* select tables */
|
||||
/* get multiplication tables */
|
||||
T[0] = table( inv(pow2(d[1]-d[0]) ^ 1) );
|
||||
T[1] = table( inv(pow2(d[0]) ^ pow2(d[1])) );
|
||||
|
||||
|
|
@ -1956,7 +1956,7 @@ static void raid_recov_1data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
return;
|
||||
}
|
||||
|
||||
/* select tables */
|
||||
/* get multiplication tables */
|
||||
T[0] = table( inv(A(e[0],d[0])) );
|
||||
|
||||
/* compute delta parity */
|
||||
|
|
@ -2005,7 +2005,7 @@ static void raid_recov_2data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
return;
|
||||
}
|
||||
|
||||
/* setup the generator matrix */
|
||||
/* setup the coefficients matrix */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
G[i*N+j] = A(e[i],d[j]);
|
||||
|
|
@ -2015,7 +2015,7 @@ static void raid_recov_2data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
/* invert it to solve the system of linear equations */
|
||||
invert(G, V, N);
|
||||
|
||||
/* select tables */
|
||||
/* get multiplication tables */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
T[i][j] = table( V[i*N+j] );
|
||||
|
|
@ -2070,7 +2070,7 @@ static void raid_recov_3data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
unsigned char V[N*N];
|
||||
unsigned i, j;
|
||||
|
||||
/* setup the generator matrix */
|
||||
/* setup the coefficients matrix */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
G[i*N+j] = A(e[i],d[j]);
|
||||
|
|
@ -2080,7 +2080,7 @@ static void raid_recov_3data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
/* invert it to solve the system of linear equations */
|
||||
invert(G, V, N);
|
||||
|
||||
/* select tables */
|
||||
/* get multiplication tables */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
T[i][j] = table( V[i*N+j] );
|
||||
|
|
@ -2143,7 +2143,7 @@ static void raid_recov_4data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
unsigned char V[N*N];
|
||||
unsigned i, j;
|
||||
|
||||
/* setup the generator matrix */
|
||||
/* setup the coefficients matrix */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
G[i*N+j] = A(e[i],d[j]);
|
||||
|
|
@ -2153,7 +2153,7 @@ static void raid_recov_4data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
/* invert it to solve the system of linear equations */
|
||||
invert(G, V, N);
|
||||
|
||||
/* select tables */
|
||||
/* get multiplication tables */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
T[i][j] = table( V[i*N+j] );
|
||||
|
|
@ -2224,7 +2224,7 @@ static void raid_recov_5data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
unsigned char V[N*N];
|
||||
unsigned i, j;
|
||||
|
||||
/* setup the generator matrix */
|
||||
/* setup the coefficients matrix */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
G[i*N+j] = A(e[i],d[j]);
|
||||
|
|
@ -2234,7 +2234,7 @@ static void raid_recov_5data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
/* invert it to solve the system of linear equations */
|
||||
invert(G, V, N);
|
||||
|
||||
/* select tables */
|
||||
/* get multiplication tables */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
T[i][j] = table( V[i*N+j] );
|
||||
|
|
@ -2313,7 +2313,7 @@ static void raid_recov_6data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
unsigned char V[N*N];
|
||||
unsigned i, j;
|
||||
|
||||
/* setup the generator matrix */
|
||||
/* setup the coefficients matrix */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
G[i*N+j] = A(e[i],d[j]);
|
||||
|
|
@ -2323,7 +2323,7 @@ static void raid_recov_6data(const int* d, const int* e, unsigned char** vbuf, u
|
|||
/* invert it to solve the system of linear equations */
|
||||
invert(G, V, N);
|
||||
|
||||
/* select tables */
|
||||
/* get multiplication tables */
|
||||
for(i=0;i<N;++i) {
|
||||
for(j=0;j<N;++j) {
|
||||
T[i][j] = table( V[i*N+j] );
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue