mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Changes the argument format of raid_rec() and renames raid_par() to raid_gen().
This commit is contained in:
parent
365b4127c0
commit
00a05a80e5
15 changed files with 363 additions and 390 deletions
36
raid/int.c
36
raid/int.c
|
|
@ -16,9 +16,9 @@
|
|||
#include "gf.h"
|
||||
|
||||
/*
|
||||
* PAR1 (RAID5 with xor) 32bit C implementation
|
||||
* GEN1 (RAID5 with xor) 32bit C implementation
|
||||
*/
|
||||
void raid_par1_int32(int nd, size_t size, void **vv)
|
||||
void raid_gen1_int32(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -44,9 +44,9 @@ void raid_par1_int32(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* PAR1 (RAID5 with xor) 64bit C implementation
|
||||
* GEN1 (RAID5 with xor) 64bit C implementation
|
||||
*/
|
||||
void raid_par1_int64(int nd, size_t size, void **vv)
|
||||
void raid_gen1_int64(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -72,9 +72,9 @@ void raid_par1_int64(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* PAR2 (RAID6 with powers of 2) 32bit C implementation
|
||||
* GEN2 (RAID6 with powers of 2) 32bit C implementation
|
||||
*/
|
||||
void raid_par2_int32(int nd, size_t size, void **vv)
|
||||
void raid_gen2_int32(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -113,9 +113,9 @@ void raid_par2_int32(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* PAR2 (RAID6 with powers of 2) 64bit C implementation
|
||||
* GEN2 (RAID6 with powers of 2) 64bit C implementation
|
||||
*/
|
||||
void raid_par2_int64(int nd, size_t size, void **vv)
|
||||
void raid_gen2_int64(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -154,14 +154,14 @@ void raid_par2_int64(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* PAR3 (triple parity with Cauchy matrix) 8bit C implementation
|
||||
* GEN3 (triple parity with Cauchy matrix) 8bit C implementation
|
||||
*
|
||||
* Note that instead of a generic multiplication 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 raid_par3_int8(int nd, size_t size, void **vv)
|
||||
void raid_gen3_int8(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -201,14 +201,14 @@ void raid_par3_int8(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* PAR4 (quad parity with Cauchy matrix) 8bit C implementation
|
||||
* GEN4 (quad parity with Cauchy matrix) 8bit C implementation
|
||||
*
|
||||
* Note that instead of a generic multiplication 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 raid_par4_int8(int nd, size_t size, void **vv)
|
||||
void raid_gen4_int8(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -253,14 +253,14 @@ void raid_par4_int8(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* PAR5 (penta parity with Cauchy matrix) 8bit C implementation
|
||||
* GEN5 (penta parity with Cauchy matrix) 8bit C implementation
|
||||
*
|
||||
* Note that instead of a generic multiplication 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 raid_par5_int8(int nd, size_t size, void **vv)
|
||||
void raid_gen5_int8(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -310,14 +310,14 @@ void raid_par5_int8(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* PAR6 (hexa parity with Cauchy matrix) 8bit C implementation
|
||||
* GEN6 (hexa parity with Cauchy matrix) 8bit C implementation
|
||||
*
|
||||
* Note that instead of a generic multiplication 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 raid_par6_int8(int nd, size_t size, void **vv)
|
||||
void raid_gen6_int8(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -397,7 +397,7 @@ void raid_rec1_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv)
|
|||
|
||||
/* if it's RAID5 uses the faster function */
|
||||
if (ip[0] == 0) {
|
||||
raid_rec1_par1(id, nd, size, vv);
|
||||
raid_rec1of1(id, nd, size, vv);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -454,7 +454,7 @@ void raid_rec2_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv)
|
|||
|
||||
/* if it's RAID6 recovering with P and Q uses the faster function */
|
||||
if (ip[0] == 0 && ip[1] == 1) {
|
||||
raid_rec2_par2(id, ip, nd, size, vv);
|
||||
raid_rec2of2_int8(id, ip, nd, size, vv);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,34 +32,34 @@
|
|||
* These are intented to provide access for testing.
|
||||
*/
|
||||
int raid_selftest(void);
|
||||
void raid_par_ref(int nd, int np, size_t size, void **vv);
|
||||
void raid_gen_ref(int nd, int np, size_t size, void **vv);
|
||||
void raid_invert(uint8_t *M, uint8_t *V, int n);
|
||||
void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v);
|
||||
void raid_rec1_par1(int *id, int nd, size_t size, void **v);
|
||||
void raid_rec2_par2(int *id, int *ip, int nd, size_t size, void **vv);
|
||||
void raid_par1_int32(int nd, size_t size, void **vv);
|
||||
void raid_par1_int64(int nd, size_t size, void **vv);
|
||||
void raid_par1_sse2(int nd, size_t size, void **vv);
|
||||
void raid_par2_int32(int nd, size_t size, void **vv);
|
||||
void raid_par2_int64(int nd, size_t size, void **vv);
|
||||
void raid_par2_sse2(int nd, size_t size, void **vv);
|
||||
void raid_par2_sse2ext(int nd, size_t size, void **vv);
|
||||
void raid_parz_int32(int nd, size_t size, void **vv);
|
||||
void raid_parz_int64(int nd, size_t size, void **vv);
|
||||
void raid_parz_sse2(int nd, size_t size, void **vv);
|
||||
void raid_parz_sse2ext(int nd, size_t size, void **vv);
|
||||
void raid_par3_int8(int nd, size_t size, void **vv);
|
||||
void raid_par3_ssse3(int nd, size_t size, void **vv);
|
||||
void raid_par3_ssse3ext(int nd, size_t size, void **vv);
|
||||
void raid_par4_int8(int nd, size_t size, void **vv);
|
||||
void raid_par4_ssse3(int nd, size_t size, void **vv);
|
||||
void raid_par4_ssse3ext(int nd, size_t size, void **vv);
|
||||
void raid_par5_int8(int nd, size_t size, void **vv);
|
||||
void raid_par5_ssse3(int nd, size_t size, void **vv);
|
||||
void raid_par5_ssse3ext(int nd, size_t size, void **vv);
|
||||
void raid_par6_int8(int nd, size_t size, void **vv);
|
||||
void raid_par6_ssse3(int nd, size_t size, void **vv);
|
||||
void raid_par6_ssse3ext(int nd, size_t size, void **vv);
|
||||
void raid_rec1of1(int *id, int nd, size_t size, void **v);
|
||||
void raid_rec2of2_int8(int *id, int *ip, int nd, size_t size, void **vv);
|
||||
void raid_gen1_int32(int nd, size_t size, void **vv);
|
||||
void raid_gen1_int64(int nd, size_t size, void **vv);
|
||||
void raid_gen1_sse2(int nd, size_t size, void **vv);
|
||||
void raid_gen2_int32(int nd, size_t size, void **vv);
|
||||
void raid_gen2_int64(int nd, size_t size, void **vv);
|
||||
void raid_gen2_sse2(int nd, size_t size, void **vv);
|
||||
void raid_gen2_sse2ext(int nd, size_t size, void **vv);
|
||||
void raid_genz_int32(int nd, size_t size, void **vv);
|
||||
void raid_genz_int64(int nd, size_t size, void **vv);
|
||||
void raid_genz_sse2(int nd, size_t size, void **vv);
|
||||
void raid_genz_sse2ext(int nd, size_t size, void **vv);
|
||||
void raid_gen3_int8(int nd, size_t size, void **vv);
|
||||
void raid_gen3_ssse3(int nd, size_t size, void **vv);
|
||||
void raid_gen3_ssse3ext(int nd, size_t size, void **vv);
|
||||
void raid_gen4_int8(int nd, size_t size, void **vv);
|
||||
void raid_gen4_ssse3(int nd, size_t size, void **vv);
|
||||
void raid_gen4_ssse3ext(int nd, size_t size, void **vv);
|
||||
void raid_gen5_int8(int nd, size_t size, void **vv);
|
||||
void raid_gen5_ssse3(int nd, size_t size, void **vv);
|
||||
void raid_gen5_ssse3ext(int nd, size_t size, void **vv);
|
||||
void raid_gen6_int8(int nd, size_t size, void **vv);
|
||||
void raid_gen6_ssse3(int nd, size_t size, void **vv);
|
||||
void raid_gen6_ssse3ext(int nd, size_t size, void **vv);
|
||||
void raid_rec1_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv);
|
||||
void raid_rec2_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv);
|
||||
void raid_recX_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv);
|
||||
|
|
@ -72,13 +72,13 @@ void raid_recX_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv);
|
|||
*
|
||||
* These are intented to provide access for testing.
|
||||
*/
|
||||
const char *raid_par1_tag(void);
|
||||
const char *raid_par2_tag(void);
|
||||
const char *raid_parz_tag(void);
|
||||
const char *raid_par3_tag(void);
|
||||
const char *raid_par4_tag(void);
|
||||
const char *raid_par5_tag(void);
|
||||
const char *raid_par6_tag(void);
|
||||
const char *raid_gen1_tag(void);
|
||||
const char *raid_gen2_tag(void);
|
||||
const char *raid_genz_tag(void);
|
||||
const char *raid_gen3_tag(void);
|
||||
const char *raid_gen4_tag(void);
|
||||
const char *raid_gen5_tag(void);
|
||||
const char *raid_gen6_tag(void);
|
||||
const char *raid_rec1_tag(void);
|
||||
const char *raid_rec2_tag(void);
|
||||
const char *raid_recX_tag(void);
|
||||
|
|
@ -86,9 +86,9 @@ const char *raid_recX_tag(void);
|
|||
/*
|
||||
* Internal forwarders.
|
||||
*/
|
||||
extern void (*raid_par3_ptr)(int nd, size_t size, void **vv);
|
||||
extern void (*raid_parz_ptr)(int nd, size_t size, void **vv);
|
||||
extern void (*raid_par_ptr[RAID_PARITY_MAX])(
|
||||
extern void (*raid_gen3_ptr)(int nd, size_t size, void **vv);
|
||||
extern void (*raid_genz_ptr)(int nd, size_t size, void **vv);
|
||||
extern void (*raid_gen_ptr[RAID_PARITY_MAX])(
|
||||
int nd, size_t size, void **vv);
|
||||
extern void (*raid_rec_ptr[RAID_PARITY_MAX])(
|
||||
int nr, int *id, int *ip, int nd, size_t size, void **vv);
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@
|
|||
#include "gf.h"
|
||||
|
||||
/*
|
||||
* PARz (triple parity with powers of 2^-1) 32bit C implementation
|
||||
* GENz (triple parity with powers of 2^-1) 32bit C implementation
|
||||
*/
|
||||
void raid_parz_int32(int nd, size_t size, void **vv)
|
||||
void raid_genz_int32(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -67,9 +67,9 @@ void raid_parz_int32(int nd, size_t size, void **vv)
|
|||
}
|
||||
|
||||
/*
|
||||
* PARz (triple parity with powers of 2^-1) 64bit C implementation
|
||||
* GENz (triple parity with powers of 2^-1) 64bit C implementation
|
||||
*/
|
||||
void raid_parz_int64(int nd, size_t size, void **vv)
|
||||
void raid_genz_int64(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
|
|||
|
|
@ -38,20 +38,20 @@
|
|||
* The selected value was choosen empirically with some speed tests
|
||||
* with 8/12/16/20/24 data buffers of 256 KB.
|
||||
*
|
||||
* These are the results with no displacement:
|
||||
* These are the results in MB/s with no displacement:
|
||||
*
|
||||
* sse2
|
||||
* par1 15368 [MB/s]
|
||||
* par2 6814 [MB/s]
|
||||
* parz 3033 [MB/s]
|
||||
* gen1 15368 [MB/s]
|
||||
* gen2 6814 [MB/s]
|
||||
* genz 3033 [MB/s]
|
||||
*
|
||||
* These are the results with displacement resulting in improvments
|
||||
* in the order of 20% or more:
|
||||
*
|
||||
* sse2
|
||||
* par1 21936 [MB/s]
|
||||
* par2 11902 [MB/s]
|
||||
* parz 5838 [MB/s]
|
||||
* gen1 21936 [MB/s]
|
||||
* gen2 11902 [MB/s]
|
||||
* genz 5838 [MB/s]
|
||||
*
|
||||
*/
|
||||
#define RAID_MALLOC_DISPLACEMENT (7*256)
|
||||
|
|
|
|||
221
raid/module.c
221
raid/module.c
|
|
@ -21,19 +21,19 @@
|
|||
*/
|
||||
void raid_init(void)
|
||||
{
|
||||
raid_par3_ptr = raid_par3_int8;
|
||||
raid_par_ptr[3] = raid_par4_int8;
|
||||
raid_par_ptr[4] = raid_par5_int8;
|
||||
raid_par_ptr[5] = raid_par6_int8;
|
||||
raid_gen3_ptr = raid_gen3_int8;
|
||||
raid_gen_ptr[3] = raid_gen4_int8;
|
||||
raid_gen_ptr[4] = raid_gen5_int8;
|
||||
raid_gen_ptr[5] = raid_gen6_int8;
|
||||
|
||||
if (sizeof(void *) == 4) {
|
||||
raid_par_ptr[0] = raid_par1_int32;
|
||||
raid_par_ptr[1] = raid_par2_int32;
|
||||
raid_parz_ptr = raid_parz_int32;
|
||||
raid_gen_ptr[0] = raid_gen1_int32;
|
||||
raid_gen_ptr[1] = raid_gen2_int32;
|
||||
raid_genz_ptr = raid_genz_int32;
|
||||
} else {
|
||||
raid_par_ptr[0] = raid_par1_int64;
|
||||
raid_par_ptr[1] = raid_par2_int64;
|
||||
raid_parz_ptr = raid_parz_int64;
|
||||
raid_gen_ptr[0] = raid_gen1_int64;
|
||||
raid_gen_ptr[1] = raid_gen2_int64;
|
||||
raid_genz_ptr = raid_genz_int64;
|
||||
}
|
||||
|
||||
raid_rec_ptr[0] = raid_rec1_int8;
|
||||
|
|
@ -45,32 +45,32 @@ void raid_init(void)
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
if (raid_cpu_has_sse2()) {
|
||||
raid_par_ptr[0] = raid_par1_sse2;
|
||||
raid_gen_ptr[0] = raid_gen1_sse2;
|
||||
#ifdef CONFIG_X86_64
|
||||
if (raid_cpu_has_slowextendedreg()) {
|
||||
raid_par_ptr[1] = raid_par2_sse2;
|
||||
raid_parz_ptr = raid_parz_sse2;
|
||||
raid_gen_ptr[1] = raid_gen2_sse2;
|
||||
raid_genz_ptr = raid_genz_sse2;
|
||||
} else {
|
||||
raid_par_ptr[1] = raid_par2_sse2ext;
|
||||
raid_parz_ptr = raid_parz_sse2ext;
|
||||
raid_gen_ptr[1] = raid_gen2_sse2ext;
|
||||
raid_genz_ptr = raid_genz_sse2ext;
|
||||
}
|
||||
#else
|
||||
raid_par_ptr[1] = raid_par2_sse2;
|
||||
raid_parz_ptr = raid_parz_sse2;
|
||||
raid_gen_ptr[1] = raid_gen2_sse2;
|
||||
raid_genz_ptr = raid_genz_sse2;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
#ifdef CONFIG_X86_64
|
||||
raid_par3_ptr = raid_par3_ssse3ext;
|
||||
raid_par_ptr[3] = raid_par4_ssse3ext;
|
||||
raid_par_ptr[4] = raid_par5_ssse3ext;
|
||||
raid_par_ptr[5] = raid_par6_ssse3ext;
|
||||
raid_gen3_ptr = raid_gen3_ssse3ext;
|
||||
raid_gen_ptr[3] = raid_gen4_ssse3ext;
|
||||
raid_gen_ptr[4] = raid_gen5_ssse3ext;
|
||||
raid_gen_ptr[5] = raid_gen6_ssse3ext;
|
||||
#else
|
||||
raid_par3_ptr = raid_par3_ssse3;
|
||||
raid_par_ptr[3] = raid_par4_ssse3;
|
||||
raid_par_ptr[4] = raid_par5_ssse3;
|
||||
raid_par_ptr[5] = raid_par6_ssse3;
|
||||
raid_gen3_ptr = raid_gen3_ssse3;
|
||||
raid_gen_ptr[3] = raid_gen4_ssse3;
|
||||
raid_gen_ptr[4] = raid_gen5_ssse3;
|
||||
raid_gen_ptr[5] = raid_gen6_ssse3;
|
||||
#endif
|
||||
raid_rec_ptr[0] = raid_rec1_ssse3;
|
||||
raid_rec_ptr[1] = raid_rec2_ssse3;
|
||||
|
|
@ -88,7 +88,7 @@ void raid_init(void)
|
|||
/*
|
||||
* Refence parity computation.
|
||||
*/
|
||||
void raid_par_ref(int nd, int np, size_t size, void **vv)
|
||||
void raid_gen_ref(int nd, int np, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
size_t i;
|
||||
|
|
@ -138,7 +138,7 @@ static int raid_test_par(int nd, int np, size_t size, void **v, void **ref)
|
|||
for (i = 0; i < np; ++i)
|
||||
t[nd+i] = v[nd+i];
|
||||
|
||||
raid_par(nd, np, size, t);
|
||||
raid_gen(nd, np, size, t);
|
||||
|
||||
/* compare parity */
|
||||
for (i = 0; i < np; ++i)
|
||||
|
|
@ -151,37 +151,31 @@ static int raid_test_par(int nd, int np, size_t size, void **v, void **ref)
|
|||
/*
|
||||
* Recovering test.
|
||||
*/
|
||||
static int raid_test_rec(int nrd, int *id, int nrp, int *ip, int nd, int np, size_t size, void **v, void **ref)
|
||||
static int raid_test_rec(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref)
|
||||
{
|
||||
int i, j;
|
||||
void *t[TEST_COUNT + RAID_PARITY_MAX];
|
||||
|
||||
/* setup data */
|
||||
for (i = 0, j = 0; i < nd; ++i) {
|
||||
if (j < nrd && id[j] == i) {
|
||||
/* setup vector */
|
||||
for (i = 0, j = 0; i < nd+np; ++i) {
|
||||
if (j < nr && ir[j] == i) {
|
||||
/* this block has to be recovered */
|
||||
t[i] = v[i];
|
||||
++j;
|
||||
} else {
|
||||
/* this block is left unchanged */
|
||||
t[i] = ref[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* setup parity */
|
||||
for (i = 0, j = 0; i < np; ++i) {
|
||||
if (j < nrp && ip[j] == i) {
|
||||
t[nd+i] = v[nd+i];
|
||||
++j;
|
||||
} else {
|
||||
t[nd+i] = ref[nd+i];
|
||||
}
|
||||
}
|
||||
|
||||
raid_rec(nrd, id, nrp, ip, nd, np, size, t);
|
||||
raid_rec(nr, ir, nd, np, size, t);
|
||||
|
||||
/* compare all data and parity */
|
||||
for (i = 0; i < nd+np; ++i)
|
||||
if (t[i] != ref[i] && memcmp(t[i], ref[i], size) != 0)
|
||||
for (i = 0; i < nd+np; ++i) {
|
||||
if (t[i] != ref[i] && memcmp(t[i], ref[i], size) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -197,8 +191,7 @@ int raid_selftest(void)
|
|||
void *v_alloc;
|
||||
void **v;
|
||||
void *ref[nd + RAID_PARITY_MAX];
|
||||
int id[RAID_PARITY_MAX];
|
||||
int ip[RAID_PARITY_MAX];
|
||||
int ir[RAID_PARITY_MAX];
|
||||
int i, np;
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -221,7 +214,7 @@ int raid_selftest(void)
|
|||
ref[nd+i] = v[nd+RAID_PARITY_MAX+i];
|
||||
|
||||
/* compute reference parity */
|
||||
raid_par_ref(nd, RAID_PARITY_MAX, size, ref);
|
||||
raid_gen_ref(nd, RAID_PARITY_MAX, size, ref);
|
||||
|
||||
/* test for each parity level */
|
||||
for (np = 1; np <= RAID_PARITY_MAX; ++np) {
|
||||
|
|
@ -232,31 +225,31 @@ int raid_selftest(void)
|
|||
|
||||
/* test recovering with full broken data disks */
|
||||
for (i = 0; i < np; ++i)
|
||||
id[i] = nd - np + i;
|
||||
ir[i] = nd - np + i;
|
||||
|
||||
ret = raid_test_rec(np, id, 0, ip, nd, np, size, v, ref);
|
||||
if (ret != 0)
|
||||
goto bail;
|
||||
|
||||
/* test recovering with half broken data and ending parity */
|
||||
for (i = 0; i < np / 2; ++i)
|
||||
id[i] = i;
|
||||
|
||||
for (i = 0; i < (np + 1) / 2; ++i)
|
||||
ip[i] = np - np / 2 + i;
|
||||
|
||||
ret = raid_test_rec(np / 2, id, np / 2, ip, nd, np, size, v, ref);
|
||||
ret = raid_test_rec(np, ir, nd, np, size, v, ref);
|
||||
if (ret != 0)
|
||||
goto bail;
|
||||
|
||||
/* test recovering with half broken data and leading parity */
|
||||
for (i = 0; i < np / 2; ++i)
|
||||
id[i] = i;
|
||||
ir[i] = i;
|
||||
|
||||
for (i = 0; i < (np + 1) / 2; ++i)
|
||||
ip[i] = i;
|
||||
ir[np / 2 + i] = nd + i;
|
||||
|
||||
ret = raid_test_rec(np / 2, id, np / 2, ip, nd, np, size, v, ref);
|
||||
ret = raid_test_rec(np, ir, nd, np, size, v, ref);
|
||||
if (ret != 0)
|
||||
goto bail;
|
||||
|
||||
/* test recovering with half broken data and ending parity */
|
||||
for (i = 0; i < np / 2; ++i)
|
||||
ir[i] = i;
|
||||
|
||||
for (i = 0; i < (np + 1) / 2; ++i)
|
||||
ir[np / 2 + i] = nd + np - (np + 1) / 2 + i;
|
||||
|
||||
ret = raid_test_rec(np, ir, nd, np, size, v, ref);
|
||||
if (ret != 0)
|
||||
goto bail;
|
||||
}
|
||||
|
|
@ -267,106 +260,4 @@ bail:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct raid_func {
|
||||
const char *name;
|
||||
void *p;
|
||||
} RAID_FUNC[] = {
|
||||
{ "int8", raid_par3_int8 },
|
||||
{ "int8", raid_par4_int8 },
|
||||
{ "int8", raid_par5_int8 },
|
||||
{ "int8", raid_par6_int8 },
|
||||
{ "int32", raid_par1_int32 },
|
||||
{ "int64", raid_par1_int64 },
|
||||
{ "int32", raid_par2_int32 },
|
||||
{ "int64", raid_par2_int64 },
|
||||
{ "int32", raid_parz_int32 },
|
||||
{ "int64", raid_parz_int64 },
|
||||
{ "int8", raid_rec1_int8 },
|
||||
{ "int8", raid_rec2_int8 },
|
||||
{ "int8", raid_recX_int8 },
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
{ "sse2", raid_par1_sse2 },
|
||||
{ "sse2", raid_par2_sse2 },
|
||||
{ "sse2", raid_parz_sse2 },
|
||||
{ "ssse3", raid_par3_ssse3 },
|
||||
{ "ssse3", raid_par4_ssse3 },
|
||||
{ "ssse3", raid_par5_ssse3 },
|
||||
{ "ssse3", raid_par6_ssse3 },
|
||||
{ "ssse3", raid_rec1_ssse3 },
|
||||
{ "ssse3", raid_rec2_ssse3 },
|
||||
{ "ssse3", raid_recX_ssse3 },
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
{ "sse2e", raid_par2_sse2ext },
|
||||
{ "sse2e", raid_parz_sse2ext },
|
||||
{ "ssse3e", raid_par3_ssse3ext },
|
||||
{ "ssse3e", raid_par4_ssse3ext },
|
||||
{ "ssse3e", raid_par5_ssse3ext },
|
||||
{ "ssse3e", raid_par6_ssse3ext },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static const char *raid_tag(void *func)
|
||||
{
|
||||
struct raid_func *i = RAID_FUNC;
|
||||
while (i->name != 0) {
|
||||
if (i->p == func)
|
||||
return i->name;
|
||||
++i;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char *raid_par1_tag(void)
|
||||
{
|
||||
return raid_tag(raid_par_ptr[0]);
|
||||
}
|
||||
|
||||
const char *raid_par2_tag(void)
|
||||
{
|
||||
return raid_tag(raid_par_ptr[1]);
|
||||
}
|
||||
|
||||
const char *raid_parz_tag(void)
|
||||
{
|
||||
return raid_tag(raid_parz_ptr);
|
||||
}
|
||||
|
||||
const char *raid_par3_tag(void)
|
||||
{
|
||||
return raid_tag(raid_par_ptr[2]);
|
||||
}
|
||||
|
||||
const char *raid_par4_tag(void)
|
||||
{
|
||||
return raid_tag(raid_par_ptr[3]);
|
||||
}
|
||||
|
||||
const char *raid_par5_tag(void)
|
||||
{
|
||||
return raid_tag(raid_par_ptr[4]);
|
||||
}
|
||||
|
||||
const char *raid_par6_tag(void)
|
||||
{
|
||||
return raid_tag(raid_par_ptr[5]);
|
||||
}
|
||||
|
||||
const char *raid_rec1_tag(void)
|
||||
{
|
||||
return raid_tag(raid_rec_ptr[0]);
|
||||
}
|
||||
|
||||
const char *raid_rec2_tag(void)
|
||||
{
|
||||
return raid_tag(raid_rec_ptr[1]);
|
||||
}
|
||||
|
||||
const char *raid_recX_tag(void)
|
||||
{
|
||||
return raid_tag(raid_rec_ptr[2]);
|
||||
}
|
||||
|
||||
|
|
|
|||
133
raid/raid.c
133
raid/raid.c
|
|
@ -133,12 +133,12 @@
|
|||
* for a Core i7-3740QM CPU @ 2.7GHz is:
|
||||
*
|
||||
* int8 int32 int64 sse2 sse2e ssse3 ssse3e
|
||||
* par1 11927 22075 36004
|
||||
* par2 3378 5874 18235 19164
|
||||
* par3 844 8814 9419
|
||||
* par4 665 6836 7415
|
||||
* par5 537 5388 5686
|
||||
* par6 449 4307 4789
|
||||
* gen1 11927 22075 36004
|
||||
* gen2 3378 5874 18235 19164
|
||||
* gen3 844 8814 9419
|
||||
* gen4 665 6836 7415
|
||||
* gen5 537 5388 5686
|
||||
* gen6 449 4307 4789
|
||||
*
|
||||
* Values are in MiB/s of data processed, not counting generated parity.
|
||||
*
|
||||
|
|
@ -150,7 +150,7 @@
|
|||
* the Cauchy matrix if SSSE3 is present.
|
||||
*
|
||||
* int8 int32 int64 sse2 sse2e ssse3 ssse3e
|
||||
* parz 2112 3118 9589 10304
|
||||
* genz 2112 3118 9589 10304
|
||||
*
|
||||
*
|
||||
* In conclusion, the use of power coefficients, and specifically powers
|
||||
|
|
@ -176,10 +176,10 @@ const uint8_t (*raid_gfgen)[256];
|
|||
void raid_mode(int mode)
|
||||
{
|
||||
if (mode == RAID_MODE_VANDERMONDE) {
|
||||
raid_par_ptr[2] = raid_parz_ptr;
|
||||
raid_gen_ptr[2] = raid_genz_ptr;
|
||||
raid_gfgen = gfvandermonde;
|
||||
} else {
|
||||
raid_par_ptr[2] = raid_par3_ptr;
|
||||
raid_gen_ptr[2] = raid_gen3_ptr;
|
||||
raid_gfgen = gfcauchy;
|
||||
}
|
||||
}
|
||||
|
|
@ -204,22 +204,43 @@ void raid_waste(void *waste)
|
|||
raid_waste_block = waste;
|
||||
}
|
||||
|
||||
/* internal forwarder */
|
||||
void (*raid_par_ptr[RAID_PARITY_MAX])(int nd, size_t size, void **vv);
|
||||
void (*raid_par3_ptr)(int nd, size_t size, void **vv);
|
||||
void (*raid_parz_ptr)(int nd, size_t size, void **vv);
|
||||
/*
|
||||
* Forwarders for parity computation.
|
||||
*
|
||||
* These functions compute the parity blocks from the provided data.
|
||||
*
|
||||
* The number of parities to compute is implicit in the position in the
|
||||
* forwarder vector. Position at index #i, computes (#i+1) parities.
|
||||
*
|
||||
* @nd Number of data blocks
|
||||
* @size Size of the blocks pointed by @v. It must be a multipler of 64.
|
||||
* @v Vector of pointers to the blocks of data and parity.
|
||||
* It has (@nd + #parities) elements. The starting elements are the blocks for
|
||||
* data, following with the parity blocks.
|
||||
* Each block has @size bytes.
|
||||
*/
|
||||
void (*raid_gen_ptr[RAID_PARITY_MAX])(int nd, size_t size, void **vv);
|
||||
void (*raid_gen3_ptr)(int nd, size_t size, void **vv);
|
||||
void (*raid_genz_ptr)(int nd, size_t size, void **vv);
|
||||
|
||||
void raid_par(int nd, int np, size_t size, void **v)
|
||||
void raid_gen(int nd, int np, size_t size, void **v)
|
||||
{
|
||||
BUG_ON(np < 1 || np > RAID_PARITY_MAX);
|
||||
BUG_ON(size % 64 != 0);
|
||||
|
||||
raid_par_ptr[np - 1](nd, size, v);
|
||||
raid_gen_ptr[np - 1](nd, size, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts the square matrix M of size nxn into V.
|
||||
*
|
||||
* This is not a general matrix inversion because we assume the matrix M
|
||||
* to have all the square submatrix not singular.
|
||||
* We use Gauss elimination to invert.
|
||||
*
|
||||
* @M Matrix to invert with @n rows and @n columns.
|
||||
* @V Destination matrix where the result is put.
|
||||
* @n Number of rows and columns of the matrix.
|
||||
*/
|
||||
void raid_invert(uint8_t *M, uint8_t *V, int n)
|
||||
{
|
||||
|
|
@ -235,8 +256,8 @@ void raid_invert(uint8_t *M, uint8_t *V, int n)
|
|||
uint8_t f;
|
||||
|
||||
/* the diagonal element cannot be 0 because */
|
||||
/* we are inverting matrices with all the square submatrices */
|
||||
/* not singular */
|
||||
/* we are inverting matrices with all the square */
|
||||
/* submatrices not singular */
|
||||
BUG_ON(M[k*n+k] == 0);
|
||||
|
||||
/* make the diagonal element to be 1 */
|
||||
|
|
@ -246,7 +267,8 @@ void raid_invert(uint8_t *M, uint8_t *V, int n)
|
|||
V[k*n+j] = mul(f, V[k*n+j]);
|
||||
}
|
||||
|
||||
/* make all the elements over and under the diagonal to be 0 */
|
||||
/* make all the elements over and under the diagonal */
|
||||
/* to be zero */
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (i == k)
|
||||
continue;
|
||||
|
|
@ -290,7 +312,7 @@ void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v)
|
|||
}
|
||||
|
||||
/* recompute the minimal parity required */
|
||||
raid_par(nd, ip[nr - 1] + 1, size, v);
|
||||
raid_gen(nd, ip[nr - 1] + 1, size, v);
|
||||
|
||||
for (i = 0; i < nr; ++i) {
|
||||
/* restore disk buffers as before */
|
||||
|
|
@ -312,7 +334,7 @@ void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v)
|
|||
*
|
||||
* Dx = Pd
|
||||
*/
|
||||
void raid_rec1_par1(int *id, int nd, size_t size, void **v)
|
||||
void raid_rec1of1(int *id, int nd, size_t size, void **v)
|
||||
{
|
||||
void *p;
|
||||
void *pa;
|
||||
|
|
@ -329,7 +351,7 @@ void raid_rec1_par1(int *id, int nd, size_t size, void **v)
|
|||
v[nd] = pa;
|
||||
|
||||
/* compute */
|
||||
raid_par(nd, 1, size, v);
|
||||
raid_gen(nd, 1, size, v);
|
||||
|
||||
/* restore as before */
|
||||
v[id[0]] = pa;
|
||||
|
|
@ -359,7 +381,7 @@ void raid_rec1_par1(int *id, int nd, size_t size, void **v)
|
|||
*
|
||||
* That are always satisfied for any 0<=id[0]<id[1]<255.
|
||||
*/
|
||||
void raid_rec2_par2(int *id, int *ip, int nd, size_t size, void **vv)
|
||||
void raid_rec2of2_int8(int *id, int *ip, int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
size_t i;
|
||||
|
|
@ -396,40 +418,87 @@ void raid_rec2_par2(int *id, int *ip, int nd, size_t size, void **vv)
|
|||
}
|
||||
}
|
||||
|
||||
/* internal forwarder */
|
||||
/*
|
||||
* Forwarders for data recovery.
|
||||
*
|
||||
* These functions recover data blocks using the specified parity
|
||||
* to recompute the missing data.
|
||||
*
|
||||
* Note that the format of vectors @id/@ip is different than raid_rec().
|
||||
* For example, in the vector @ip the first parity is represented with the
|
||||
* value 0 and not @nd.
|
||||
*
|
||||
* @nr Number of failed data blocks to recover.
|
||||
* @id[] Vector of @nr indexes of the data blocks to recover.
|
||||
* The indexes start from 0. They must be in order.
|
||||
* @ip[] Vector of @nr indexes of the parity blocks to use in the recovering.
|
||||
* The indexes start from 0. They must be in order.
|
||||
* @nd Number of data blocks.
|
||||
* @np Number of parity blocks.
|
||||
* @size Size of the blocks pointed by @v. It must be a multipler of 64.
|
||||
* @v Vector of pointers to the blocks of data and parity.
|
||||
* It has (@nd + @np) elements. The starting elements are the blocks
|
||||
* for data, following with the parity blocks.
|
||||
* Each block has @size bytes.
|
||||
*/
|
||||
void (*raid_rec_ptr[RAID_PARITY_MAX])(
|
||||
int nr, int *id, int *ip, int nd, size_t size, void **vv);
|
||||
|
||||
void raid_rec(int nrd, int *id, int nrp, int *ip, int nd, int np, size_t size, void **v)
|
||||
void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v)
|
||||
{
|
||||
BUG_ON(nrd > nd);
|
||||
BUG_ON(nrd + nrp > np);
|
||||
int nrd; /* number of data blocks to recover */
|
||||
int nrp; /* number of parity blocks to recover */
|
||||
|
||||
/* enforce limits on size */
|
||||
BUG_ON(size % 64 != 0);
|
||||
|
||||
/* enforce the order in the index vector */
|
||||
BUG_ON(nr >= 2 && ir[0] > ir[1]);
|
||||
BUG_ON(nr >= 3 && ir[1] > ir[2]);
|
||||
BUG_ON(nr >= 4 && ir[2] > ir[3]);
|
||||
BUG_ON(nr >= 5 && ir[3] > ir[4]);
|
||||
BUG_ON(nr >= 6 && ir[4] > ir[5]);
|
||||
|
||||
/* counts the number of data blocks to recover */
|
||||
nrd = 0;
|
||||
while (nrd < nr && ir[nrd] < nd)
|
||||
++nrd;
|
||||
|
||||
/* all the remaining are parity */
|
||||
nrp = nr - nrd;
|
||||
|
||||
/* enforce basic sanity in arguments */
|
||||
BUG_ON(nrd > nd);
|
||||
BUG_ON(nrp > np);
|
||||
|
||||
/* ensure that we have enough parity to recover */
|
||||
BUG_ON(nrd + nrp > np);
|
||||
|
||||
/* if failed data is present */
|
||||
if (nrd != 0) {
|
||||
int iu[RAID_PARITY_MAX];
|
||||
int ip[RAID_PARITY_MAX];
|
||||
int i, j, k;
|
||||
|
||||
/* setup the vector of parities to use */
|
||||
for (i = 0, j = 0, k = 0; i < np; ++i) {
|
||||
if (j < nrp && ip[j] == i) {
|
||||
if (j < nrp && ir[nrd + j] == nd + i) {
|
||||
/* this parity has to be recovered */
|
||||
++j;
|
||||
} else {
|
||||
/* this parity is used for recovering */
|
||||
iu[k] = i;
|
||||
ip[k] = i;
|
||||
++k;
|
||||
}
|
||||
}
|
||||
|
||||
/* recover the data, and limit the parity use to needed ones */
|
||||
raid_rec_ptr[nrd - 1](nrd, id, iu, nd, size, v);
|
||||
/* recover the nrd data blocks specified in ir[], */
|
||||
/* using the first nrd parity in ip[] for recovering */
|
||||
raid_rec_ptr[nrd - 1](nrd, ir, ip, nd, size, v);
|
||||
}
|
||||
|
||||
/* recompute all the parities up to the last bad one */
|
||||
if (nrp != 0)
|
||||
raid_par(nd, ip[nrp - 1] + 1, size, v);
|
||||
raid_gen(nd, ir[nr - 1] - nd + 1, size, v);
|
||||
}
|
||||
|
||||
void raid_rec_dataonly(int nr, int *id, int *ip, int nd, size_t size, void **v)
|
||||
|
|
|
|||
54
raid/raid.h
54
raid/raid.h
|
|
@ -35,7 +35,7 @@
|
|||
#define RAID_MODE_VANDERMONDE 1
|
||||
|
||||
/**
|
||||
* Max level of parity disks supported.
|
||||
* Maximum number of parity disks supported.
|
||||
*/
|
||||
#define RAID_PARITY_MAX 6
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ int raid_selftest(void);
|
|||
/**
|
||||
* Sets the mode to use. One of RAID_MODE_*.
|
||||
*
|
||||
* You can change mode at any time, and it will affect next calls to raid_par(),
|
||||
* You can change mode at any time, and it will affect next calls to raid_gen(),
|
||||
* raid_rec() and raid_recpar().
|
||||
*
|
||||
* The two modes are compatible for the first two levels of parity.
|
||||
|
|
@ -82,7 +82,12 @@ void raid_zero(void *zero);
|
|||
void raid_waste(void *zero);
|
||||
|
||||
/**
|
||||
* Computes the parity.
|
||||
* Computes the parity blocks.
|
||||
*
|
||||
* This function computes the specified number of parity blocks of the
|
||||
* provided set of data blocks.
|
||||
*
|
||||
* Each parity block, will allow to recover on data block.
|
||||
*
|
||||
* @nd Number of data blocks.
|
||||
* @np Number of parities blocks to compute.
|
||||
|
|
@ -90,38 +95,45 @@ void raid_waste(void *zero);
|
|||
* @v Vector of pointers to the blocks of data and parity.
|
||||
* It has (@nd + @np) elements. The starting elements are the blocks for
|
||||
* data, following with the parity blocks.
|
||||
* Each blocks has @size bytes.
|
||||
* Data blocks are only read and not modified. Parity blocks are written.
|
||||
* Each block has @size bytes.
|
||||
*/
|
||||
void raid_par(int nd, int np, size_t size, void **v);
|
||||
void raid_gen(int nd, int np, size_t size, void **v);
|
||||
|
||||
/**
|
||||
* Recovers failures in data and parity blocks.
|
||||
*
|
||||
* All the data and parity blocks marked as bad in the @id and @ip vector
|
||||
* are recovered and recomputed.
|
||||
* This function recovers all the data and parity blocks marked as bad
|
||||
* in the @ir vector.
|
||||
*
|
||||
* The parities blocks to use for recovering are automatically selected from
|
||||
* the ones NOT present in the @ip vector.
|
||||
* Ensure to have @nr <= @np, otherwise recovering is not possible.
|
||||
*
|
||||
* Ensure to have @nrd + @nrp <= @np, otherwise recovering is not possible.
|
||||
* The parities blocks used for recovering are automatically selected from
|
||||
* the ones NOT present in the @ir vector.
|
||||
*
|
||||
* @nrd Number of failed data blocks to recover.
|
||||
* @id[] Vector of @nrd indexes of the data blocks to recover.
|
||||
* In case there are more parity blocks than needed to recover, the parities
|
||||
* at lower indexes are used in the recovering, and the others are ignored.
|
||||
*
|
||||
* Note that no internal integrity check is done when recovering. If the
|
||||
* provided parities are correct the resulting data will be also correct.
|
||||
* If parities are wrong, also the resulting recovered data will be wrong.
|
||||
* This happens even in the case you have more parities blocks than needed,
|
||||
* and some form of integrity verification is possible.
|
||||
*
|
||||
* @nr Number of failed data and parity blocks to recover.
|
||||
* @ir[] Vector of @nr indexes of the data and parity blocks to recover.
|
||||
* The indexes start from 0. They must be in order.
|
||||
* @nrp Number of failed parity blocks to recover.
|
||||
* @ip[] Vector of @nrp indexes of the parity blocks to recover.
|
||||
* The indexes start from 0. They must be in order.
|
||||
* All the parities not specified here are assumed correct, and they are
|
||||
* not recomputed.
|
||||
* The first parity is represented with value @nd, the second with value
|
||||
* @nd + 1, just like positions in the @v vector.
|
||||
* @nd Number of data blocks.
|
||||
* @np Number of parity blocks.
|
||||
* @size Size of the blocks pointed by @v. It must be a multipler of 64.
|
||||
* @v Vector of pointers to the blocks of data and parity.
|
||||
* It has (@nd + @np) elements. The starting elements are the blocks
|
||||
* for data, following with the parity blocks.
|
||||
* Each blocks has @size bytes.
|
||||
* Each block has @size bytes.
|
||||
*/
|
||||
void raid_rec(int nrd, int *id, int nrp, int *ip, int nd, int np, size_t size, void **v);
|
||||
void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v);
|
||||
|
||||
/**
|
||||
* Recovers failures of data blocks using the specified parities.
|
||||
|
|
@ -150,10 +162,10 @@ void raid_rec_dataonly(int nr, int *id, int *ip, int nd, size_t size, void **v);
|
|||
* Sorts a small vector of integers.
|
||||
*
|
||||
* If you have block indexes not in order, you can use this function to sort
|
||||
* them before callign raid_rec().
|
||||
* them before calling raid_rec().
|
||||
*
|
||||
* @n Number of integers. No more than RAID_PARITY_MAX.
|
||||
* \paran v Vector of integers.
|
||||
* @v Vector of integers.
|
||||
*/
|
||||
void raid_sort(int n, int *v);
|
||||
|
||||
|
|
|
|||
50
raid/test.c
50
raid/test.c
|
|
@ -176,7 +176,7 @@ int raid_test_rec(int mode, int nd, size_t size)
|
|||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_par_ref(nd, np, size, v);
|
||||
raid_gen_ref(nd, np, size, v);
|
||||
|
||||
/* set all the parity to the waste v */
|
||||
for (i = 0; i < np; ++i)
|
||||
|
|
@ -257,7 +257,7 @@ int raid_test_par(int mode, int nd, size_t size)
|
|||
raid_mrand_vector(nv, size, v);
|
||||
|
||||
/* compute the parity */
|
||||
raid_par_ref(nd, np, size, v);
|
||||
raid_gen_ref(nd, np, size, v);
|
||||
|
||||
/* copy in back buffers */
|
||||
for (i = 0; i < np; ++i)
|
||||
|
|
@ -266,50 +266,50 @@ int raid_test_par(int mode, int nd, size_t size)
|
|||
/* load all the available functions */
|
||||
nf = 0;
|
||||
|
||||
f[nf++] = raid_par1_int32;
|
||||
f[nf++] = raid_par1_int64;
|
||||
f[nf++] = raid_par2_int32;
|
||||
f[nf++] = raid_par2_int64;
|
||||
f[nf++] = raid_gen1_int32;
|
||||
f[nf++] = raid_gen1_int64;
|
||||
f[nf++] = raid_gen2_int32;
|
||||
f[nf++] = raid_gen2_int64;
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
if (raid_cpu_has_sse2()) {
|
||||
f[nf++] = raid_par1_sse2;
|
||||
f[nf++] = raid_par2_sse2;
|
||||
f[nf++] = raid_gen1_sse2;
|
||||
f[nf++] = raid_gen2_sse2;
|
||||
#ifdef CONFIG_X86_64
|
||||
f[nf++] = raid_par2_sse2ext;
|
||||
f[nf++] = raid_gen2_sse2ext;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mode == RAID_MODE_CAUCHY) {
|
||||
f[nf++] = raid_par3_int8;
|
||||
f[nf++] = raid_par4_int8;
|
||||
f[nf++] = raid_par5_int8;
|
||||
f[nf++] = raid_par6_int8;
|
||||
f[nf++] = raid_gen3_int8;
|
||||
f[nf++] = raid_gen4_int8;
|
||||
f[nf++] = raid_gen5_int8;
|
||||
f[nf++] = raid_gen6_int8;
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
if (raid_cpu_has_ssse3()) {
|
||||
f[nf++] = raid_par3_ssse3;
|
||||
f[nf++] = raid_par4_ssse3;
|
||||
f[nf++] = raid_par5_ssse3;
|
||||
f[nf++] = raid_par6_ssse3;
|
||||
f[nf++] = raid_gen3_ssse3;
|
||||
f[nf++] = raid_gen4_ssse3;
|
||||
f[nf++] = raid_gen5_ssse3;
|
||||
f[nf++] = raid_gen6_ssse3;
|
||||
#ifdef CONFIG_X86_64
|
||||
f[nf++] = raid_par3_ssse3ext;
|
||||
f[nf++] = raid_par4_ssse3ext;
|
||||
f[nf++] = raid_par5_ssse3ext;
|
||||
f[nf++] = raid_par6_ssse3ext;
|
||||
f[nf++] = raid_gen3_ssse3ext;
|
||||
f[nf++] = raid_gen4_ssse3ext;
|
||||
f[nf++] = raid_gen5_ssse3ext;
|
||||
f[nf++] = raid_gen6_ssse3ext;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
f[nf++] = raid_parz_int32;
|
||||
f[nf++] = raid_parz_int64;
|
||||
f[nf++] = raid_genz_int32;
|
||||
f[nf++] = raid_genz_int64;
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
if (raid_cpu_has_sse2()) {
|
||||
f[nf++] = raid_parz_sse2;
|
||||
f[nf++] = raid_genz_sse2;
|
||||
#ifdef CONFIG_X86_64
|
||||
f[nf++] = raid_parz_sse2ext;
|
||||
f[nf++] = raid_genz_sse2ext;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
46
raid/x86.c
46
raid/x86.c
|
|
@ -17,13 +17,13 @@
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* PAR1 (RAID5 with xor) SSE2 implementation
|
||||
* GEN1 (RAID5 with xor) SSE2 implementation
|
||||
*
|
||||
* Intentionally don't process more than 64 bytes because 64 is the typical
|
||||
* cache block, and processing 128 bytes doesn't increase performance, and in
|
||||
* some cases it even decreases it.
|
||||
*/
|
||||
void raid_par1_sse2(int nd, size_t size, void **vv)
|
||||
void raid_gen1_sse2(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -70,9 +70,9 @@ static const struct gfconst16 {
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* PAR2 (RAID6 with powers of 2) SSE2 implementation
|
||||
* GEN2 (RAID6 with powers of 2) SSE2 implementation
|
||||
*/
|
||||
void raid_par2_sse2(int nd, size_t size, void **vv)
|
||||
void raid_gen2_sse2(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -124,11 +124,11 @@ void raid_par2_sse2(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* PAR2 (RAID6 with powers of 2) SSE2 implementation
|
||||
* GEN2 (RAID6 with powers of 2) SSE2 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raid_par2_sse2ext(int nd, size_t size, void **vv)
|
||||
void raid_gen2_sse2ext(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -204,9 +204,9 @@ void raid_par2_sse2ext(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* PAR3 (triple parity with Cauchy matrix) SSSE3 implementation
|
||||
* GEN3 (triple parity with Cauchy matrix) SSSE3 implementation
|
||||
*/
|
||||
void raid_par3_ssse3(int nd, size_t size, void **vv)
|
||||
void raid_gen3_ssse3(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -301,11 +301,11 @@ void raid_par3_ssse3(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* PAR3 (triple parity with Cauchy matrix) SSSE3 implementation
|
||||
* GEN3 (triple parity with Cauchy matrix) SSSE3 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raid_par3_ssse3ext(int nd, size_t size, void **vv)
|
||||
void raid_gen3_ssse3ext(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -442,9 +442,9 @@ void raid_par3_ssse3ext(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* PAR4 (quad parity with Cauchy matrix) SSSE3 implementation
|
||||
* GEN4 (quad parity with Cauchy matrix) SSSE3 implementation
|
||||
*/
|
||||
void raid_par4_ssse3(int nd, size_t size, void **vv)
|
||||
void raid_gen4_ssse3(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -558,11 +558,11 @@ void raid_par4_ssse3(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* PAR4 (quad parity with Cauchy matrix) SSSE3 implementation
|
||||
* GEN4 (quad parity with Cauchy matrix) SSSE3 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raid_par4_ssse3ext(int nd, size_t size, void **vv)
|
||||
void raid_gen4_ssse3ext(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -731,13 +731,13 @@ void raid_par4_ssse3ext(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* PAR5 (penta parity with Cauchy matrix) SSSE3 implementation
|
||||
* GEN5 (penta parity with Cauchy matrix) 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 raid_par5_ssse3(int nd, size_t size, void **vv)
|
||||
void raid_gen5_ssse3(int nd, size_t size, void **vv)
|
||||
/* ensures that stack is aligned at 16 bytes because we allocate SSE registers in it */
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
|
|
@ -872,11 +872,11 @@ void raid_par5_ssse3(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* PAR5 (penta parity with Cauchy matrix) SSSE3 implementation
|
||||
* GEN5 (penta parity with Cauchy matrix) SSSE3 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raid_par5_ssse3ext(int nd, size_t size, void **vv)
|
||||
void raid_gen5_ssse3ext(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -1005,13 +1005,13 @@ void raid_par5_ssse3ext(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* PAR6 (hexa parity with Cauchy matrix) SSSE3 implementation
|
||||
* GEN6 (hexa parity with Cauchy matrix) 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 raid_par6_ssse3(int nd, size_t size, void **vv)
|
||||
void raid_gen6_ssse3(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -1167,11 +1167,11 @@ void raid_par6_ssse3(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* PAR6 (hexa parity with Cauchy matrix) SSSE3 implementation
|
||||
* GEN6 (hexa parity with Cauchy matrix) SSSE3 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raid_par6_ssse3ext(int nd, size_t size, void **vv)
|
||||
void raid_gen6_ssse3ext(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -1332,7 +1332,7 @@ void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv)
|
|||
|
||||
/* if it's RAID5 uses the faster function */
|
||||
if (ip[0] == 0) {
|
||||
raid_rec1_par1(id, nd, size, vv);
|
||||
raid_rec1of1(id, nd, size, vv);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ static const struct gfzconst16 {
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* PARz (triple parity with powers of 2^-1) SSE2 implementation
|
||||
* GENz (triple parity with powers of 2^-1) SSE2 implementation
|
||||
*/
|
||||
void raid_parz_sse2(int nd, size_t size, void **vv)
|
||||
void raid_genz_sse2(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
@ -89,11 +89,11 @@ void raid_parz_sse2(int nd, size_t size, void **vv)
|
|||
|
||||
#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* PARz (triple parity with powers of 2^-1) SSE2 implementation
|
||||
* GENz (triple parity with powers of 2^-1) SSE2 implementation
|
||||
*
|
||||
* Note that it uses 16 registers, meaning that x64 is required.
|
||||
*/
|
||||
void raid_parz_sse2ext(int nd, size_t size, void **vv)
|
||||
void raid_genz_sse2ext(int nd, size_t size, void **vv)
|
||||
{
|
||||
uint8_t **v = (uint8_t **)vv;
|
||||
uint8_t *p;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue