mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Adds support for fast triple parity without SSSE3.
This commit is contained in:
parent
6a3438f883
commit
a5a3c33854
17 changed files with 784 additions and 214 deletions
14
Makefile.am
14
Makefile.am
|
|
@ -75,7 +75,7 @@ EXTRA_DIST = \
|
|||
noautomake.sh \
|
||||
README AUTHORS HISTORY INSTALL COPYING TODO TEST INSTALL.windows \
|
||||
snapraid.d snapraid.1 snapraid.txt \
|
||||
test-raid5.conf test-raid6.conf test-raidTP.conf test-raidQP.conf test-raidPP.conf test-raidHP.conf test-raidHP-hole.conf \
|
||||
test-raid5.conf test-raid6.conf test-raidS3.conf test-raidS4.conf test-raidS5.conf test-raidS6.conf test-raidS6-hole.conf \
|
||||
snapraid.conf.example \
|
||||
configure.windows-x86 configure.windows-x64 snapraid.conf.example.windows \
|
||||
acinclude.m4
|
||||
|
|
@ -99,14 +99,14 @@ maintainer-clean-local:
|
|||
CHECKFLAGS = --test-skip-device --test-skip-self -q
|
||||
CHECKCOUNT = 2000
|
||||
CHECKSIZE = 4000
|
||||
CONF = $(srcdir)/test-raidHP.conf
|
||||
HOLE = $(srcdir)/test-raidHP-hole.conf
|
||||
CONF = $(srcdir)/test-raidS6.conf
|
||||
HOLE = $(srcdir)/test-raidS6-hole.conf
|
||||
RAID5 = $(srcdir)/test-raid5.conf
|
||||
RAID6 = $(srcdir)/test-raid6.conf
|
||||
RAIDTP = $(srcdir)/test-raidTP.conf
|
||||
RAIDQP = $(srcdir)/test-raidQP.conf
|
||||
RAIDPP = $(srcdir)/test-raidPP.conf
|
||||
RAIDHP = $(srcdir)/test-raidHP.conf
|
||||
RAIDTP = $(srcdir)/test-raidS3.conf
|
||||
RAIDQP = $(srcdir)/test-raidS4.conf
|
||||
RAIDPP = $(srcdir)/test-raidS5.conf
|
||||
RAIDHP = $(srcdir)/test-raidS6.conf
|
||||
|
||||
check-local:
|
||||
rm -rf test
|
||||
|
|
|
|||
30
cpu.h
30
cpu.h
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
|
|
@ -192,20 +192,20 @@ static inline int cpu_has_slowpshufb(void)
|
|||
* RAID6 mmx 1160 [MB/s]
|
||||
* RAID6 sse2 2082 [MB/s]
|
||||
* RAID6 sse2ext 2481 [MB/s]
|
||||
* RAIDTP int32 236 [MB/s]
|
||||
* RAIDTP int64 456 [MB/s]
|
||||
* RAIDTP mmx 576 [MB/s]
|
||||
* RAIDTP sse2 1109 [MB/s]
|
||||
* RAIDTP sse2ext 1527 [MB/s]
|
||||
* RAIDTP ssse3 931 [MB/s] (slower than sse2ext)
|
||||
* RAIDTP ssse3ext 932 [MB/s] (slower than sse2ext)
|
||||
* RAIDQP int32 144 [MB/s]
|
||||
* RAIDQP int64 271 [MB/s]
|
||||
* RAIDQP mmx 431 [MB/s]
|
||||
* RAIDQP sse2 843 [MB/s]
|
||||
* RAIDQP sse2ext 1086 [MB/s]
|
||||
* RAIDQP ssse3 732 [MB/s] (slower than sse2ext)
|
||||
* RAIDQP ssse3ext 571 [MB/s] (slower than sse2ext)
|
||||
* RAIDZ3 int32 236 [MB/s]
|
||||
* RAIDZ3 int64 456 [MB/s]
|
||||
* RAIDZ3 mmx 576 [MB/s]
|
||||
* RAIDZ3 sse2 1109 [MB/s]
|
||||
* RAIDZ3 sse2ext 1527 [MB/s]
|
||||
* RAIDZ3 ssse3 931 [MB/s] (slower than sse2ext)
|
||||
* RAIDZ3 ssse3ext 932 [MB/s] (slower than sse2ext)
|
||||
* RAIDZ4 int32 144 [MB/s]
|
||||
* RAIDZ4 int64 271 [MB/s]
|
||||
* RAIDZ4 mmx 431 [MB/s]
|
||||
* RAIDZ4 sse2 843 [MB/s]
|
||||
* RAIDZ4 sse2ext 1086 [MB/s]
|
||||
* RAIDZ4 ssse3 732 [MB/s] (slower than sse2ext)
|
||||
* RAIDZ4 ssse3ext 571 [MB/s] (slower than sse2ext)
|
||||
*/
|
||||
if (family == 6 && model == 28)
|
||||
return 1;
|
||||
|
|
|
|||
58
mktables.c
58
mktables.c
|
|
@ -134,6 +134,32 @@ void set_cauchy(unsigned char* matrix)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the Power matrix used to generate the parity.
|
||||
*/
|
||||
void set_power(unsigned char* matrix)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned char v;
|
||||
|
||||
v = 1;
|
||||
for(i=0;i<DISK;++i) {
|
||||
matrix[0*DISK+i] = v;
|
||||
}
|
||||
|
||||
v = 1;
|
||||
for(i=0;i<DISK;++i) {
|
||||
matrix[1*DISK+i] = v;
|
||||
v = gfmul(2, v);
|
||||
}
|
||||
|
||||
v = 1;
|
||||
for(i=0;i<DISK;++i) {
|
||||
matrix[2*DISK+i] = v;
|
||||
v = gfmul(4, v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Next power of 2.
|
||||
*/
|
||||
|
|
@ -230,6 +256,38 @@ int main(void)
|
|||
}
|
||||
printf("};\n\n");
|
||||
|
||||
/* power matrix */
|
||||
set_power(matrix);
|
||||
|
||||
printf("/**\n");
|
||||
printf(" * Power matrix used to generate parity.\n");
|
||||
printf(" * This matrix is valid for up to %u parity with %u data disks.\n", 3, DISK);
|
||||
printf(" *\n");
|
||||
for(p=0;p<3;++p) {
|
||||
printf(" * ");
|
||||
for(i=0;i<DISK;++i) {
|
||||
printf("%02x ", matrix[p*DISK+i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf(" */\n");
|
||||
printf("const unsigned char __attribute__((aligned(256))) gfpower[%u][256] =\n", 3);
|
||||
printf("{\n");
|
||||
for(p=0;p<3;++p) {
|
||||
printf("\t{\n");
|
||||
for(i=0;i<DISK;++i) {
|
||||
if (i % 8 == 0)
|
||||
printf("\t\t");
|
||||
printf("0x%02x,", matrix[p*DISK+i]);
|
||||
if (i % 8 == 7)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n\t},\n");
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
/* cauchy matrix */
|
||||
set_cauchy(matrix);
|
||||
|
||||
|
|
|
|||
465
raid.c
465
raid.c
|
|
@ -26,8 +26,7 @@
|
|||
* This support was later completely rewritten (many times), but
|
||||
* the H. Peter Anvin's Copyright may still apply.
|
||||
*
|
||||
* The RAIDTP (Triple Parity), RAIDQP (Quad parity), RAIDPP (Penta Parity)
|
||||
* and RAIDHP (Hexa parity) support, and the recovering based on matrix
|
||||
* The others RAID levels and the recovering based on matrix
|
||||
* inversion is original work implemented from scratch.
|
||||
*/
|
||||
|
||||
|
|
@ -42,7 +41,7 @@
|
|||
* P = sum(Di)
|
||||
* Q = sum(2^i * Di) with 0<=i<N
|
||||
*
|
||||
* To support RAIDTP (Triple Parity), it was first evaluated, and then
|
||||
* 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:
|
||||
*
|
||||
|
|
@ -53,7 +52,7 @@
|
|||
* 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).
|
||||
* Unfortunately, the same approach doesn't work for quad parity.
|
||||
* Using additional parity coefficients set as power of 8 with equations:
|
||||
*
|
||||
* P = sum(Di)
|
||||
|
|
@ -69,8 +68,8 @@
|
|||
* requirement to have a MDS (Maximum Distance Separable) code [2, Chap 11,
|
||||
* Theorem 8].
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
|
|
@ -79,7 +78,7 @@
|
|||
* 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 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
|
||||
|
|
@ -91,12 +90,12 @@
|
|||
*
|
||||
* 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.
|
||||
* computation of triple parity using power coefficients.
|
||||
*
|
||||
* Another important property of the Cauchy matrix is that we can setup
|
||||
* the first two rows with 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.
|
||||
* 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
|
||||
|
|
@ -167,24 +166,24 @@
|
|||
* int8 int32 int64 sse2 sse2e ssse3 ssse3e
|
||||
* raid5 11927 22075 36004
|
||||
* raid6 3378 5874 18235 19164
|
||||
* raidTP 844 8814 9419
|
||||
* raidQP 665 6836 7415
|
||||
* raidPP 537 5388 5686
|
||||
* raidHP 449 4307 4789
|
||||
* raidS3 844 8814 9419
|
||||
* raidS4 665 6836 7415
|
||||
* raidS5 537 5388 5686
|
||||
* 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 RAIDTP with power
|
||||
* coefficient "4", and with equal speed for RAIDQP with power coefficient
|
||||
* 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.
|
||||
*
|
||||
* int32 int64 sse2 sse2e ssse3 ssse3e avxe
|
||||
* raidTP (power) 1511 2775 8625 9336 9645 9966
|
||||
* raidQP (power) 842 1518 5195 5507 6278 6737 7410
|
||||
* raidZ3 1511 2775 8625 9336 9645 9966
|
||||
* raidZ4 842 1518 5195 5507 6278 6737 7410
|
||||
*
|
||||
* References:
|
||||
* [1] Anvin, "The mathematics of RAID-6", 2004
|
||||
|
|
@ -564,14 +563,253 @@ void raid6_sse2ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
#endif
|
||||
|
||||
/*
|
||||
* RAIDTP 8bit C implementation
|
||||
* RAIDZ3 with power coefficients 32bit C implementation
|
||||
*/
|
||||
void raidZ3_int32(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
unsigned char* r;
|
||||
int d, l;
|
||||
unsigned i;
|
||||
|
||||
uint32_t d0, r0, q0, p0;
|
||||
uint32_t d1, r1, q1, p1;
|
||||
|
||||
l = data - 1;
|
||||
p = vbuf[data];
|
||||
q = vbuf[data+1];
|
||||
r = vbuf[data+2];
|
||||
|
||||
for(i=0;i<size;i+=8) {
|
||||
r0 = q0 = p0 = v_32(vbuf[l][i]);
|
||||
r1 = q1 = p1 = v_32(vbuf[l][i+4]);
|
||||
for(d=l-1;d>=0;--d) {
|
||||
d0 = v_32(vbuf[d][i]);
|
||||
d1 = v_32(vbuf[d][i+4]);
|
||||
|
||||
p0 ^= d0;
|
||||
p1 ^= d1;
|
||||
|
||||
q0 = x2_32(q0);
|
||||
q1 = x2_32(q1);
|
||||
|
||||
q0 ^= d0;
|
||||
q1 ^= d1;
|
||||
|
||||
r0 = x2_32(r0);
|
||||
r1 = x2_32(r1);
|
||||
r0 = x2_32(r0);
|
||||
r1 = x2_32(r1);
|
||||
|
||||
r0 ^= d0;
|
||||
r1 ^= d1;
|
||||
}
|
||||
v_32(p[i]) = p0;
|
||||
v_32(p[i+4]) = p1;
|
||||
v_32(q[i]) = q0;
|
||||
v_32(q[i+4]) = q1;
|
||||
v_32(r[i]) = r0;
|
||||
v_32(r[i+4]) = r1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RAIDZ3 with power coefficients 64bit C implementation
|
||||
*/
|
||||
void raidZ3_int64(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
unsigned char* r;
|
||||
int d, l;
|
||||
unsigned i;
|
||||
|
||||
uint64_t d0, r0, q0, p0;
|
||||
uint64_t d1, r1, q1, p1;
|
||||
|
||||
l = data - 1;
|
||||
p = vbuf[data];
|
||||
q = vbuf[data+1];
|
||||
r = vbuf[data+2];
|
||||
|
||||
for(i=0;i<size;i+=16) {
|
||||
r0 = q0 = p0 = v_64(vbuf[l][i]);
|
||||
r1 = q1 = p1 = v_64(vbuf[l][i+8]);
|
||||
for(d=l-1;d>=0;--d) {
|
||||
d0 = v_64(vbuf[d][i]);
|
||||
d1 = v_64(vbuf[d][i+8]);
|
||||
|
||||
p0 ^= d0;
|
||||
p1 ^= d1;
|
||||
|
||||
q0 = x2_64(q0);
|
||||
q1 = x2_64(q1);
|
||||
|
||||
q0 ^= d0;
|
||||
q1 ^= d1;
|
||||
|
||||
r0 = x2_64(r0);
|
||||
r1 = x2_64(r1);
|
||||
r0 = x2_64(r0);
|
||||
r1 = x2_64(r1);
|
||||
|
||||
r0 ^= d0;
|
||||
r1 ^= d1;
|
||||
}
|
||||
v_64(p[i]) = p0;
|
||||
v_64(p[i+8]) = p1;
|
||||
v_64(q[i]) = q0;
|
||||
v_64(q[i+8]) = q1;
|
||||
v_64(r[i]) = r0;
|
||||
v_64(r[i+8]) = r1;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* RAIDZ3 with power coefficients SSE2 implementation
|
||||
*/
|
||||
void raidZ3_sse2(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
unsigned char* r;
|
||||
int d, l;
|
||||
unsigned i;
|
||||
|
||||
l = data - 1;
|
||||
p = vbuf[data];
|
||||
q = vbuf[data+1];
|
||||
r = vbuf[data+2];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0]));
|
||||
|
||||
for(i=0;i<size;i+=16) {
|
||||
asm volatile("movdqa %0,%%xmm0" : : "m" (vbuf[l][i]));
|
||||
asm volatile("movdqa %xmm0,%xmm1");
|
||||
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("movntdq %%xmm0,%0" : "=m" (p[i]));
|
||||
asm volatile("movntdq %%xmm1,%0" : "=m" (q[i]));
|
||||
asm volatile("movntdq %%xmm2,%0" : "=m" (r[i]));
|
||||
}
|
||||
|
||||
asm volatile("sfence" : : : "memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
/*
|
||||
* RAIDZ3 with power coefficients SSE2 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raidZ3_sse2ext(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
unsigned char* r;
|
||||
int d, l;
|
||||
unsigned i;
|
||||
|
||||
l = data - 1;
|
||||
p = vbuf[data];
|
||||
q = vbuf[data+1];
|
||||
r = vbuf[data+2];
|
||||
|
||||
asm volatile("movdqa %0,%%xmm7" : : "m" (raid_16_const.poly[0]));
|
||||
|
||||
for(i=0;i<size;i+=32) {
|
||||
asm volatile("movdqa %0,%%xmm0" : : "m" (vbuf[l][i]));
|
||||
asm volatile("movdqa %0,%%xmm8" : : "m" (vbuf[l][i+16]));
|
||||
asm volatile("movdqa %xmm0,%xmm1");
|
||||
asm volatile("movdqa %xmm8,%xmm9");
|
||||
asm volatile("movdqa %xmm0,%xmm2");
|
||||
asm volatile("movdqa %xmm8,%xmm10");
|
||||
for(d=l-1;d>=0;--d) {
|
||||
asm volatile("pxor %xmm4,%xmm4");
|
||||
asm volatile("pxor %xmm5,%xmm5");
|
||||
asm volatile("pxor %xmm6,%xmm6");
|
||||
asm volatile("pxor %xmm12,%xmm12");
|
||||
asm volatile("pxor %xmm13,%xmm13");
|
||||
asm volatile("pxor %xmm14,%xmm14");
|
||||
asm volatile("pcmpgtb %xmm1,%xmm4");
|
||||
asm volatile("pcmpgtb %xmm2,%xmm5");
|
||||
asm volatile("pcmpgtb %xmm9,%xmm12");
|
||||
asm volatile("pcmpgtb %xmm10,%xmm13");
|
||||
asm volatile("paddb %xmm1,%xmm1");
|
||||
asm volatile("paddb %xmm2,%xmm2");
|
||||
asm volatile("paddb %xmm9,%xmm9");
|
||||
asm volatile("paddb %xmm10,%xmm10");
|
||||
asm volatile("pand %xmm7,%xmm4");
|
||||
asm volatile("pand %xmm7,%xmm5");
|
||||
asm volatile("pand %xmm7,%xmm12");
|
||||
asm volatile("pand %xmm7,%xmm13");
|
||||
asm volatile("pxor %xmm4,%xmm1");
|
||||
asm volatile("pxor %xmm5,%xmm2");
|
||||
asm volatile("pxor %xmm12,%xmm9");
|
||||
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("movntdq %%xmm0,%0" : "=m" (p[i]));
|
||||
asm volatile("movntdq %%xmm8,%0" : "=m" (p[i+16]));
|
||||
asm volatile("movntdq %%xmm1,%0" : "=m" (q[i]));
|
||||
asm volatile("movntdq %%xmm9,%0" : "=m" (q[i+16]));
|
||||
asm volatile("movntdq %%xmm2,%0" : "=m" (r[i]));
|
||||
asm volatile("movntdq %%xmm10,%0" : "=m" (r[i+16]));
|
||||
}
|
||||
|
||||
asm volatile("sfence" : : : "memory");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RAIDS3 8bit C implementation
|
||||
*
|
||||
* Note that instead of a generic multiplicationt table, likely resulting
|
||||
* in multiple cache misses, a precomputed table could be used.
|
||||
* But this is only a kind of reference function, and we are not really
|
||||
* interested in speed.
|
||||
*/
|
||||
void raidTP_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS3_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -611,9 +849,9 @@ void raidTP_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* RAIDTP SSSE3 implementation
|
||||
* RAIDS3 SSSE3 implementation
|
||||
*/
|
||||
void raidTP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS3_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -697,11 +935,11 @@ void raidTP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
/*
|
||||
* RAIDTP SSSE3 implementation
|
||||
* RAIDS3 SSSE3 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raidTP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS3_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -826,14 +1064,14 @@ void raidTP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
#endif
|
||||
|
||||
/*
|
||||
* RAIDQP 8bit C implementation
|
||||
* RAIDS4 8bit C implementation
|
||||
*
|
||||
* Note that instead of a generic multiplicationt table, likely resulting
|
||||
* in multiple cache misses, a precomputed table could be used.
|
||||
* But this is only a kind of reference function, and we are not really
|
||||
* interested in speed.
|
||||
*/
|
||||
void raidQP_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS4_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -878,9 +1116,9 @@ void raidQP_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* RAIDQP SSSE3 implementation
|
||||
* RAIDS4 SSSE3 implementation
|
||||
*/
|
||||
void raidQP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS4_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -983,11 +1221,11 @@ void raidQP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
/*
|
||||
* RAIDQP SSSE3 implementation
|
||||
* RAIDS4 SSSE3 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raidQP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS4_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -1144,14 +1382,14 @@ void raidQP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
#endif
|
||||
|
||||
/*
|
||||
* RAIDPP 8bit C implementation
|
||||
* RAIDS5 8bit C implementation
|
||||
*
|
||||
* Note that instead of a generic multiplicationt table, likely resulting
|
||||
* in multiple cache misses, a precomputed table could be used.
|
||||
* But this is only a kind of reference function, and we are not really
|
||||
* interested in speed.
|
||||
*/
|
||||
void raidPP_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS5_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -1201,13 +1439,13 @@ void raidPP_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* RAIDPP SSSE3 implementation
|
||||
* RAIDS5 SSSE3 implementation
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
/* ensures that stack is aligned at 16 bytes because we allocate SSE registers in it */
|
||||
__attribute__((force_align_arg_pointer))
|
||||
#endif
|
||||
void raidPP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS5_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
/* ensures that stack is aligned at 16 bytes because we allocate SSE registers in it */
|
||||
{
|
||||
unsigned char* p;
|
||||
|
|
@ -1331,11 +1569,11 @@ void raidPP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
/*
|
||||
* RAIDPP SSSE3 implementation
|
||||
* RAIDS5 SSSE3 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raidPP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS5_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -1452,14 +1690,14 @@ void raidPP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
#endif
|
||||
|
||||
/*
|
||||
* RAIDHP 8bit C implementation
|
||||
* RAIDS6 8bit C implementation
|
||||
*
|
||||
* Note that instead of a generic multiplicationt table, likely resulting
|
||||
* in multiple cache misses, a precomputed table could be used.
|
||||
* But this is only a kind of reference function, and we are not really
|
||||
* interested in speed.
|
||||
*/
|
||||
void raidHP_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS6_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -1514,13 +1752,13 @@ void raidHP_int8(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* RAIDHP SSSE3 implementation
|
||||
* RAIDS6 SSSE3 implementation
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
/* ensures that stack is aligned at 16 bytes because we allocate SSE registers in it */
|
||||
__attribute__((force_align_arg_pointer))
|
||||
#endif
|
||||
void raidHP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS6_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -1665,11 +1903,11 @@ void raidHP_ssse3(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
/*
|
||||
* RAIDHP SSSE3 implementation
|
||||
* RAIDS6 SSSE3 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raidHP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
void raidS6_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
|
@ -1802,28 +2040,42 @@ void raidHP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size)
|
|||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* mode */
|
||||
|
||||
static unsigned raid_mode = RAID_MODE_S; /**< RAID mode. */
|
||||
|
||||
void raid_set(unsigned mode)
|
||||
{
|
||||
raid_mode = mode;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* parity generation */
|
||||
|
||||
/* internal forwarder */
|
||||
static void (*raid5_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raid6_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raidTP_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raidQP_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raidPP_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raidHP_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raidZ3_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raidS3_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raidS4_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raidS5_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
static void (*raidS6_gen)(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
|
||||
void raid_gen(unsigned level, unsigned char** vbuf, unsigned data, unsigned size)
|
||||
{
|
||||
assert(data >= RAID_DATA_MIN && data <= RAID_DATA_MAX);
|
||||
|
||||
switch (level) {
|
||||
case 1 : raid5_gen(vbuf, data, size); break;
|
||||
case 2 : raid6_gen(vbuf, data, size); break;
|
||||
case 3 : raidTP_gen(vbuf, data, size); break;
|
||||
case 4 : raidQP_gen(vbuf, data, size); break;
|
||||
case 5 : raidPP_gen(vbuf, data, size); break;
|
||||
case 6 : raidHP_gen(vbuf, data, size); break;
|
||||
case 3 :
|
||||
if (raid_mode == RAID_MODE_S)
|
||||
raidS3_gen(vbuf, data, size);
|
||||
else
|
||||
raidZ3_gen(vbuf, data, size);
|
||||
break;
|
||||
case 4 : raidS4_gen(vbuf, data, size); break;
|
||||
case 5 : raidS5_gen(vbuf, data, size); break;
|
||||
case 6 : raidS6_gen(vbuf, data, size); break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid raid gen level\n");
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -1892,11 +2144,11 @@ static inline const unsigned char* table(unsigned char v)
|
|||
*/
|
||||
static inline void raid_delta_gen(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
unsigned char* p[RAID_PARITY_MAX];
|
||||
unsigned char* pa[RAID_PARITY_MAX];
|
||||
unsigned char* p[RAID_PARITY_S_MAX];
|
||||
unsigned char* pa[RAID_PARITY_S_MAX];
|
||||
unsigned i;
|
||||
|
||||
assert(level > 0 && level <= RAID_PARITY_MAX);
|
||||
assert(level > 0 && level <= RAID_PARITY_S_MAX);
|
||||
|
||||
for(i=0;i<level;++i) {
|
||||
/* keep a copy of the parity buffer */
|
||||
|
|
@ -2029,7 +2281,10 @@ static void raid6_recov2(const int* d, const int* c, unsigned char** vbuf, unsig
|
|||
*/
|
||||
static unsigned char A(unsigned p, unsigned d)
|
||||
{
|
||||
return gfgen[p][d];
|
||||
if (raid_mode == RAID_MODE_S)
|
||||
return gfgen[p][d];
|
||||
else
|
||||
return gfpower[p][d];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2225,11 +2480,11 @@ void raid_recov2_int8(unsigned level, const int* d, const int* c, unsigned char*
|
|||
*/
|
||||
void raid_recovX_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
unsigned char* p[RAID_PARITY_MAX];
|
||||
unsigned char* pa[RAID_PARITY_MAX];
|
||||
const unsigned char* T[RAID_PARITY_MAX][RAID_PARITY_MAX];
|
||||
unsigned char G[RAID_PARITY_MAX*RAID_PARITY_MAX];
|
||||
unsigned char V[RAID_PARITY_MAX*RAID_PARITY_MAX];
|
||||
unsigned char* p[RAID_PARITY_S_MAX];
|
||||
unsigned char* pa[RAID_PARITY_S_MAX];
|
||||
const unsigned char* T[RAID_PARITY_S_MAX][RAID_PARITY_S_MAX];
|
||||
unsigned char G[RAID_PARITY_S_MAX*RAID_PARITY_S_MAX];
|
||||
unsigned char V[RAID_PARITY_S_MAX*RAID_PARITY_S_MAX];
|
||||
unsigned i, j, k;
|
||||
|
||||
/* setup the coefficients matrix */
|
||||
|
|
@ -2258,7 +2513,7 @@ void raid_recovX_int8(unsigned level, const int* d, const int* c, unsigned char*
|
|||
}
|
||||
|
||||
for(i=0;i<size;++i) {
|
||||
unsigned char PD[RAID_PARITY_MAX];
|
||||
unsigned char PD[RAID_PARITY_S_MAX];
|
||||
|
||||
/* delta */
|
||||
for(j=0;j<level;++j)
|
||||
|
|
@ -2441,10 +2696,10 @@ void raid_recov2_ssse3(unsigned level, const int* d, const int* c, unsigned char
|
|||
void raid_recovX_ssse3(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size)
|
||||
{
|
||||
unsigned N = level;
|
||||
unsigned char* p[RAID_PARITY_MAX];
|
||||
unsigned char* pa[RAID_PARITY_MAX];
|
||||
unsigned char G[RAID_PARITY_MAX*RAID_PARITY_MAX];
|
||||
unsigned char V[RAID_PARITY_MAX*RAID_PARITY_MAX];
|
||||
unsigned char* p[RAID_PARITY_S_MAX];
|
||||
unsigned char* pa[RAID_PARITY_S_MAX];
|
||||
unsigned char G[RAID_PARITY_S_MAX*RAID_PARITY_S_MAX];
|
||||
unsigned char V[RAID_PARITY_S_MAX*RAID_PARITY_S_MAX];
|
||||
unsigned i, j, k;
|
||||
|
||||
/* setup the coefficients matrix */
|
||||
|
|
@ -2468,7 +2723,7 @@ void raid_recovX_ssse3(unsigned level, const int* d, const int* c, unsigned char
|
|||
asm volatile("movdqa %0,%%xmm7" : : "m" (gfconst16.mask[0]));
|
||||
|
||||
for(i=0;i<size;i+=16) {
|
||||
unsigned char PD[RAID_PARITY_MAX][16] __attribute__((aligned(16)));
|
||||
unsigned char PD[RAID_PARITY_S_MAX][16] __attribute__((aligned(16)));
|
||||
|
||||
/* delta */
|
||||
for(j=0;j<N;++j) {
|
||||
|
|
@ -2540,17 +2795,19 @@ void raid_recov(unsigned level, const int* d, const int* c, unsigned char** vbuf
|
|||
|
||||
void raid_init(void)
|
||||
{
|
||||
raidTP_gen = raidTP_int8;
|
||||
raidQP_gen = raidQP_int8;
|
||||
raidPP_gen = raidPP_int8;
|
||||
raidHP_gen = raidHP_int8;
|
||||
raidS3_gen = raidS3_int8;
|
||||
raidS4_gen = raidS4_int8;
|
||||
raidS5_gen = raidS5_int8;
|
||||
raidS6_gen = raidS6_int8;
|
||||
|
||||
if (sizeof(void*) == 4) {
|
||||
raid5_gen = raid5_int32;
|
||||
raid6_gen = raid6_int32;
|
||||
raidZ3_gen = raidZ3_int32;
|
||||
} else {
|
||||
raid5_gen = raid5_int64;
|
||||
raid6_gen = raid6_int64;
|
||||
raidZ3_gen = raidZ3_int64;
|
||||
}
|
||||
|
||||
raid_recov1 = raid_recov1_int8;
|
||||
|
|
@ -2563,25 +2820,28 @@ void raid_init(void)
|
|||
#if defined(__x86_64__)
|
||||
if (cpu_has_slowextendedreg()) {
|
||||
raid6_gen = raid6_sse2;
|
||||
raidZ3_gen = raidZ3_sse2;
|
||||
} else {
|
||||
raid6_gen = raid6_sse2ext;
|
||||
raidZ3_gen = raidZ3_sse2ext;
|
||||
}
|
||||
#else
|
||||
raid6_gen = raid6_sse2;
|
||||
raidZ3_gen = raidZ3_sse2;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cpu_has_ssse3()) {
|
||||
#if defined(__x86_64__)
|
||||
raidTP_gen = raidTP_ssse3ext;
|
||||
raidQP_gen = raidQP_ssse3ext;
|
||||
raidPP_gen = raidPP_ssse3ext;
|
||||
raidHP_gen = raidHP_ssse3ext;
|
||||
raidS3_gen = raidS3_ssse3ext;
|
||||
raidS4_gen = raidS4_ssse3ext;
|
||||
raidS5_gen = raidS5_ssse3ext;
|
||||
raidS6_gen = raidS6_ssse3ext;
|
||||
#else
|
||||
raidTP_gen = raidTP_ssse3;
|
||||
raidQP_gen = raidQP_ssse3;
|
||||
raidPP_gen = raidPP_ssse3;
|
||||
raidHP_gen = raidHP_ssse3;
|
||||
raidS3_gen = raidS3_ssse3;
|
||||
raidS4_gen = raidS4_ssse3;
|
||||
raidS5_gen = raidS5_ssse3;
|
||||
raidS6_gen = raidS6_ssse3;
|
||||
#endif
|
||||
raid_recov1 = raid_recov1_ssse3;
|
||||
raid_recov2 = raid_recov2_ssse3;
|
||||
|
|
@ -2594,14 +2854,16 @@ static struct raid_func {
|
|||
const char* name;
|
||||
void* p;
|
||||
} RAID_FUNC[] = {
|
||||
{ "int8", raidTP_int8 },
|
||||
{ "int8", raidQP_int8 },
|
||||
{ "int8", raidPP_int8 },
|
||||
{ "int8", raidHP_int8 },
|
||||
{ "int8", raidS3_int8 },
|
||||
{ "int8", raidS4_int8 },
|
||||
{ "int8", raidS5_int8 },
|
||||
{ "int8", raidS6_int8 },
|
||||
{ "int32", raid5_int32 },
|
||||
{ "int64", raid5_int64 },
|
||||
{ "int32", raid6_int32 },
|
||||
{ "int64", raid6_int64 },
|
||||
{ "int32", raidZ3_int32 },
|
||||
{ "int64", raidZ3_int64 },
|
||||
{ "int8", raid_recov1_int8 },
|
||||
{ "int8", raid_recov2_int8 },
|
||||
{ "int8", raid_recovX_int8 },
|
||||
|
|
@ -2609,10 +2871,11 @@ static struct raid_func {
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
{ "sse2", raid5_sse2 },
|
||||
{ "sse2", raid6_sse2 },
|
||||
{ "ssse3", raidTP_ssse3 },
|
||||
{ "ssse3", raidQP_ssse3 },
|
||||
{ "ssse3", raidPP_ssse3 },
|
||||
{ "ssse3", raidHP_ssse3 },
|
||||
{ "sse2", raidZ3_sse2 },
|
||||
{ "ssse3", raidS3_ssse3 },
|
||||
{ "ssse3", raidS4_ssse3 },
|
||||
{ "ssse3", raidS5_ssse3 },
|
||||
{ "ssse3", raidS6_ssse3 },
|
||||
{ "ssse3", raid_recov1_ssse3 },
|
||||
{ "ssse3", raid_recov2_ssse3 },
|
||||
{ "ssse3", raid_recovX_ssse3 },
|
||||
|
|
@ -2620,10 +2883,11 @@ static struct raid_func {
|
|||
|
||||
#if defined(__x86_64__)
|
||||
{ "sse2e", raid6_sse2ext },
|
||||
{ "ssse3e", raidTP_ssse3ext },
|
||||
{ "ssse3e", raidQP_ssse3ext },
|
||||
{ "ssse3e", raidPP_ssse3ext },
|
||||
{ "ssse3e", raidHP_ssse3ext },
|
||||
{ "sse2e", raidZ3_sse2ext },
|
||||
{ "ssse3e", raidS3_ssse3ext },
|
||||
{ "ssse3e", raidS4_ssse3ext },
|
||||
{ "ssse3e", raidS5_ssse3ext },
|
||||
{ "ssse3e", raidS6_ssse3ext },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
|
@ -2649,24 +2913,29 @@ const char* raid6_tag(void)
|
|||
return raid_tag(raid6_gen);
|
||||
}
|
||||
|
||||
const char* raidTP_tag(void)
|
||||
const char* raidZ3_tag(void)
|
||||
{
|
||||
return raid_tag(raidTP_gen);
|
||||
return raid_tag(raidZ3_gen);
|
||||
}
|
||||
|
||||
const char* raidQP_tag(void)
|
||||
const char* raidS3_tag(void)
|
||||
{
|
||||
return raid_tag(raidQP_gen);
|
||||
return raid_tag(raidS3_gen);
|
||||
}
|
||||
|
||||
const char* raidPP_tag(void)
|
||||
const char* raidS4_tag(void)
|
||||
{
|
||||
return raid_tag(raidPP_gen);
|
||||
return raid_tag(raidS4_gen);
|
||||
}
|
||||
|
||||
const char* raidHP_tag(void)
|
||||
const char* raidS5_tag(void)
|
||||
{
|
||||
return raid_tag(raidHP_gen);
|
||||
return raid_tag(raidS5_gen);
|
||||
}
|
||||
|
||||
const char* raidS6_tag(void)
|
||||
{
|
||||
return raid_tag(raidS6_gen);
|
||||
}
|
||||
|
||||
const char* raid_recov1_tag(void)
|
||||
|
|
|
|||
78
raid.h
78
raid.h
|
|
@ -22,9 +22,33 @@
|
|||
/* raid */
|
||||
|
||||
/**
|
||||
* Max level of parity supported.
|
||||
* RAID mode supporting up to 6 parities.
|
||||
*
|
||||
* It requires SSSE3 to get good performance with triple or more parities.
|
||||
*
|
||||
* This is the default mode used by SnapRAID.
|
||||
*/
|
||||
#define RAID_PARITY_MAX 6
|
||||
#define RAID_MODE_S 0
|
||||
|
||||
/**
|
||||
* RAID mode supporting up to 3 parities,
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#define RAID_MODE_Z 1
|
||||
|
||||
/**
|
||||
* Max level of parity supported for mode S.
|
||||
*/
|
||||
#define RAID_PARITY_S_MAX 6
|
||||
|
||||
/**
|
||||
* Max level of parity supported for mode Z.
|
||||
*/
|
||||
#define RAID_PARITY_Z_MAX 3
|
||||
|
||||
/**
|
||||
* Maximum number of data disks.
|
||||
|
|
@ -34,7 +58,6 @@
|
|||
|
||||
/**
|
||||
* Minimum number of data disks.
|
||||
* Limit of some optimized parity generator functions.
|
||||
*/
|
||||
#define RAID_DATA_MIN 2
|
||||
|
||||
|
|
@ -43,8 +66,18 @@
|
|||
*/
|
||||
void raid_init(void);
|
||||
|
||||
/**
|
||||
* Set the RAID mode to use. One of RAID_MODE_*.
|
||||
*
|
||||
* You can change mode at any time, and it will affect next calls to raid_gen() and raid_recov().
|
||||
*
|
||||
* The two modes are compatible for the first two levels of parity. The third one is different.
|
||||
*/
|
||||
void raid_set(unsigned mode);
|
||||
|
||||
/**
|
||||
* Computes the parity.
|
||||
*
|
||||
* \param level Number of parities to compute.
|
||||
* \param vbuf Vector of pointers to the blocks for disks and parities.
|
||||
* It has (::data + ::level) elements. Each element points to a buffer of ::size bytes.
|
||||
|
|
@ -55,6 +88,7 @@ void raid_gen(unsigned level, unsigned char** vbuf, unsigned data, unsigned size
|
|||
|
||||
/**
|
||||
* Recovers failures of data disks using the specified parities.
|
||||
*
|
||||
* Note that only the data blocks are recovered. The parity is destroyed.
|
||||
* \param level Number of failed disks.
|
||||
* \param d[] Vector of indexes of the data disks to recover. Starting from 0.
|
||||
|
|
@ -73,16 +107,18 @@ void raid_recov(unsigned level, const int* d, const int* c, unsigned char** vbuf
|
|||
*/
|
||||
const char* raid5_tag(void);
|
||||
const char* raid6_tag(void);
|
||||
const char* raidTP_tag(void);
|
||||
const char* raidQP_tag(void);
|
||||
const char* raidPP_tag(void);
|
||||
const char* raidHP_tag(void);
|
||||
const char* raidZ3_tag(void);
|
||||
const char* raidS3_tag(void);
|
||||
const char* raidS4_tag(void);
|
||||
const char* raidS5_tag(void);
|
||||
const char* raidS6_tag(void);
|
||||
const char* raid_recov1_tag(void);
|
||||
const char* raid_recov2_tag(void);
|
||||
const char* raid_recovX_tag(void);
|
||||
|
||||
/**
|
||||
* Specialized parity computation.
|
||||
*
|
||||
* Only for testing.
|
||||
*/
|
||||
void raid5_int32(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
|
|
@ -92,18 +128,22 @@ void raid6_int32(unsigned char** vbuf, unsigned data, unsigned size);
|
|||
void raid6_int64(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raid6_sse2(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raid6_sse2ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidTP_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidTP_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidTP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidQP_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidQP_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidQP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidPP_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidPP_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidPP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidHP_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidHP_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidHP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidZ3_int32(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidZ3_int64(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidZ3_sse2(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidZ3_sse2ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS3_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS3_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS3_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS4_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS4_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS4_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS5_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS5_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS5_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS6_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS6_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raidS6_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raid_recov1_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recov2_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recovX_int8(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
|
|
|
|||
100
selftest.c
100
selftest.c
|
|
@ -80,7 +80,7 @@ static void combotest(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void recovtest(unsigned diskmax, unsigned block_size)
|
||||
static void recovtest(unsigned mode, unsigned diskmax, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
unsigned char** buffer;
|
||||
|
|
@ -99,17 +99,24 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
unsigned r;
|
||||
void (*map[LEV_MAX][4])(unsigned level, const int* d, const int* c, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
unsigned mac[LEV_MAX];
|
||||
unsigned level;
|
||||
|
||||
buffermax = diskmax + LEV_MAX * 2 + 2;
|
||||
raid_set(mode);
|
||||
if (mode == RAID_MODE_S)
|
||||
level = LEV_MAX;
|
||||
else
|
||||
level = 3;
|
||||
|
||||
buffermax = diskmax + level * 2 + 2;
|
||||
|
||||
buffer = malloc_nofail_vector_align(diskmax, buffermax, block_size, &buffer_alloc);
|
||||
mtest_vector(buffer, buffermax, block_size);
|
||||
|
||||
data = buffer;
|
||||
parity = buffer + diskmax;
|
||||
test = buffer + diskmax + LEV_MAX;
|
||||
test = buffer + diskmax + level;
|
||||
|
||||
for(i=0;i<LEV_MAX;++i)
|
||||
for(i=0;i<level;++i)
|
||||
parity_save[i] = parity[i];
|
||||
|
||||
zero = buffer[buffermax-2];
|
||||
|
|
@ -124,7 +131,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
}
|
||||
|
||||
/* setup recov functions */
|
||||
for(i=0;i<LEV_MAX;++i) {
|
||||
for(i=0;i<level;++i) {
|
||||
mac[i] = 0;
|
||||
if (i == 0) {
|
||||
map[i][mac[i]++] = raid_recov1_int8;
|
||||
|
|
@ -151,19 +158,19 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(LEV_MAX, buffer, diskmax, block_size);
|
||||
raid_gen(level, buffer, diskmax, block_size);
|
||||
|
||||
/* set all the parity to the waste buffer */
|
||||
for(i=0;i<LEV_MAX;++i)
|
||||
for(i=0;i<level;++i)
|
||||
parity[i] = waste;
|
||||
|
||||
/* all parity levels */
|
||||
for(r=1;r<=LEV_MAX;++r) {
|
||||
for(r=1;r<=level;++r) {
|
||||
/* all combinations (r of diskmax) disks */
|
||||
combination_first(r, diskmax, d);
|
||||
do {
|
||||
/* all combinations (r of LEV_MAX) parities */
|
||||
combination_first(r, LEV_MAX, p);
|
||||
/* all combinations (r of level) parities */
|
||||
combination_first(r, level, p);
|
||||
do {
|
||||
/* for each recover function */
|
||||
for(j=0;j<mac[r-1];++j) {
|
||||
|
|
@ -195,7 +202,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
parity[p[i]] = waste;
|
||||
}
|
||||
}
|
||||
} while (combination_next(r, LEV_MAX, p));
|
||||
} while (combination_next(r, level, p));
|
||||
} while (combination_next(r, diskmax, d));
|
||||
}
|
||||
|
||||
|
|
@ -203,7 +210,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
free(buffer);
|
||||
}
|
||||
|
||||
static void gentest(unsigned diskmax, unsigned block_size)
|
||||
static void gentest(unsigned mode, unsigned diskmax, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
unsigned char** buffer;
|
||||
|
|
@ -211,8 +218,15 @@ static void gentest(unsigned diskmax, unsigned block_size)
|
|||
unsigned i, j;
|
||||
void (*map[64])(unsigned char** buffer, unsigned diskmax, unsigned size);
|
||||
unsigned mac;
|
||||
unsigned level;
|
||||
|
||||
buffermax = diskmax + LEV_MAX * 2;
|
||||
raid_set(mode);
|
||||
if (mode == RAID_MODE_S)
|
||||
level = LEV_MAX;
|
||||
else
|
||||
level = 3;
|
||||
|
||||
buffermax = diskmax + level * 2;
|
||||
|
||||
buffer = malloc_nofail_vector_align(diskmax, buffermax, block_size, &buffer_alloc);
|
||||
mtest_vector(buffer, buffermax, block_size);
|
||||
|
|
@ -224,20 +238,15 @@ static void gentest(unsigned diskmax, unsigned block_size)
|
|||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(LEV_MAX, buffer, diskmax, block_size);
|
||||
raid_gen(level, buffer, diskmax, block_size);
|
||||
|
||||
/* copy in back buffers */
|
||||
for(i=0;i<LEV_MAX;++i)
|
||||
memcpy(buffer[diskmax + LEV_MAX + i], buffer[diskmax + i], block_size);
|
||||
for(i=0;i<level;++i)
|
||||
memcpy(buffer[diskmax + level + i], buffer[diskmax + i], block_size);
|
||||
|
||||
/* load all the available functions */
|
||||
mac = 0;
|
||||
|
||||
map[mac++] = raidTP_int8;
|
||||
map[mac++] = raidQP_int8;
|
||||
map[mac++] = raidPP_int8;
|
||||
map[mac++] = raidHP_int8;
|
||||
|
||||
map[mac++] = raid5_int32;
|
||||
map[mac++] = raid5_int64;
|
||||
map[mac++] = raid6_int32;
|
||||
|
|
@ -252,19 +261,37 @@ static void gentest(unsigned diskmax, unsigned block_size)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (cpu_has_ssse3()) {
|
||||
map[mac++] = raidTP_ssse3;
|
||||
map[mac++] = raidQP_ssse3;
|
||||
map[mac++] = raidPP_ssse3;
|
||||
map[mac++] = raidHP_ssse3;
|
||||
if (mode == RAID_MODE_S) {
|
||||
map[mac++] = raidS3_int8;
|
||||
map[mac++] = raidS4_int8;
|
||||
map[mac++] = raidS5_int8;
|
||||
map[mac++] = raidS6_int8;
|
||||
|
||||
if (cpu_has_ssse3()) {
|
||||
map[mac++] = raidS3_ssse3;
|
||||
map[mac++] = raidS4_ssse3;
|
||||
map[mac++] = raidS5_ssse3;
|
||||
map[mac++] = raidS6_ssse3;
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raidTP_ssse3ext;
|
||||
map[mac++] = raidQP_ssse3ext;
|
||||
map[mac++] = raidPP_ssse3ext;
|
||||
map[mac++] = raidHP_ssse3ext;
|
||||
map[mac++] = raidS3_ssse3ext;
|
||||
map[mac++] = raidS4_ssse3ext;
|
||||
map[mac++] = raidS5_ssse3ext;
|
||||
map[mac++] = raidS6_ssse3ext;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
map[mac++] = raidZ3_int32;
|
||||
map[mac++] = raidZ3_int64;
|
||||
if (cpu_has_sse2()) {
|
||||
map[mac++] = raidZ3_sse2;
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raidZ3_sse2ext;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check all the functions */
|
||||
for(j=0;j<mac;++j) {
|
||||
|
|
@ -272,8 +299,8 @@ static void gentest(unsigned diskmax, unsigned block_size)
|
|||
map[j](buffer, diskmax, block_size);
|
||||
|
||||
/* check it */
|
||||
for(i=0;i<LEV_MAX;++i) {
|
||||
if (memcmp(buffer[diskmax + LEV_MAX + i], buffer[diskmax + i], block_size) != 0) {
|
||||
for(i=0;i<level;++i) {
|
||||
if (memcmp(buffer[diskmax + level + i], buffer[diskmax + i], block_size) != 0) {
|
||||
fprintf(stderr, "Failed GEN test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -398,6 +425,9 @@ void selftest()
|
|||
hashtest();
|
||||
crc32ctest();
|
||||
combotest();
|
||||
gentest(32, 256);
|
||||
recovtest(12, 256);
|
||||
gentest(RAID_MODE_Z, 32, 256);
|
||||
recovtest(RAID_MODE_Z, 12, 256);
|
||||
gentest(RAID_MODE_S, 32, 256);
|
||||
recovtest(RAID_MODE_S, 12, 256);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -560,6 +560,9 @@ int main(int argc, char* argv[])
|
|||
/* read the configuration file */
|
||||
state_config(&state, conf, command, &opt, &filterlist_disk);
|
||||
|
||||
/* set the raid mode */
|
||||
raid_set(state.raid_mode);
|
||||
|
||||
#if HAVE_LOCKFILE
|
||||
/* create the lock file */
|
||||
if (!opt.skip_lock) {
|
||||
|
|
|
|||
110
speed.c
110
speed.c
|
|
@ -327,33 +327,31 @@ void speed(void)
|
|||
#endif
|
||||
printf("\n");
|
||||
|
||||
/* RAIDTP */
|
||||
printf("%8s", "raidTP");
|
||||
printf("%8s", raidTP_tag());
|
||||
/* RAIDZ3 */
|
||||
printf("%8s", "raidZ3");
|
||||
printf("%8s", raidZ3_tag());
|
||||
fflush(stdout);
|
||||
|
||||
printf("%8s", "");
|
||||
|
||||
SPEED_START {
|
||||
raidTP_int8(buffer, diskmax, block_size);
|
||||
raidZ3_int32(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
printf("%8s", "");
|
||||
printf("%8s", "");
|
||||
SPEED_START {
|
||||
raidZ3_int64(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
if (cpu_has_sse2()) {
|
||||
printf("%8s", "");
|
||||
|
||||
#if defined(__x86_64__)
|
||||
printf("%8s", "");
|
||||
#endif
|
||||
}
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
if (cpu_has_sse2()) {
|
||||
SPEED_START {
|
||||
raidTP_ssse3(buffer, diskmax, block_size);
|
||||
raidZ3_sse2(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -361,7 +359,7 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raidTP_ssse3ext(buffer, diskmax, block_size);
|
||||
raidZ3_sse2ext(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -371,13 +369,13 @@ void speed(void)
|
|||
#endif
|
||||
printf("\n");
|
||||
|
||||
/* RAIDQP */
|
||||
printf("%8s", "raidQP");
|
||||
printf("%8s", raidQP_tag());
|
||||
/* RAIDS3 */
|
||||
printf("%8s", "raidS3");
|
||||
printf("%8s", raidS3_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raidQP_int8(buffer, diskmax, block_size);
|
||||
raidS3_int8(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -397,7 +395,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
raidQP_ssse3(buffer, diskmax, block_size);
|
||||
raidS3_ssse3(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -405,7 +403,51 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raidQP_ssse3ext(buffer, diskmax, block_size);
|
||||
raidS3_ssse3ext(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
/* RAIDS4 */
|
||||
printf("%8s", "raidS4");
|
||||
printf("%8s", raidS4_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raidS4_int8(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
printf("%8s", "");
|
||||
printf("%8s", "");
|
||||
|
||||
if (cpu_has_sse2()) {
|
||||
printf("%8s", "");
|
||||
|
||||
#if defined(__x86_64__)
|
||||
printf("%8s", "");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
raidS4_ssse3(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raidS4_ssse3ext(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -415,13 +457,13 @@ void speed(void)
|
|||
#endif
|
||||
printf("\n");
|
||||
|
||||
/* RAIDPP */
|
||||
printf("%8s", "raidPP");
|
||||
printf("%8s", raidPP_tag());
|
||||
/* RAIDS5 */
|
||||
printf("%8s", "raidS5");
|
||||
printf("%8s", raidS5_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raidPP_int8(buffer, diskmax, block_size);
|
||||
raidS5_int8(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -441,7 +483,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
raidPP_ssse3(buffer, diskmax, block_size);
|
||||
raidS5_ssse3(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -449,7 +491,7 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raidPP_ssse3ext(buffer, diskmax, block_size);
|
||||
raidS5_ssse3ext(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -459,13 +501,13 @@ void speed(void)
|
|||
#endif
|
||||
printf("\n");
|
||||
|
||||
/* RAIDHP */
|
||||
printf("%8s", "raidHP");
|
||||
printf("%8s", raidHP_tag());
|
||||
/* RAIDS6 */
|
||||
printf("%8s", "raidS6");
|
||||
printf("%8s", raidS6_tag());
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
raidHP_int8(buffer, diskmax, block_size);
|
||||
raidS6_int8(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -485,7 +527,7 @@ void speed(void)
|
|||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
raidHP_ssse3(buffer, diskmax, block_size);
|
||||
raidS6_ssse3(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
@ -493,7 +535,7 @@ void speed(void)
|
|||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
raidHP_ssse3ext(buffer, diskmax, block_size);
|
||||
raidS6_ssse3ext(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf("%8"PRIu64, ds / dt);
|
||||
|
|
|
|||
21
state.c
21
state.c
|
|
@ -58,10 +58,10 @@ const char* lev_raid_name(unsigned n)
|
|||
switch (n) {
|
||||
case 1 : return "raid5";
|
||||
case 2 : return "raid6";
|
||||
case 3 : return "raidTP";
|
||||
case 4 : return "raidQP";
|
||||
case 5 : return "raidPP";
|
||||
case 6 : return "raidHP";
|
||||
case 3 : return "raidS3";
|
||||
case 4 : return "raidS4";
|
||||
case 5 : return "raidS5";
|
||||
case 6 : return "raidS6";
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -75,6 +75,7 @@ void state_init(struct snapraid_state* state)
|
|||
state->autosave = 0;
|
||||
state->need_write = 0;
|
||||
state->block_size = 256 * 1024; /* default 256 KiB */
|
||||
state->raid_mode = RAID_MODE_S;
|
||||
for(l=0;l<LEV_MAX;++l) {
|
||||
state->parity_path[l][0] = 0;
|
||||
state->parity_device[l] = 0;
|
||||
|
|
@ -117,6 +118,13 @@ static void state_config_check(struct snapraid_state* state, const char* path, t
|
|||
tommy_node* i;
|
||||
unsigned l;
|
||||
|
||||
if (state->raid_mode == RAID_MODE_Z) {
|
||||
if (state->level > RAID_PARITY_Z_MAX) {
|
||||
fprintf(stderr, "If you use the z-parity you cannot have more than %u parities.\n", RAID_PARITY_Z_MAX);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for(l=0;l<state->level;++l) {
|
||||
if (state->parity_path[l][0] == 0) {
|
||||
fprintf(stderr, "No '%s' specification in '%s'\n", lev_config_name(l), path);
|
||||
|
|
@ -370,6 +378,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
|| strcmp(tag, "s-parity") == 0
|
||||
|| strcmp(tag, "t-parity") == 0
|
||||
|| strcmp(tag, "u-parity") == 0
|
||||
|| strcmp(tag, "z-parity") == 0
|
||||
) {
|
||||
char device[PATH_MAX];
|
||||
char* slash;
|
||||
|
|
@ -383,6 +392,10 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
case 's' : l = 3; break;
|
||||
case 't' : l = 4; break;
|
||||
case 'u' : l = 5; break;
|
||||
case 'z' :
|
||||
l = 2;
|
||||
state->raid_mode = RAID_MODE_Z;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid '%s' specification in '%s' at line %u\n", tag, path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
|
|||
1
state.h
1
state.h
|
|
@ -87,6 +87,7 @@ struct snapraid_state {
|
|||
uint64_t autosave; /**< Autosave after the specified amount of data. 0 to disable. */
|
||||
int need_write; /**< If the state is changed. */
|
||||
uint32_t block_size; /**< Block size in bytes. */
|
||||
unsigned raid_mode; /**< Raid mode to use. RAID_MODE_DEFAULT or RAID_MODE_ALTERNATE. */
|
||||
char parity_path[LEV_MAX][PATH_MAX]; /**< Path of the parity file. One for each parity. */
|
||||
uint64_t parity_device[LEV_MAX]; /**< Device identifier of the parity. One for each parity. */
|
||||
char pool[PATH_MAX]; /**< Path of the pool tree. */
|
||||
|
|
|
|||
114
tables.h
114
tables.h
|
|
@ -8796,6 +8796,120 @@ const unsigned char __attribute__((aligned(256))) gfinv[256] =
|
|||
0x42, 0xd4, 0xe8, 0x75, 0x7f, 0xff, 0x7e, 0xfd,
|
||||
};
|
||||
|
||||
/**
|
||||
* Power matrix used to generate parity.
|
||||
* This matrix is valid for up to 3 parity with 251 data disks.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
const unsigned char __attribute__((aligned(256))) gfpower[3][256] =
|
||||
{
|
||||
{
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01,
|
||||
},
|
||||
{
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
|
||||
0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
|
||||
0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9,
|
||||
0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0,
|
||||
0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35,
|
||||
0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23,
|
||||
0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0,
|
||||
0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1,
|
||||
0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc,
|
||||
0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0,
|
||||
0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f,
|
||||
0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2,
|
||||
0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88,
|
||||
0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce,
|
||||
0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93,
|
||||
0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc,
|
||||
0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9,
|
||||
0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54,
|
||||
0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa,
|
||||
0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73,
|
||||
0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e,
|
||||
0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff,
|
||||
0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4,
|
||||
0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41,
|
||||
0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e,
|
||||
0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6,
|
||||
0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef,
|
||||
0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09,
|
||||
0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5,
|
||||
0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16,
|
||||
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83,
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Cauchy matrix used to generate parity.
|
||||
* This matrix is valid for up to 6 parity with 251 data disks.
|
||||
|
|
|
|||
4
util.c
4
util.c
|
|
@ -1362,13 +1362,13 @@ void* malloc_nofail_align(size_t size, void** freeptr)
|
|||
*
|
||||
* RAID5 sse2x4 21936 [MB/s]
|
||||
* RAID6 sse2x2 11902 [MB/s]
|
||||
* RAIDTP sse2x1 5838 [MB/s]
|
||||
* RAIDZ3 sse2x1 5838 [MB/s]
|
||||
*
|
||||
* Without displacement:
|
||||
*
|
||||
* RAID5 sse2x4 15368 [MB/s]
|
||||
* RAID6 sse2x2 6814 [MB/s]
|
||||
* RAIDTP sse2x1 3033 [MB/s]
|
||||
* RAIDZ3 sse2x1 3033 [MB/s]
|
||||
*/
|
||||
#define MALLOC_DISPLACEMENT (7*256)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue