Changes the power coefficient for z-parity from 4 to 2^-1.

This commit is contained in:
Andrea Mazzoleni 2013-11-06 22:07:50 +01:00
parent a10e8d2c2a
commit 5c061e1dca
8 changed files with 203 additions and 189 deletions

9
TODO
View file

@ -22,13 +22,18 @@ This will also improve the cases of a crash during sync, because
we already have all the hashes when sync starts.
We need to extend the NEW blocks with an hash, likely using
the dummy 0 hash as marker for no hash.
And create a new block type REP (replaced) where the
hash is intented to match the new block and not the
previous one like for CHG blocks.
* When renaming to .unrecoverable at now we always overwrite
losing partial, but potentially better, previous copy of the files.
Is is possible a better strategy ?
a previous copy losing partial, but potentially better, file recovery.
Is it possible a better strategy ?
Maybe we can rename the unrecoverable as the real file, if the real file
is missing at the first open. This should ensure to always
get better results if the file is hashed.
Something like an incremental recovery, in case multiple fix commands
are attempted.
- Minor

View file

@ -156,7 +156,7 @@ void set_power(unsigned char* matrix)
v = 1;
for(i=0;i<DISK;++i) {
matrix[2*DISK+i] = v;
v = gfmul(4, v);
v = gfmul(0x8e, v);
}
}

253
raid.c
View file

@ -31,7 +31,7 @@
*/
/*
* The RAID5 and RAID6 support works like the Linux Kernel RAID
* The RAID5 and RAID6 support is implemented like the Linux Kernel RAID
* following the Anvin's paper "The mathematics of RAID-6" [1].
*
* We compute the parity in the Galois Field GF(2^8) with the primitive
@ -41,55 +41,39 @@
* P = sum(Di)
* Q = sum(2^i * Di) with 0<=i<N
*
* To support 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:
* To support triple parity, it was first evaluated, and then dropped, an
* extension of the same approach, with additional parity coefficients set
* as powers of 2^-1, with equations:
*
* P = sum(Di)
* Q = sum(2^i * Di)
* R = sum(4^i * Di) with 0<=i<N
* R = sum(2^-i * Di) with 0<=i<N
*
* 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 quad parity.
* Using additional parity coefficients set as power of 8 with equations:
* This approach works well for triple parity and it's very efficient,
* because we can implement very fast parallele multiplication and
* division by 2 in GF(2^8).
*
* P = sum(Di)
* Q = sum(2^i * Di)
* R = sum(4^i * Di)
* S = sum(8^i * Di) with 0<=i<N
* Unfortunately it doesn't work beyond triple parity, because whatever
* value we choose to generate the power coefficients to compute other
* parities, the resulting equations are not solvable for some
* combinations of missing disks.
*
* we don't have a system of always solvable equations.
* This is expected, because the Vandermonde 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 (Maximum Distance Separable) code [2, Chap 11, Theorem 8].
*
* This approach was expected to fail at some point, because the Vandermonde
* matrix of coefficents 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 (Maximum Distance Separable) code [2, Chap 11,
* Theorem 8].
* To overcome this limitation, we instead use a Cauchy matrix [3][4] to
* compute the parity. A Cauchy matrix has the property to have all the
* square submatrices not singular, resulting in always solvable equations,
* for any combination of missing disks.
*
* Using the primitive polynomial 285, quad parity 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, 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 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, but only for up to 89 disks.
*
* To overcome these limitations we instead use a Cauchy matrix [3][4]
* to compute the parity.
* Such matrix has the mathematical property to have all the square
* submatrices not singular, resulting in always solvable equations, for
* 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, not allowing to use the fast
* implementation described in the Anvin's paper [1].
* The problem of this approach is that it requires the use of
* multiplications by a generic value, and not only by 2 or 2^-1,
* potentially affecting badly the performance.
*
* Hopefully there is a method to implement parallel multiplications
* using SSSE3 instructions [1][5]. Method already competitive with the
* using SSSE3 instructions [1][5]. Method competitive with the
* computation of triple parity using power coefficients.
*
* Another important property of the Cauchy matrix is that we can setup
@ -97,9 +81,9 @@
* described in Anvin's paper [1], resulting in a compatible extension,
* and requiring SSSE3 instructions only if triple parity is used.
*
* We also adjust the matrix, multipling each row for a constant factor
* to make the first column with all 1, to optimize the computation
* for the first disk.
* The matrix is also adjusted, multipling each row by a constant factor
* to make the first column of all 1, to optimize the computation for
* the first disk.
*
* This results in the matrix A[row,col] defined as:
*
@ -172,19 +156,25 @@
* raidS6 449 4307 4789
*
* Values are in MiB/s of data processed, not counting generated parity.
*
* You can replicate these results in your machine using the "snapraid -T"
* command.
*
* For comparison, a similar implementation using the power coeffients
* approach, is only a little faster (5%) for RAIDS3 with power
* coefficient "4", and with equal speed for RAIDS4 with power coefficient
* "8", even using AVX instructions to get a better registers allocation
* with the three operands PSHUFB.
* For comparison, the triple parity computation using the power
* coeffients "1,2,2^-1" is only a little faster than the one based on
* the Cauchy matrix if SSSE3 is present. Instead, it's a lot faster if
* SSSE3 is not present.
*
* int8 int32 int64 sse2 sse2e ssse3 ssse3e
* raidZ3 2112 3118 9589 10304
*
*
* This makes the use of power coefficients still a good option to
* implement triple parity in CPUs without SSSE3.
* But if a modern CPU with SSSE3 (or similar) is available, the Cauchy
* matrix is the best option because it provides a general approach
* working for any number of parities.
*
* int32 int64 sse2 sse2e ssse3 ssse3e avxe
* raidZ3 1511 2775 8625 9336 9645 9966
* raidZ4 842 1518 5195 5507 6278 6737 7410
*
* References:
* [1] Anvin, "The mathematics of RAID-6", 2004
* [2] MacWilliams, Sloane, "The Theory of Error-Correcting Codes", 1977
@ -346,6 +336,32 @@ static inline uint64_t x2_64(uint64_t v)
return v;
}
/**
* Divide each byte of a uint32 by 2 in the GF(2^8).
*/
__attribute__((always_inline))
static inline uint32_t d2_32(uint32_t v)
{
uint32_t mask = v & 0x01010101U;
mask = (mask << 8) - mask;
v = (v >> 1) & 0x7f7f7f7fU;
v ^= mask & 0x8e8e8e8eU;
return v;
}
/**
* Divide each byte of a uint64 by 2 in the GF(2^8).
*/
__attribute__((always_inline))
static inline uint64_t d2_64(uint64_t v)
{
uint64_t mask = v & 0x0101010101010101U;
mask = (mask << 8) - mask;
v = (v >> 1) & 0x7f7f7f7f7f7f7f7fU;
v ^= mask & 0x8e8e8e8e8e8e8e8eU;
return v;
}
/*
* RAID6 32bit C implementation
*/
@ -429,10 +445,14 @@ void raid6_int64(unsigned char** vbuf, unsigned data, unsigned size)
#if defined(__i386__) || defined(__x86_64__)
static const struct gfconst16 {
unsigned char poly[16];
unsigned char mask[16];
} gfconst16 __attribute__((aligned(32))) = {
unsigned char low4[16];
unsigned char half[16];
unsigned char low7[16];
} gfconst16 __attribute__((aligned(64))) = {
{ 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 }
{ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f },
{ 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e },
{ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f }
};
/*
@ -597,10 +617,8 @@ void raidZ3_int32(unsigned char** vbuf, unsigned data, unsigned size)
q0 ^= d0;
q1 ^= d1;
r0 = x2_32(r0);
r1 = x2_32(r1);
r0 = x2_32(r0);
r1 = x2_32(r1);
r0 = d2_32(r0);
r1 = d2_32(r1);
r0 ^= d0;
r1 ^= d1;
@ -649,10 +667,8 @@ void raidZ3_int64(unsigned char** vbuf, unsigned data, unsigned size)
q0 ^= d0;
q1 ^= d1;
r0 = x2_64(r0);
r1 = x2_64(r1);
r0 = x2_64(r0);
r1 = x2_64(r1);
r0 = d2_64(r0);
r1 = d2_64(r1);
r0 ^= d0;
r1 ^= d1;
@ -684,6 +700,8 @@ void raidZ3_sse2(unsigned char** vbuf, unsigned data, unsigned size)
r = vbuf[data+2];
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
asm volatile("movdqa %0,%%xmm3" : : "m" (gfconst16.half[0]));
asm volatile("movdqa %0,%%xmm6" : : "m" (gfconst16.low7[0]));
for(i=0;i<size;i+=16) {
asm volatile("movdqa %0,%%xmm0" : : "m" (vbuf[l][i]));
@ -691,25 +709,24 @@ void raidZ3_sse2(unsigned char** vbuf, unsigned data, unsigned size)
asm volatile("movdqa %xmm0,%xmm2");
for(d=l-1;d>=0;--d) {
asm volatile("pxor %xmm4,%xmm4");
asm volatile("pxor %xmm5,%xmm5");
asm volatile("pxor %xmm6,%xmm6");
asm volatile("pcmpgtb %xmm1,%xmm4");
asm volatile("pcmpgtb %xmm2,%xmm5");
asm volatile("paddb %xmm1,%xmm1");
asm volatile("paddb %xmm2,%xmm2");
asm volatile("pand %xmm7,%xmm4");
asm volatile("pand %xmm7,%xmm5");
asm volatile("pxor %xmm4,%xmm1");
asm volatile("pxor %xmm5,%xmm2");
asm volatile("pcmpgtb %xmm2,%xmm6");
asm volatile("paddb %xmm2,%xmm2");
asm volatile("pand %xmm7,%xmm6");
asm volatile("pxor %xmm6,%xmm2");
asm volatile("movdqa %0,%%xmm3" : : "m" (vbuf[d][i]));
asm volatile("pxor %xmm3,%xmm0");
asm volatile("pxor %xmm3,%xmm1");
asm volatile("pxor %xmm3,%xmm2");
asm volatile("movdqa %xmm2,%xmm4");
asm volatile("pxor %xmm5,%xmm5");
asm volatile("psllw $7,%xmm4");
asm volatile("psrlw $1,%xmm2");
asm volatile("pcmpgtb %xmm4,%xmm5");
asm volatile("pand %xmm6,%xmm2");
asm volatile("pand %xmm3,%xmm5");
asm volatile("pxor %xmm5,%xmm2");
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[d][i]));
asm volatile("pxor %xmm4,%xmm0");
asm volatile("pxor %xmm4,%xmm1");
asm volatile("pxor %xmm4,%xmm2");
}
asm volatile("movntdq %%xmm0,%0" : "=m" (p[i]));
asm volatile("movntdq %%xmm1,%0" : "=m" (q[i]));
@ -740,6 +757,8 @@ void raidZ3_sse2ext(unsigned char** vbuf, unsigned data, unsigned size)
r = vbuf[data+2];
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
asm volatile("movdqa %0,%%xmm3" : : "m" (gfconst16.half[0]));
asm volatile("movdqa %0,%%xmm11" : : "m" (gfconst16.low7[0]));
for(i=0;i<size;i+=32) {
asm volatile("movdqa %0,%%xmm0" : : "m" (vbuf[l][i]));
@ -749,45 +768,41 @@ void raidZ3_sse2ext(unsigned char** vbuf, unsigned data, unsigned size)
asm volatile("movdqa %xmm0,%xmm2");
asm volatile("movdqa %xmm8,%xmm10");
for(d=l-1;d>=0;--d) {
asm volatile("movdqa %xmm2,%xmm6");
asm volatile("movdqa %xmm10,%xmm14");
asm volatile("pxor %xmm4,%xmm4");
asm volatile("pxor %xmm5,%xmm5");
asm volatile("pxor %xmm6,%xmm6");
asm volatile("pxor %xmm12,%xmm12");
asm volatile("pxor %xmm5,%xmm5");
asm volatile("pxor %xmm13,%xmm13");
asm volatile("pxor %xmm14,%xmm14");
asm volatile("psllw $7,%xmm6");
asm volatile("psllw $7,%xmm14");
asm volatile("psrlw $1,%xmm2");
asm volatile("psrlw $1,%xmm10");
asm volatile("pcmpgtb %xmm1,%xmm4");
asm volatile("pcmpgtb %xmm2,%xmm5");
asm volatile("pcmpgtb %xmm9,%xmm12");
asm volatile("pcmpgtb %xmm10,%xmm13");
asm volatile("pcmpgtb %xmm6,%xmm5");
asm volatile("pcmpgtb %xmm14,%xmm13");
asm volatile("paddb %xmm1,%xmm1");
asm volatile("paddb %xmm2,%xmm2");
asm volatile("paddb %xmm9,%xmm9");
asm volatile("paddb %xmm10,%xmm10");
asm volatile("pand %xmm11,%xmm2");
asm volatile("pand %xmm11,%xmm10");
asm volatile("pand %xmm7,%xmm4");
asm volatile("pand %xmm7,%xmm5");
asm volatile("pand %xmm7,%xmm12");
asm volatile("pand %xmm7,%xmm13");
asm volatile("pand %xmm3,%xmm5");
asm volatile("pand %xmm3,%xmm13");
asm volatile("pxor %xmm4,%xmm1");
asm volatile("pxor %xmm5,%xmm2");
asm volatile("pxor %xmm12,%xmm9");
asm volatile("pxor %xmm5,%xmm2");
asm volatile("pxor %xmm13,%xmm10");
asm volatile("pcmpgtb %xmm2,%xmm6");
asm volatile("pcmpgtb %xmm10,%xmm14");
asm volatile("paddb %xmm2,%xmm2");
asm volatile("paddb %xmm10,%xmm10");
asm volatile("pand %xmm7,%xmm6");
asm volatile("pand %xmm7,%xmm14");
asm volatile("pxor %xmm6,%xmm2");
asm volatile("pxor %xmm14,%xmm10");
asm volatile("movdqa %0,%%xmm3" : : "m" (vbuf[d][i]));
asm volatile("movdqa %0,%%xmm11" : : "m" (vbuf[d][i+16]));
asm volatile("pxor %xmm3,%xmm0");
asm volatile("pxor %xmm3,%xmm1");
asm volatile("pxor %xmm3,%xmm2");
asm volatile("pxor %xmm11,%xmm8");
asm volatile("pxor %xmm11,%xmm9");
asm volatile("pxor %xmm11,%xmm10");
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[d][i]));
asm volatile("movdqa %0,%%xmm12" : : "m" (vbuf[d][i+16]));
asm volatile("pxor %xmm4,%xmm0");
asm volatile("pxor %xmm4,%xmm1");
asm volatile("pxor %xmm4,%xmm2");
asm volatile("pxor %xmm12,%xmm8");
asm volatile("pxor %xmm12,%xmm9");
asm volatile("pxor %xmm12,%xmm10");
}
asm volatile("movntdq %%xmm0,%0" : "=m" (p[i]));
asm volatile("movntdq %%xmm8,%0" : "=m" (p[i+16]));
@ -865,7 +880,7 @@ void raidS3_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
r = vbuf[data+2];
asm volatile("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
for(i=0;i<size;i+=16) {
/* last disk without the by two multiplication */
@ -953,7 +968,7 @@ void raidS3_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
r = vbuf[data+2];
asm volatile("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0]));
asm volatile("movdqa %0,%%xmm11" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm11" : : "m" (gfconst16.low4[0]));
for(i=0;i<size;i+=32) {
/* last disk without the by two multiplication */
@ -1135,7 +1150,7 @@ void raidS4_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
for(i=0;i<size;i+=16) {
/* last disk without the by two multiplication */
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[l][i]));
asm volatile("movdqa %xmm4,%xmm0");
@ -1169,7 +1184,7 @@ void raidS4_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
asm volatile("pand %xmm7,%xmm5");
asm volatile("pxor %xmm5,%xmm1");
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
asm volatile("pxor %xmm4,%xmm0");
asm volatile("pxor %xmm4,%xmm1");
@ -1242,7 +1257,7 @@ void raidS4_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
for(i=0;i<size;i+=32) {
/* last disk without the by two multiplication */
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0]));
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[l][i]));
asm volatile("movdqa %0,%%xmm12" : : "m" (vbuf[l][i+16]));
@ -1285,7 +1300,7 @@ void raidS4_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
/* intermediate disks */
for(d=l-1;d>0;--d) {
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0]));
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[d][i]));
asm volatile("movdqa %0,%%xmm12" : : "m" (vbuf[d][i+16]));
@ -1343,7 +1358,7 @@ void raidS4_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
/* first disk with all coefficients at 1 */
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0]));
asm volatile("movdqa %0,%%xmm4" : : "m" (vbuf[0][i]));
asm volatile("movdqa %0,%%xmm12" : : "m" (vbuf[0][i+16]));
@ -1471,7 +1486,7 @@ void raidS5_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
asm volatile("movdqa %xmm4,%xmm0");
asm volatile("movdqa %%xmm4,%0" : "=m" (p0[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
asm volatile("movdqa %xmm4,%xmm5");
asm volatile("psrlw $4,%xmm5");
asm volatile("pand %xmm7,%xmm4");
@ -1511,7 +1526,7 @@ void raidS5_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
asm volatile("pxor %xmm4,%xmm6");
asm volatile("movdqa %%xmm6,%0" : "=m" (p0[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
asm volatile("movdqa %xmm4,%xmm5");
asm volatile("psrlw $4,%xmm5");
asm volatile("pand %xmm7,%xmm4");
@ -1591,7 +1606,7 @@ void raidS5_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
t = vbuf[data+4];
asm volatile("movdqa %0,%%xmm14" : : "m" (gfconst16.poly[0]));
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0]));
for(i=0;i<size;i+=16) {
/* last disk without the by two multiplication */
@ -1786,7 +1801,7 @@ void raidS6_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
asm volatile("movdqa %%xmm4,%0" : "=m" (p0[0]));
asm volatile("movdqa %%xmm4,%0" : "=m" (q0[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
asm volatile("movdqa %xmm4,%xmm5");
asm volatile("psrlw $4,%xmm5");
asm volatile("pand %xmm7,%xmm4");
@ -1835,7 +1850,7 @@ void raidS6_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
asm volatile("movdqa %%xmm5,%0" : "=m" (p0[0]));
asm volatile("movdqa %%xmm6,%0" : "=m" (q0[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
asm volatile("movdqa %xmm4,%xmm5");
asm volatile("psrlw $4,%xmm5");
asm volatile("pand %xmm7,%xmm4");
@ -1927,7 +1942,7 @@ void raidS6_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
u = vbuf[data+5];
asm volatile("movdqa %0,%%xmm14" : : "m" (gfconst16.poly[0]));
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0]));
for(i=0;i<size;i+=16) {
/* last disk without the by two multiplication */
@ -2561,7 +2576,7 @@ void raid_recov1_ssse3(unsigned level, const int* d, const int* c, unsigned char
p = vbuf[data+c[0]];
pa = vbuf[d[0]];
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
asm volatile("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0]));
asm volatile("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0]));
@ -2618,7 +2633,7 @@ void raid_recov2_ssse3(unsigned level, const int* d, const int* c, unsigned char
pa[i] = vbuf[d[i]];
}
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
for(i=0;i<size;i+=16) {
asm volatile("movdqa %0,%%xmm0" : : "m" (p[0][i]));
@ -2720,7 +2735,7 @@ void raid_recovX_ssse3(unsigned level, const int* d, const int* c, unsigned char
pa[i] = vbuf[d[i]];
}
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0]));
for(i=0;i<size;i+=16) {
unsigned char PD[RAID_PARITY_S_MAX][16] __attribute__((aligned(16)));

2
raid.h
View file

@ -36,7 +36,7 @@
* It has a fast implementation not requiring SSSE3 for triple parity.
* This is mostly intended for low end CPUs like ARM and AMD Athlon II.
*
* This is the mode used by ZFS.
* This is similar at the mode used by Linux Kernel RAID6 and ZFS RAIDZ.
*/
#define RAID_MODE_Z 1

View file

@ -814,25 +814,23 @@ they doesn\(cqt get fragmented, improving the performance.
.PP
These options are optional and they can be used only one time.
.SS z\(hyparity FILE
Defines an alternate file and format to store the triple parity,
instead of the other \(cqr\(hyparity\(cq one.
Defines an alternate file and format to store the triple parity.
.PP
It\(cqs mainly intended for low end CPUs like ARM or AMD Phenom, Athlon
and Opteron that don\(cqt support the SSSE3 instructions set, and in
such case it may provide better performance.
This option is an alternative at \(cqr\(hyparity\(cq mainly intended for
low end CPUs like ARM or AMD Phenom, Athlon and Opteron that don\(cqt
support the SSSE3 instructions set, and in such case it may provide
a better performance.
.PP
This is also the parity format used by ZFS, but it doesn\(cqt work
for beyond triple parity.
This format is similar at the one used by the Linux kernel RAID6 and
ZFS RAIDZ3, but it doesn\(cqt work for beyond triple parity.
.PP
If you are using the \(cqr\(hyparity\(cq you will be warned if it\(cqs
recommended to use the \(cqz\(hyparity\(cq format for a performance
If you are using the \(cqr\(hyparity\(cq you will be warned at very run
if it\(cqs recommended to use the \(cqz\(hyparity\(cq format for a performance
increase.
.PP
It\(cqs possible to convert from one format to another, adjusting
the configuraton file with the wanted z\(hyparity or r\(hyparity file,
and using \(cqfix\(cq to recreate it.
.PP
This option is alternative to \(cqr\(hyparity\(cq.
.SS content FILE
Defines the file to use to store the list and checksums of all the
files present in your disk array.

View file

@ -607,26 +607,24 @@ Configuration
These options are optional and they can be used only one time.
z-parity FILE
Defines an alternate file and format to store the triple parity,
instead of the other 'r-parity' one.
Defines an alternate file and format to store the triple parity.
It's mainly intended for low end CPUs like ARM or AMD Phenom, Athlon
and Opteron that don't support the SSSE3 instructions set, and in
such case it may provide better performance.
This option is an alternative at 'r-parity' mainly intended for
low end CPUs like ARM or AMD Phenom, Athlon and Opteron that don't
support the SSSE3 instructions set, and in such case it may provide
a better performance.
This is also the parity format used by ZFS, but it doesn't work
for beyond triple parity.
This format is similar at the one used by the Linux kernel RAID6 and
ZFS RAIDZ3, but it doesn't work for beyond triple parity.
If you are using the 'r-parity' you will be warned if it's
recommended to use the 'z-parity' format for a performance
If you are using the 'r-parity' you will be warned at very run
if it's recommended to use the 'z-parity' format for a performance
increase.
It's possible to convert from one format to another, adjusting
the configuraton file with the wanted z-parity or r-parity file,
and using 'fix' to recreate it.
This option is alternative to 'r-parity'.
content FILE
Defines the file to use to store the list and checksums of all the
files present in your disk array.

View file

@ -663,26 +663,24 @@ These options are optional and they can be used only one time.
7.3 z-parity FILE
-----------------
Defines an alternate file and format to store the triple parity,
instead of the other 'r-parity' one.
Defines an alternate file and format to store the triple parity.
It's mainly intended for low end CPUs like ARM or AMD Phenom, Athlon
and Opteron that don't support the SSSE3 instructions set, and in
such case it may provide better performance.
This option is an alternative at 'r-parity' mainly intended for
low end CPUs like ARM or AMD Phenom, Athlon and Opteron that don't
support the SSSE3 instructions set, and in such case it may provide
a better performance.
This is also the parity format used by ZFS, but it doesn't work
for beyond triple parity.
This format is similar at the one used by the Linux kernel RAID6 and
ZFS RAIDZ3, but it doesn't work for beyond triple parity.
If you are using the 'r-parity' you will be warned if it's
recommended to use the 'z-parity' format for a performance
If you are using the 'r-parity' you will be warned at very run
if it's recommended to use the 'z-parity' format for a performance
increase.
It's possible to convert from one format to another, adjusting
the configuraton file with the wanted z-parity or r-parity file,
and using 'fix' to recreate it.
This option is alternative to 'r-parity'.
7.4 content FILE
----------------

View file

@ -8802,7 +8802,7 @@ const unsigned char __attribute__((aligned(256))) gfinv[256] =
*
* 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01
* 01 02 04 08 10 20 40 80 1d 3a 74 e8 cd 87 13 26 4c 98 2d 5a b4 75 ea c9 8f 03 06 0c 18 30 60 c0 9d 27 4e 9c 25 4a 94 35 6a d4 b5 77 ee c1 9f 23 46 8c 05 0a 14 28 50 a0 5d ba 69 d2 b9 6f de a1 5f be 61 c2 99 2f 5e bc 65 ca 89 0f 1e 3c 78 f0 fd e7 d3 bb 6b d6 b1 7f fe e1 df a3 5b b6 71 e2 d9 af 43 86 11 22 44 88 0d 1a 34 68 d0 bd 67 ce 81 1f 3e 7c f8 ed c7 93 3b 76 ec c5 97 33 66 cc 85 17 2e 5c b8 6d da a9 4f 9e 21 42 84 15 2a 54 a8 4d 9a 29 52 a4 55 aa 49 92 39 72 e4 d5 b7 73 e6 d1 bf 63 c6 91 3f 7e fc e5 d7 b3 7b f6 f1 ff e3 db ab 4b 96 31 62 c4 95 37 6e dc a5 57 ae 41 82 19 32 64 c8 8d 07 0e 1c 38 70 e0 dd a7 53 a6 51 a2 59 b2 79 f2 f9 ef c3 9b 2b 56 ac 45 8a 09 12 24 48 90 3d 7a f4 f5 f7 f3 fb eb cb 8b 0b 16 2c 58 b0 7d fa e9 cf 83 1b 36 6c
* 01 04 10 40 1d 74 cd 13 4c 2d b4 ea 8f 06 18 60 9d 4e 25 94 6a b5 ee 9f 46 05 14 50 5d 69 b9 de 5f 61 99 5e 65 89 1e 78 fd d3 6b b1 fe df 5b 71 d9 43 11 44 0d 34 d0 67 81 3e f8 c7 3b ec 97 66 85 2e b8 da 4f 21 84 2a a8 9a 52 55 49 39 e4 b7 e6 bf c6 3f fc d7 7b f1 e3 ab 96 62 95 6e a5 ae 82 32 c8 07 1c 70 dd 53 51 59 79 f9 c3 2b ac 8a 12 48 3d f4 f7 fb cb 0b 2c b0 fa cf 1b 6c ad 8e 02 08 20 80 3a e8 87 26 98 5a 75 c9 03 0c 30 c0 27 9c 4a 35 d4 77 c1 23 8c 0a 28 a0 ba d2 6f a1 be c2 2f bc ca 0f 3c f0 e7 bb d6 7f e1 a3 b6 e2 af 86 22 88 1a 68 bd ce 1f 7c ed 93 76 c5 33 cc 17 5c 6d a9 9e 42 15 54 4d 29 a4 aa 92 72 d5 73 d1 63 91 7e e5 b3 f6 ff db 4b 31 c4 37 dc 57 41 19 64 8d 0e 38 e0 a7 a6 a2 b2 f2 ef 9b 56 45 09 24 90 7a f5 f3 eb 8b 16 58 7d e9
* 01 8e 47 ad d8 6c 36 1b 83 cf e9 fa 7d b0 58 2c 16 0b 8b cb eb fb f3 f7 f5 f4 7a 3d 90 48 24 12 09 8a 45 ac 56 2b 9b c3 ef f9 f2 79 b2 59 a2 51 a6 53 a7 dd e0 70 38 1c 0e 07 8d c8 64 32 19 82 41 ae 57 a5 dc 6e 37 95 c4 62 31 96 4b ab db e3 ff f1 f6 7b b3 d7 e5 fc 7e 3f 91 c6 63 bf d1 e6 73 b7 d5 e4 72 39 92 49 aa 55 a4 52 29 9a 4d a8 54 2a 15 84 42 21 9e 4f a9 da 6d b8 5c 2e 17 85 cc 66 33 97 c5 ec 76 3b 93 c7 ed f8 7c 3e 1f 81 ce 67 bd d0 68 34 1a 0d 88 44 22 11 86 43 af d9 e2 71 b6 5b a3 df e1 fe 7f b1 d6 6b bb d3 e7 fd f0 78 3c 1e 0f 89 ca 65 bc 5e 2f 99 c2 61 be 5f a1 de 6f b9 d2 69 ba 5d a0 50 28 14 0a 05 8c 46 23 9f c1 ee 77 b5 d4 6a 35 94 4a 25 9c 4e 27 9d c0 60 30 18 0c 06 03 8f c9 ea 75 b4 5a 2d 98 4c 26 13 87 cd e8 74 3a 1d 80 40 20
*/
const unsigned char __attribute__((aligned(256))) gfpower[3][256] =
{
@ -8875,38 +8875,38 @@ const unsigned char __attribute__((aligned(256))) gfpower[3][256] =
0x1b, 0x36, 0x6c,
},
{
0x01, 0x04, 0x10, 0x40, 0x1d, 0x74, 0xcd, 0x13,
0x4c, 0x2d, 0xb4, 0xea, 0x8f, 0x06, 0x18, 0x60,
0x9d, 0x4e, 0x25, 0x94, 0x6a, 0xb5, 0xee, 0x9f,
0x46, 0x05, 0x14, 0x50, 0x5d, 0x69, 0xb9, 0xde,
0x5f, 0x61, 0x99, 0x5e, 0x65, 0x89, 0x1e, 0x78,
0xfd, 0xd3, 0x6b, 0xb1, 0xfe, 0xdf, 0x5b, 0x71,
0xd9, 0x43, 0x11, 0x44, 0x0d, 0x34, 0xd0, 0x67,
0x81, 0x3e, 0xf8, 0xc7, 0x3b, 0xec, 0x97, 0x66,
0x85, 0x2e, 0xb8, 0xda, 0x4f, 0x21, 0x84, 0x2a,
0xa8, 0x9a, 0x52, 0x55, 0x49, 0x39, 0xe4, 0xb7,
0xe6, 0xbf, 0xc6, 0x3f, 0xfc, 0xd7, 0x7b, 0xf1,
0xe3, 0xab, 0x96, 0x62, 0x95, 0x6e, 0xa5, 0xae,
0x82, 0x32, 0xc8, 0x07, 0x1c, 0x70, 0xdd, 0x53,
0x51, 0x59, 0x79, 0xf9, 0xc3, 0x2b, 0xac, 0x8a,
0x12, 0x48, 0x3d, 0xf4, 0xf7, 0xfb, 0xcb, 0x0b,
0x2c, 0xb0, 0xfa, 0xcf, 0x1b, 0x6c, 0xad, 0x8e,
0x02, 0x08, 0x20, 0x80, 0x3a, 0xe8, 0x87, 0x26,
0x98, 0x5a, 0x75, 0xc9, 0x03, 0x0c, 0x30, 0xc0,
0x27, 0x9c, 0x4a, 0x35, 0xd4, 0x77, 0xc1, 0x23,
0x8c, 0x0a, 0x28, 0xa0, 0xba, 0xd2, 0x6f, 0xa1,
0xbe, 0xc2, 0x2f, 0xbc, 0xca, 0x0f, 0x3c, 0xf0,
0xe7, 0xbb, 0xd6, 0x7f, 0xe1, 0xa3, 0xb6, 0xe2,
0xaf, 0x86, 0x22, 0x88, 0x1a, 0x68, 0xbd, 0xce,
0x1f, 0x7c, 0xed, 0x93, 0x76, 0xc5, 0x33, 0xcc,
0x17, 0x5c, 0x6d, 0xa9, 0x9e, 0x42, 0x15, 0x54,
0x4d, 0x29, 0xa4, 0xaa, 0x92, 0x72, 0xd5, 0x73,
0xd1, 0x63, 0x91, 0x7e, 0xe5, 0xb3, 0xf6, 0xff,
0xdb, 0x4b, 0x31, 0xc4, 0x37, 0xdc, 0x57, 0x41,
0x19, 0x64, 0x8d, 0x0e, 0x38, 0xe0, 0xa7, 0xa6,
0xa2, 0xb2, 0xf2, 0xef, 0x9b, 0x56, 0x45, 0x09,
0x24, 0x90, 0x7a, 0xf5, 0xf3, 0xeb, 0x8b, 0x16,
0x58, 0x7d, 0xe9,
0x01, 0x8e, 0x47, 0xad, 0xd8, 0x6c, 0x36, 0x1b,
0x83, 0xcf, 0xe9, 0xfa, 0x7d, 0xb0, 0x58, 0x2c,
0x16, 0x0b, 0x8b, 0xcb, 0xeb, 0xfb, 0xf3, 0xf7,
0xf5, 0xf4, 0x7a, 0x3d, 0x90, 0x48, 0x24, 0x12,
0x09, 0x8a, 0x45, 0xac, 0x56, 0x2b, 0x9b, 0xc3,
0xef, 0xf9, 0xf2, 0x79, 0xb2, 0x59, 0xa2, 0x51,
0xa6, 0x53, 0xa7, 0xdd, 0xe0, 0x70, 0x38, 0x1c,
0x0e, 0x07, 0x8d, 0xc8, 0x64, 0x32, 0x19, 0x82,
0x41, 0xae, 0x57, 0xa5, 0xdc, 0x6e, 0x37, 0x95,
0xc4, 0x62, 0x31, 0x96, 0x4b, 0xab, 0xdb, 0xe3,
0xff, 0xf1, 0xf6, 0x7b, 0xb3, 0xd7, 0xe5, 0xfc,
0x7e, 0x3f, 0x91, 0xc6, 0x63, 0xbf, 0xd1, 0xe6,
0x73, 0xb7, 0xd5, 0xe4, 0x72, 0x39, 0x92, 0x49,
0xaa, 0x55, 0xa4, 0x52, 0x29, 0x9a, 0x4d, 0xa8,
0x54, 0x2a, 0x15, 0x84, 0x42, 0x21, 0x9e, 0x4f,
0xa9, 0xda, 0x6d, 0xb8, 0x5c, 0x2e, 0x17, 0x85,
0xcc, 0x66, 0x33, 0x97, 0xc5, 0xec, 0x76, 0x3b,
0x93, 0xc7, 0xed, 0xf8, 0x7c, 0x3e, 0x1f, 0x81,
0xce, 0x67, 0xbd, 0xd0, 0x68, 0x34, 0x1a, 0x0d,
0x88, 0x44, 0x22, 0x11, 0x86, 0x43, 0xaf, 0xd9,
0xe2, 0x71, 0xb6, 0x5b, 0xa3, 0xdf, 0xe1, 0xfe,
0x7f, 0xb1, 0xd6, 0x6b, 0xbb, 0xd3, 0xe7, 0xfd,
0xf0, 0x78, 0x3c, 0x1e, 0x0f, 0x89, 0xca, 0x65,
0xbc, 0x5e, 0x2f, 0x99, 0xc2, 0x61, 0xbe, 0x5f,
0xa1, 0xde, 0x6f, 0xb9, 0xd2, 0x69, 0xba, 0x5d,
0xa0, 0x50, 0x28, 0x14, 0x0a, 0x05, 0x8c, 0x46,
0x23, 0x9f, 0xc1, 0xee, 0x77, 0xb5, 0xd4, 0x6a,
0x35, 0x94, 0x4a, 0x25, 0x9c, 0x4e, 0x27, 0x9d,
0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x8f,
0xc9, 0xea, 0x75, 0xb4, 0x5a, 0x2d, 0x98, 0x4c,
0x26, 0x13, 0x87, 0xcd, 0xe8, 0x74, 0x3a, 0x1d,
0x80, 0x40, 0x20,
},
};