mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Adds preliminary support for RAID based on a Cauchy matrix.
This commit is contained in:
parent
c95917ecfe
commit
136af37e96
13 changed files with 70993 additions and 238 deletions
7
HISTORY
7
HISTORY
|
|
@ -1,6 +1,13 @@
|
|||
SnapRAID HISTORY
|
||||
================
|
||||
|
||||
6.0 2013/10 (BETA)
|
||||
==================
|
||||
* Added support for unlimted RAIDQP (QuadParity), RAIDPP (Penta Parity)
|
||||
and RAIDHP (Hexa parity).
|
||||
We use a Cauchy parity generator that gets good performance only if
|
||||
SSSE3 is available.
|
||||
|
||||
5.0 2013/10 (BETA)
|
||||
==================
|
||||
* Added support for RAIDTP (Triple Parity) and RAIDQP (Quad Parity).
|
||||
|
|
|
|||
25
check.c
25
check.c
|
|
@ -164,7 +164,7 @@ static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned d
|
|||
/* if we checked something, and no block failed the check */
|
||||
if (hash_checked && j==failed_count) {
|
||||
/* recompute all the redundancy information */
|
||||
raid_gen(state->level, buffer, diskmax, state->block_size);
|
||||
raid_gen(RAID_POWER, state->level, buffer, diskmax, state->block_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -177,12 +177,12 @@ static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned d
|
|||
static int is_parity_matching(struct snapraid_state* state, unsigned diskmax, unsigned i, unsigned char** buffer, unsigned char** buffer_recov)
|
||||
{
|
||||
/* recompute parity, note that we don't need parity over i */
|
||||
raid_gen(i + 1, buffer, diskmax, state->block_size);
|
||||
raid_gen(RAID_POWER, i + 1, buffer, diskmax, state->block_size);
|
||||
|
||||
/* if the recovered parity block matches */
|
||||
if (memcmp(buffer[diskmax+i], buffer_recov[i], state->block_size) == 0) {
|
||||
/* recompute all the redundancy information */
|
||||
raid_gen(state->level, buffer, diskmax, state->block_size);
|
||||
raid_gen(RAID_POWER, state->level, buffer, diskmax, state->block_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -199,11 +199,12 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
unsigned i, j;
|
||||
int error;
|
||||
int has_hash;
|
||||
int kind = RAID_POWER;
|
||||
|
||||
/* no fix required */
|
||||
if (failed_count == 0) {
|
||||
/* recompute only parity and qarity */
|
||||
raid_gen(state->level, buffer, diskmax, state->block_size);
|
||||
raid_gen(kind, state->level, buffer, diskmax, state->block_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -228,7 +229,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
memcpy(buffer[diskmax+COMBO1[i].a], buffer_recov[COMBO1[i].a], state->block_size);
|
||||
|
||||
/* recover data */
|
||||
raid_recov_1data(failed[failed_map[0]].index, COMBO1[i].a, buffer, diskmax, buffer_zero, state->block_size);
|
||||
raid_recov_1data(kind, failed[failed_map[0]].index, COMBO1[i].a, buffer, diskmax, buffer_zero, state->block_size);
|
||||
|
||||
if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero))
|
||||
return 0;
|
||||
|
|
@ -249,7 +250,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
memcpy(buffer[diskmax+COMBO2[i].a], buffer_recov[COMBO2[i].a], state->block_size);
|
||||
|
||||
/* recover data */
|
||||
raid_recov_1data(failed[failed_map[0]].index, COMBO2[i].a, buffer, diskmax, buffer_zero, state->block_size);
|
||||
raid_recov_1data(kind, failed[failed_map[0]].index, COMBO2[i].a, buffer, diskmax, buffer_zero, state->block_size);
|
||||
|
||||
if (is_parity_matching(state, diskmax, COMBO2[i].b, buffer, buffer_recov))
|
||||
return 0;
|
||||
|
|
@ -271,7 +272,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
memcpy(buffer[diskmax+COMBO2[i].b], buffer_recov[COMBO2[i].b], state->block_size);
|
||||
|
||||
/* recover data */
|
||||
raid_recov_2data(failed[failed_map[0]].index, failed[failed_map[1]].index, COMBO2[i].a, COMBO2[i].b, buffer, diskmax, buffer_zero, state->block_size);
|
||||
raid_recov_2data(kind, failed[failed_map[0]].index, failed[failed_map[1]].index, COMBO2[i].a, COMBO2[i].b, buffer, diskmax, buffer_zero, state->block_size);
|
||||
|
||||
if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero))
|
||||
return 0;
|
||||
|
|
@ -293,7 +294,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
memcpy(buffer[diskmax+COMBO3[i].b], buffer_recov[COMBO3[i].b], state->block_size);
|
||||
|
||||
/* recover data */
|
||||
raid_recov_2data(failed[failed_map[0]].index, failed[failed_map[1]].index, COMBO3[i].a, COMBO3[i].b, buffer, diskmax, buffer_zero, state->block_size);
|
||||
raid_recov_2data(kind, failed[failed_map[0]].index, failed[failed_map[1]].index, COMBO3[i].a, COMBO3[i].b, buffer, diskmax, buffer_zero, state->block_size);
|
||||
|
||||
if (is_parity_matching(state, diskmax, COMBO3[i].c, buffer, buffer_recov))
|
||||
return 0;
|
||||
|
|
@ -316,7 +317,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
memcpy(buffer[diskmax+COMBO3[i].c], buffer_recov[COMBO3[i].c], state->block_size);
|
||||
|
||||
/* recover data */
|
||||
raid_recov_3data(failed[failed_map[0]].index, failed[failed_map[1]].index, failed[failed_map[2]].index, COMBO3[i].a, COMBO3[i].b, COMBO3[i].c, buffer, diskmax, buffer_zero, state->block_size);
|
||||
raid_recov_3data(kind, failed[failed_map[0]].index, failed[failed_map[1]].index, failed[failed_map[2]].index, COMBO3[i].a, COMBO3[i].b, COMBO3[i].c, buffer, diskmax, buffer_zero, state->block_size);
|
||||
|
||||
if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero))
|
||||
return 0;
|
||||
|
|
@ -339,7 +340,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
memcpy(buffer[diskmax+COMBO4[i].c], buffer_recov[COMBO4[i].c], state->block_size);
|
||||
|
||||
/* recover data */
|
||||
raid_recov_3data(failed[failed_map[0]].index, failed[failed_map[1]].index, failed[failed_map[2]].index, COMBO4[i].a, COMBO4[i].b, COMBO4[i].c, buffer, diskmax, buffer_zero, state->block_size);
|
||||
raid_recov_3data(kind, failed[failed_map[0]].index, failed[failed_map[1]].index, failed[failed_map[2]].index, COMBO4[i].a, COMBO4[i].b, COMBO4[i].c, buffer, diskmax, buffer_zero, state->block_size);
|
||||
|
||||
if (is_parity_matching(state, diskmax, COMBO4[i].d, buffer, buffer_recov))
|
||||
return 0;
|
||||
|
|
@ -363,7 +364,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
memcpy(buffer[diskmax+COMBO4[i].d], buffer_recov[COMBO4[i].d], state->block_size);
|
||||
|
||||
/* recover data */
|
||||
raid_recov_4data(failed[failed_map[0]].index, failed[failed_map[1]].index, failed[failed_map[2]].index, failed[failed_map[3]].index, COMBO4[i].a, COMBO4[i].b, COMBO4[i].c, COMBO4[i].d, buffer, diskmax, buffer_zero, state->block_size);
|
||||
raid_recov_4data(kind, failed[failed_map[0]].index, failed[failed_map[1]].index, failed[failed_map[2]].index, failed[failed_map[3]].index, COMBO4[i].a, COMBO4[i].b, COMBO4[i].c, COMBO4[i].d, buffer, diskmax, buffer_zero, state->block_size);
|
||||
|
||||
if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero))
|
||||
return 0;
|
||||
|
|
@ -440,7 +441,7 @@ static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsign
|
|||
/* if nothing to fix */
|
||||
if (!something_to_recover) {
|
||||
/* recompute only parity and qarity */
|
||||
raid_gen(state->level, buffer, diskmax, state->block_size);
|
||||
raid_gen(RAID_POWER, state->level, buffer, diskmax, state->block_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ([2.65])
|
||||
AC_INIT([snapraid], [5.0], [], [], [http://snapraid.sourceforge.net])
|
||||
AC_INIT([snapraid], [6.0], [], [], [http://snapraid.sourceforge.net])
|
||||
AM_INIT_AUTOMAKE([foreign no-dependencies -Wall])
|
||||
AC_CONFIG_SRCDIR([snapraid.c])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
|
|
|
|||
252
mktables.c
252
mktables.c
|
|
@ -39,11 +39,114 @@ unsigned char gfmul(unsigned char a, unsigned char b)
|
|||
return v;
|
||||
}
|
||||
|
||||
unsigned char gfinv[256];
|
||||
|
||||
#define POWER_PARITY 4
|
||||
#define POWER_DISK 255
|
||||
|
||||
/**
|
||||
* Setup the power matrix used to generate parity.
|
||||
* The first row is formed by all 1.
|
||||
* The second row contains power of 2, the third power of 4, and so on...
|
||||
* Note that this matrix is valid only for up to Quad Parity and for up to 21 data disks.
|
||||
*/
|
||||
void set_power(unsigned char* matrix)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char g;
|
||||
|
||||
g = 1;
|
||||
for(i=0;i<POWER_PARITY;++i) {
|
||||
unsigned char v = 1;
|
||||
for(j=0;j<POWER_DISK;++j) {
|
||||
matrix[i*POWER_DISK+j] = v;
|
||||
v = gfmul(g, v);
|
||||
}
|
||||
g = gfmul(2, g);
|
||||
}
|
||||
}
|
||||
|
||||
#define CAUCHY_PARITY 6
|
||||
#define CAUCHY_DISK (256-(CAUCHY_PARITY-1))
|
||||
|
||||
/**
|
||||
* Setup the Extended Cauchy matrix used to generate parity.
|
||||
* The first row is formed by all 1.
|
||||
* The second row are power of 2, 2^0, 2^1, 2^2, ...
|
||||
* The others row are computed.
|
||||
*/
|
||||
void set_cauchy(unsigned char* matrix)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char cv, rv;
|
||||
|
||||
/* first row all 1, this is an Extended Cauchy matrix */
|
||||
for(i=0;i<CAUCHY_DISK;++i) {
|
||||
matrix[0*CAUCHY_DISK+i] = 1;
|
||||
}
|
||||
|
||||
/* second row power of 2, this is the first row of the Cauchy matrix */
|
||||
cv = 1;
|
||||
for(i=0;i<CAUCHY_DISK;++i) {
|
||||
matrix[1*CAUCHY_DISK+i] = cv;
|
||||
cv = gfmul(2, cv);
|
||||
}
|
||||
|
||||
/* other rows using a Cauchy matrix */
|
||||
rv = 2;
|
||||
for(j=0;j<CAUCHY_PARITY-2;++j) {
|
||||
unsigned char ce;
|
||||
|
||||
ce = 1;
|
||||
for(i=0;i<CAUCHY_DISK;++i) {
|
||||
cv = gfinv[ce];
|
||||
matrix[(j+2)*CAUCHY_DISK+i] = gfinv[rv ^ cv];
|
||||
ce = gfmul(2, ce);
|
||||
}
|
||||
|
||||
rv = gfmul(2, rv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Next power of 2.
|
||||
*/
|
||||
unsigned np(unsigned v)
|
||||
{
|
||||
--v;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
++v;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned char gfinv[256];
|
||||
unsigned char v;
|
||||
int i, j;
|
||||
int i, j, k, p;
|
||||
unsigned char matrix[8 * 256];
|
||||
|
||||
printf("/*\n");
|
||||
printf(" * Copyright (C) 2011 Andrea Mazzoleni\n");
|
||||
printf(" *\n");
|
||||
printf(" * This program is free software: you can redistribute it and/or modify\n");
|
||||
printf(" * it under the terms of the GNU General Public License as published by\n");
|
||||
printf(" * the Free Software Foundation, either version 2 of the License, or\n");
|
||||
printf(" * (at your option) any later version.\n");
|
||||
printf(" *\n");
|
||||
printf(" * This program is distributed in the hope that it will be useful,\n");
|
||||
printf(" * but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
|
||||
printf(" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
|
||||
printf(" * GNU General Public License for more details.\n");
|
||||
printf(" *\n");
|
||||
printf(" * You should have received a copy of the GNU General Public License\n");
|
||||
printf(" * along with this program. If not, see <http://www.gnu.org/licenses/>.\n");
|
||||
printf(" */\n");
|
||||
printf("\n");
|
||||
|
||||
/* a*b */
|
||||
printf("const unsigned char __attribute__((aligned(256))) gfmul[256][256] =\n");
|
||||
|
|
@ -98,22 +201,6 @@ int main(void)
|
|||
}
|
||||
printf("};\n\n");
|
||||
|
||||
/* 8^a */
|
||||
printf("const unsigned char __attribute__((aligned(256))) gfexp8[256] =\n");
|
||||
printf("{\n");
|
||||
v = 1;
|
||||
for(i=0;i<256;++i) {
|
||||
if (i % 8 == 0)
|
||||
printf("\t");
|
||||
printf("0x%02x,", v);
|
||||
v = gfmul(v, 8);
|
||||
if (i % 8 == 7)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
/* 1/a */
|
||||
printf("const unsigned char __attribute__((aligned(256))) gfinv[256] =\n");
|
||||
printf("{\n");
|
||||
|
|
@ -177,9 +264,136 @@ int main(void)
|
|||
printf("#define GFPOLY8 { 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d } \n");
|
||||
printf("#define GFPOLY16 { 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d } \n");
|
||||
printf("#define GFMASK16 { 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f } \n");
|
||||
|
||||
printf("\n");
|
||||
|
||||
/* power matrix */
|
||||
set_power(matrix);
|
||||
|
||||
printf("/**\n");
|
||||
printf(" * Power matrix used to generate parity.\n");
|
||||
printf(" * This matrix is valid for up to 4 parity with 21 data disks.\n");
|
||||
printf(" *\n");
|
||||
for(p=0;p<POWER_PARITY;++p) {
|
||||
printf(" * ");
|
||||
for(i=0;i<POWER_DISK;++i) {
|
||||
printf("%02x ", matrix[p*POWER_DISK+i]);
|
||||
if (p+1 == 4 && i+1 == 21) {
|
||||
/* stop at 4 parity and 21 data disks */
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf(" */\n");
|
||||
printf("const unsigned char __attribute__((aligned(256))) gfmatrix_power[%u][256] =\n", POWER_PARITY);
|
||||
printf("{\n");
|
||||
for(p=0;p<POWER_PARITY;++p) {
|
||||
printf("\t{\n");
|
||||
for(i=0;i<POWER_DISK;++i) {
|
||||
if (i % 8 == 0)
|
||||
printf("\t\t");
|
||||
printf("0x%02x,", matrix[p*POWER_DISK+i]);
|
||||
if (p+1 == 4 && i+1 == 21) {
|
||||
/* stop at 4 parity and 21 data disks */
|
||||
break;
|
||||
}
|
||||
if (i % 8 == 7)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n\t},\n");
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
/* matrix matrix */
|
||||
set_cauchy(matrix);
|
||||
|
||||
printf("/**\n");
|
||||
printf(" * Extended Cauchy matrix used to generate parity.\n");
|
||||
printf(" * This matrix is valid for up to %u parity with %u data disks.\n", CAUCHY_PARITY, CAUCHY_DISK);
|
||||
printf(" *\n");
|
||||
for(p=0;p<CAUCHY_PARITY;++p) {
|
||||
printf(" * ");
|
||||
for(i=0;i<CAUCHY_DISK;++i) {
|
||||
printf("%02x ", matrix[p*CAUCHY_DISK+i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf(" */\n");
|
||||
printf("const unsigned char __attribute__((aligned(256))) gfmatrix_cauchy[%u][256] =\n", CAUCHY_PARITY);
|
||||
printf("{\n");
|
||||
for(p=0;p<CAUCHY_PARITY;++p) {
|
||||
printf("\t{\n");
|
||||
for(i=0;i<CAUCHY_DISK;++i) {
|
||||
if (i % 8 == 0)
|
||||
printf("\t\t");
|
||||
printf("0x%02x,", matrix[p*CAUCHY_DISK+i]);
|
||||
if (i % 8 == 7)
|
||||
printf("\n");
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n\t},\n");
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
printf("/**\n");
|
||||
printf(" * Multiplication tables for the Extended Cauchy matrix.\n");
|
||||
printf(" *\n");
|
||||
printf(" * Indexes are [DISK][DATA][PARITY - 1].\n");
|
||||
printf(" * Where DISK is from 0 to %u, DATA from 0 to 255, PARITY from 1 to %u.\n", CAUCHY_DISK - 1, CAUCHY_PARITY - 1);
|
||||
printf(" */\n");
|
||||
printf("const unsigned char __attribute__((aligned(256))) gfcauchy_mul[%u][256][%u] =\n", CAUCHY_DISK, np(CAUCHY_PARITY - 1));
|
||||
printf("{\n");
|
||||
for(i=0;i<CAUCHY_DISK;++i) {
|
||||
printf("\t{\n");
|
||||
for(j=0;j<256;++j) {
|
||||
printf("\t\t{ ");
|
||||
for(p=1;p<CAUCHY_PARITY;++p) {
|
||||
v = gfmul(matrix[p*CAUCHY_DISK+i], j);
|
||||
printf("0x%02x", (unsigned)v);
|
||||
if (p != CAUCHY_PARITY - 1)
|
||||
printf(", ");
|
||||
}
|
||||
printf(" },\n");
|
||||
}
|
||||
printf("\t},\n");
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
printf("#if defined(__i386__) || defined(__x86_64__)\n");
|
||||
printf("/**\n");
|
||||
printf(" * PSHUFB tables for the Extended Cauchy matrix.\n");
|
||||
printf(" *\n");
|
||||
printf(" * Indexes are [DISK][DATA][PARITY - 2].\n");
|
||||
printf(" * Where DISK is from 0 to %u, DATA from 0 to 255, PARITY from 2 to %u.\n", CAUCHY_DISK - 1, CAUCHY_PARITY - 1);
|
||||
printf(" */\n");
|
||||
printf("const unsigned char __attribute__((aligned(256))) gfcauchy_pshufb[%u][%u][2][16] =\n", CAUCHY_DISK, np(CAUCHY_PARITY - 2));
|
||||
printf("{\n");
|
||||
for(i=0;i<CAUCHY_DISK;++i) {
|
||||
printf("\t{\n");
|
||||
for(p=2;p<CAUCHY_PARITY;++p) {
|
||||
printf("\t\t{\n");
|
||||
for(j=0;j<2;++j) {
|
||||
printf("\t\t\t{ ");
|
||||
for(k=0;k<16;++k) {
|
||||
v = gfmul(matrix[p*CAUCHY_DISK+i], k);
|
||||
if (j == 1)
|
||||
v = gfmul(v, 16);
|
||||
printf("0x%02x", (unsigned)v);
|
||||
if (k != 15)
|
||||
printf(", ");
|
||||
}
|
||||
printf(" },\n");
|
||||
}
|
||||
printf("\t\t},\n");
|
||||
}
|
||||
printf("\t},\n");
|
||||
}
|
||||
printf("};\n");
|
||||
printf("#endif\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
42
raid.h
42
raid.h
|
|
@ -22,14 +22,25 @@
|
|||
/* raid */
|
||||
|
||||
/**
|
||||
* Max number of data disks for RAID6.
|
||||
* Kind of generator matrix used.
|
||||
*/
|
||||
#define RAID6_DATA_LIMIT 255
|
||||
#define RAID_POWER 0 /**< Power matrix. Fast but no more than 4 parity with 21 data disks */
|
||||
#define RAID_CAUCHY 1 /**< Cauchy matrix. Slower, but no limit. */
|
||||
|
||||
/**
|
||||
* Max number of data disks for RAIDQP.
|
||||
* Max number of data disks for RAID_POWER for up to TripleParity.
|
||||
*/
|
||||
#define RAIDQP_DATA_LIMIT 21
|
||||
#define RAID_POWER_DATA_LIMIT 255
|
||||
|
||||
/**
|
||||
* Max number of data disks for RAID_POWER with QuadParity.
|
||||
*/
|
||||
#define RAID_POWER_QP_DATA_LIMIT 21
|
||||
|
||||
/**
|
||||
* Max number of data disks with RAID_CAUCHY.
|
||||
*/
|
||||
#define RAID_CAUCHY_DATA_LIMIT 251
|
||||
|
||||
/**
|
||||
* Initializes the RAID system.
|
||||
|
|
@ -38,13 +49,14 @@ void raid_init(void);
|
|||
|
||||
/**
|
||||
* Computes the specified number of parities.
|
||||
* \param kind Kind of parity. RAID_POWER or RAID_CAUCHY.
|
||||
* \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.
|
||||
* \param data Number of data disks.
|
||||
* \param size Size of the blocks pointed by vbuf.
|
||||
*/
|
||||
void raid_gen(unsigned level, unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void raid_gen(unsigned kind, unsigned level, unsigned char** vbuf, unsigned data, unsigned size);
|
||||
|
||||
/*
|
||||
* Recovers failure of one data block x using parity i.
|
||||
|
|
@ -58,25 +70,25 @@ void raid_gen(unsigned level, unsigned char** vbuf, unsigned data, unsigned size
|
|||
* This buffer is not modified.
|
||||
* \param size Size of the blocks pointed by vbuf.
|
||||
*/
|
||||
void raid_recov_1data(int x, int i, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recov_1data(unsigned kind, int x, int i, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
|
||||
/*
|
||||
* Recovers failure of two data blocks x,y using parity i,j.
|
||||
* Note that only the data blocks are recovered. The full parity is instead destroyed.
|
||||
*/
|
||||
void raid_recov_2data(int x, int y, int i, int j, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recov_2data(unsigned kind, int x, int y, int i, int j, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
|
||||
/*
|
||||
* Recovers failure of three data blocks x,y,z using parity i,j,k.
|
||||
* Note that only the data blocks are recovered. The full parity is instead destroyed.
|
||||
*/
|
||||
void raid_recov_3data(int x, int y, int z, int i, int j, int k, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recov_3data(unsigned kind, int x, int y, int z, int i, int j, int k, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
|
||||
/*
|
||||
* Recovers failure of four data blocks x,y,z,v using parity i,j,k,l.
|
||||
* Note that only the data blocks are recovered. The full parity is instead destroyed.
|
||||
*/
|
||||
void raid_recov_4data(int x, int y, int z, int v, int i, int j, int k, int l, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
void raid_recov_4data(unsigned kind, int x, int y, int z, int v, int i, int j, int k, int l, unsigned char** vbuf, unsigned data, unsigned char* zero, unsigned size);
|
||||
|
||||
/**
|
||||
* Gets the name of the selected function to compute parity.
|
||||
|
|
@ -85,6 +97,9 @@ const char* raid5_tag(void);
|
|||
const char* raid6_tag(void);
|
||||
const char* raidTP_tag(void);
|
||||
const char* raidQP_tag(void);
|
||||
const char* cauchyQP_tag(void);
|
||||
const char* cauchyPP_tag(void);
|
||||
const char* cauchyHP_tag(void);
|
||||
|
||||
/**
|
||||
* Internal specialized parity computation.
|
||||
|
|
@ -114,6 +129,15 @@ void raidQP_sse2ext(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 raidQP_avxext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void cauchyQP_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void cauchyQP_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void cauchyQP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void cauchyPP_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void cauchyPP_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void cauchyPP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void cauchyHP_int8(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void cauchyHP_ssse3(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
void cauchyHP_ssse3ext(unsigned char** vbuf, unsigned data, unsigned size);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
2
scrub.c
2
scrub.c
|
|
@ -315,7 +315,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
|||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(state->level, buffer, diskmax, state->block_size);
|
||||
raid_gen(RAID_POWER, state->level, buffer, diskmax, state->block_size);
|
||||
|
||||
/* compare the parity */
|
||||
for(l=0;l<state->level;++l) {
|
||||
|
|
|
|||
140
selftest.c
140
selftest.c
|
|
@ -46,7 +46,7 @@ static struct hash_test_vector TEST_SPOOKY2[] = {
|
|||
{ 0, 0, { 0 } }
|
||||
};
|
||||
|
||||
static void recovtest(unsigned diskmax, unsigned block_size)
|
||||
static void recovtest(unsigned kind, unsigned diskmax, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
unsigned char** buffer;
|
||||
|
|
@ -57,6 +57,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
unsigned char* buffer_zero;
|
||||
unsigned char* buffer_bad;
|
||||
unsigned buffermax;
|
||||
unsigned level;
|
||||
unsigned i, j, k, l;
|
||||
unsigned n;
|
||||
|
||||
|
|
@ -92,7 +93,13 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
{ 3, { 0, 1, 2 } }
|
||||
};
|
||||
|
||||
buffermax = diskmax + LEV_MAX * 2 + 1 + 1;
|
||||
if (kind == RAID_POWER) {
|
||||
level = 4;
|
||||
} else {
|
||||
level = 4; /* TODO preliminary support limited to 4 parity */
|
||||
}
|
||||
|
||||
buffermax = diskmax + level * 2 + 1 + 1;
|
||||
|
||||
buffer = malloc_nofail_vector_align(buffermax, block_size, &buffer_alloc);
|
||||
|
||||
|
|
@ -112,7 +119,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(LEV_MAX, buffer, diskmax, block_size);
|
||||
raid_gen(kind, level, buffer, diskmax, block_size);
|
||||
|
||||
/* check 4data */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
|
|
@ -124,6 +131,10 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
unsigned char* c;
|
||||
unsigned char* d;
|
||||
|
||||
/* enforce the limit */
|
||||
if (kind == RAID_POWER && diskmax > RAID_POWER_QP_DATA_LIMIT && l >= 3)
|
||||
continue;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
b = buffer[j];
|
||||
|
|
@ -137,7 +148,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
buffer[l] = buffer_test3;
|
||||
|
||||
/* recover */
|
||||
raid_recov_4data(i, j, k, l, 0, 1, 2, 3, buffer, diskmax, buffer_zero, block_size);
|
||||
raid_recov_4data(kind, i, j, k, l, 0, 1, 2, 3, buffer, diskmax, buffer_zero, block_size);
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, a, block_size) != 0
|
||||
|
|
@ -169,8 +180,9 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
unsigned char* c;
|
||||
unsigned char* p;
|
||||
|
||||
/* this is the point where quad parity fails over RAIDQP_DATA_LIMIT data disks */
|
||||
if (diskmax > RAIDQP_DATA_LIMIT && COMBO3[n].use[2] >= 3)
|
||||
/* enforce the limit */
|
||||
/* this is the point where quad parity fails over RAID_POWER_QP_DATA_LIMIT data disks */
|
||||
if (kind == RAID_POWER && diskmax > RAID_POWER_QP_DATA_LIMIT && COMBO3[n].use[2] >= 3)
|
||||
continue;
|
||||
|
||||
/* save */
|
||||
|
|
@ -189,7 +201,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
buffer[l] = buffer_bad;
|
||||
|
||||
/* recover ignoring p */
|
||||
raid_recov_3data(i, j, k, COMBO3[n].use[0], COMBO3[n].use[1], COMBO3[n].use[2], buffer, diskmax, buffer_zero, block_size);
|
||||
raid_recov_3data(kind, i, j, k, COMBO3[n].use[0], COMBO3[n].use[1], COMBO3[n].use[2], buffer, diskmax, buffer_zero, block_size);
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, a, block_size) != 0
|
||||
|
|
@ -221,6 +233,10 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
||||
/* enforce the limit */
|
||||
if (kind == RAID_POWER && diskmax > RAID_POWER_QP_DATA_LIMIT && COMBO2[n].use[1] >= 3)
|
||||
continue;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
b = buffer[j];
|
||||
|
|
@ -238,7 +254,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
buffer[l] = buffer_bad;
|
||||
|
||||
/* recover */
|
||||
raid_recov_2data(i, j, COMBO2[n].use[0], COMBO2[n].use[1], buffer, diskmax, buffer_zero, block_size);
|
||||
raid_recov_2data(kind, i, j, COMBO2[n].use[0], COMBO2[n].use[1], buffer, diskmax, buffer_zero, block_size);
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, a, block_size) != 0
|
||||
|
|
@ -267,6 +283,10 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
unsigned char* q;
|
||||
unsigned char* r;
|
||||
|
||||
/* enforce the limit */
|
||||
if (kind == RAID_POWER && diskmax > RAID_POWER_QP_DATA_LIMIT && COMBO1[n].use >= 3)
|
||||
continue;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
|
||||
|
|
@ -285,7 +305,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
buffer[l] = buffer_bad;
|
||||
|
||||
/* recover */
|
||||
raid_recov_1data(i, COMBO1[n].use, buffer, diskmax, buffer_zero, block_size);
|
||||
raid_recov_1data(kind, i, COMBO1[n].use, buffer, diskmax, buffer_zero, block_size);
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, a, block_size) != 0) {
|
||||
|
|
@ -307,7 +327,7 @@ static void recovtest(unsigned diskmax, unsigned block_size)
|
|||
free(buffer);
|
||||
}
|
||||
|
||||
static void gentest(unsigned diskmax, unsigned block_size)
|
||||
static void gentest(unsigned kind, unsigned diskmax, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
unsigned char** buffer;
|
||||
|
|
@ -315,8 +335,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;
|
||||
if (kind == RAID_POWER) {
|
||||
level = 4;
|
||||
} else {
|
||||
level = LEV_MAX;
|
||||
}
|
||||
|
||||
buffermax = diskmax + level * 2;
|
||||
|
||||
buffer = malloc_nofail_vector_align(buffermax, block_size, &buffer_alloc);
|
||||
|
||||
|
|
@ -327,55 +354,82 @@ static void gentest(unsigned diskmax, unsigned block_size)
|
|||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(LEV_MAX, buffer, diskmax, block_size);
|
||||
raid_gen(kind, 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++] = raid5_int32;
|
||||
map[mac++] = raid5_int64;
|
||||
map[mac++] = raid6_int32;
|
||||
map[mac++] = raid6_int64;
|
||||
map[mac++] = raidTP_int32;
|
||||
map[mac++] = raidTP_int64;
|
||||
map[mac++] = raidQP_int32;
|
||||
map[mac++] = raidQP_int64;
|
||||
if (kind == RAID_CAUCHY) {
|
||||
map[mac++] = cauchyQP_int8;
|
||||
map[mac++] = cauchyPP_int8;
|
||||
map[mac++] = cauchyHP_int8;
|
||||
}
|
||||
if (kind == RAID_POWER) {
|
||||
map[mac++] = raid5_int32;
|
||||
map[mac++] = raid5_int64;
|
||||
map[mac++] = raid6_int32;
|
||||
map[mac++] = raid6_int64;
|
||||
map[mac++] = raidTP_int32;
|
||||
map[mac++] = raidTP_int64;
|
||||
map[mac++] = raidQP_int32;
|
||||
map[mac++] = raidQP_int64;
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_mmx()) {
|
||||
map[mac++] = raid5_mmx;
|
||||
map[mac++] = raid6_mmx;
|
||||
map[mac++] = raidQP_mmx;
|
||||
map[mac++] = raidTP_mmx;
|
||||
if (kind == RAID_POWER) {
|
||||
map[mac++] = raid5_mmx;
|
||||
map[mac++] = raid6_mmx;
|
||||
map[mac++] = raidQP_mmx;
|
||||
map[mac++] = raidTP_mmx;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu_has_sse2()) {
|
||||
map[mac++] = raid5_sse2;
|
||||
map[mac++] = raid6_sse2;
|
||||
map[mac++] = raidTP_sse2;
|
||||
map[mac++] = raidQP_sse2;
|
||||
if (kind == RAID_POWER) {
|
||||
map[mac++] = raid5_sse2;
|
||||
map[mac++] = raid6_sse2;
|
||||
map[mac++] = raidTP_sse2;
|
||||
map[mac++] = raidQP_sse2;
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raid6_sse2ext;
|
||||
map[mac++] = raidTP_sse2ext;
|
||||
map[mac++] = raidQP_sse2ext;
|
||||
map[mac++] = raid6_sse2ext;
|
||||
map[mac++] = raidTP_sse2ext;
|
||||
map[mac++] = raidQP_sse2ext;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu_has_ssse3()) {
|
||||
map[mac++] = raidTP_ssse3;
|
||||
map[mac++] = raidQP_ssse3;
|
||||
if (kind == RAID_POWER) {
|
||||
map[mac++] = raidTP_ssse3;
|
||||
map[mac++] = raidQP_ssse3;
|
||||
}
|
||||
if (kind == RAID_CAUCHY) {
|
||||
map[mac++] = cauchyQP_ssse3;
|
||||
map[mac++] = cauchyPP_ssse3;
|
||||
map[mac++] = cauchyHP_ssse3;
|
||||
}
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raidTP_ssse3ext;
|
||||
map[mac++] = raidQP_ssse3ext;
|
||||
if (kind == RAID_POWER) {
|
||||
map[mac++] = raidTP_ssse3ext;
|
||||
map[mac++] = raidQP_ssse3ext;
|
||||
}
|
||||
if (kind == RAID_CAUCHY) {
|
||||
map[mac++] = cauchyQP_ssse3ext;
|
||||
map[mac++] = cauchyPP_ssse3ext;
|
||||
map[mac++] = cauchyHP_ssse3ext;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (cpu_has_avx()) {
|
||||
#if defined(__x86_64__)
|
||||
map[mac++] = raidQP_avxext;
|
||||
if (kind == RAID_POWER) {
|
||||
map[mac++] = raidQP_avxext;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
@ -386,8 +440,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 RAID test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -511,7 +565,9 @@ void selftest()
|
|||
|
||||
hashtest();
|
||||
crc32ctest();
|
||||
gentest(24, 256 * 1024);
|
||||
recovtest(24, 2048);
|
||||
gentest(RAID_POWER, 24, 256 * 1024);
|
||||
gentest(RAID_CAUCHY, 32, 256 * 1024);
|
||||
recovtest(RAID_POWER, 24, 2048);
|
||||
recovtest(RAID_CAUCHY, 32, 2048);
|
||||
}
|
||||
|
||||
|
|
|
|||
169
speed.c
169
speed.c
|
|
@ -21,6 +21,7 @@
|
|||
#include "util.h"
|
||||
#include "raid.h"
|
||||
#include "cpu.h"
|
||||
#include "state.h"
|
||||
|
||||
/**
|
||||
* Differential us of two timeval.
|
||||
|
|
@ -66,7 +67,7 @@ void speed(void)
|
|||
void* buffer_alloc;
|
||||
unsigned char** buffer;
|
||||
|
||||
buffer = malloc_nofail_vector_align(diskmax + 4, block_size, &buffer_alloc);
|
||||
buffer = malloc_nofail_vector_align(diskmax + LEV_MAX, block_size, &buffer_alloc);
|
||||
|
||||
/* initialize with fixed data */
|
||||
for(i=0;i<diskmax+4;++i) {
|
||||
|
|
@ -134,10 +135,10 @@ void speed(void)
|
|||
#endif
|
||||
printf("\n");
|
||||
|
||||
printf("Expected fastest raid5 is %s\n", raid5_tag());
|
||||
printf("Expected fastest raid6 is %s\n", raid6_tag());
|
||||
printf("Expected fastest raidTP is %s\n", raidTP_tag());
|
||||
printf("Expected fastest raidQP is %s\n", raidQP_tag());
|
||||
printf("Expected fastest power5 is %s\n", raid5_tag());
|
||||
printf("Expected fastest power6 is %s\n", raid6_tag());
|
||||
printf("Expected fastest powerTP is %s\n", raidTP_tag());
|
||||
printf("Expected fastest powerQP is %s\n", raidQP_tag());
|
||||
|
||||
printf("If these expectations are false, please report it in the SnapRAID forum\n");
|
||||
|
||||
|
|
@ -223,6 +224,7 @@ void speed(void)
|
|||
/* RAID table */
|
||||
printf("RAID functions used to compute the parity:\n");
|
||||
printf("%10s", "");
|
||||
printf(" %6s", "int8");
|
||||
printf(" %6s", "int32");
|
||||
printf(" %6s", "int64");
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
|
@ -240,9 +242,11 @@ void speed(void)
|
|||
printf("\n");
|
||||
|
||||
/* RAID5 */
|
||||
printf("%10s", "raid5");
|
||||
printf("%10s", "power5");
|
||||
fflush(stdout);
|
||||
|
||||
printf(" %6s", "");
|
||||
|
||||
SPEED_START {
|
||||
raid5_int32(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
|
@ -279,9 +283,11 @@ void speed(void)
|
|||
printf("\n");
|
||||
|
||||
/* RAID6 */
|
||||
printf("%10s", "raid6");
|
||||
printf("%10s", "power6");
|
||||
fflush(stdout);
|
||||
|
||||
printf(" %6s", "");
|
||||
|
||||
SPEED_START {
|
||||
raid6_int32(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
|
@ -327,9 +333,11 @@ void speed(void)
|
|||
printf("\n");
|
||||
|
||||
/* RAIDTP */
|
||||
printf("%10s", "raidTP");
|
||||
printf("%10s", "powerTP");
|
||||
fflush(stdout);
|
||||
|
||||
printf(" %6s", "");
|
||||
|
||||
SPEED_START {
|
||||
raidTP_int32(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
|
@ -393,9 +401,11 @@ void speed(void)
|
|||
printf("\n");
|
||||
|
||||
/* RAIDQP */
|
||||
printf("%10s", "raidQP");
|
||||
printf("%10s", "powerQP");
|
||||
fflush(stdout);
|
||||
|
||||
printf(" %6s", "");
|
||||
|
||||
SPEED_START {
|
||||
raidQP_int32(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
|
@ -468,6 +478,147 @@ void speed(void)
|
|||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
/* CAUCHYQP */
|
||||
printf("%10s", "cauchyQP");
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
cauchyQP_int8(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf(" %6"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
printf(" %6s", "");
|
||||
printf(" %6s", "");
|
||||
|
||||
if (cpu_has_mmx()) {
|
||||
printf(" %6s", "");
|
||||
}
|
||||
|
||||
if (cpu_has_sse2()) {
|
||||
printf(" %6s", "");
|
||||
|
||||
#if defined(__x86_64__)
|
||||
printf(" %6s", "");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
cauchyQP_ssse3(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf(" %6"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
cauchyQP_ssse3ext(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf(" %6"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
/* CAUCHYPP */
|
||||
printf("%10s", "cauchyPP");
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
cauchyPP_int8(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf(" %6"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
printf(" %6s", "");
|
||||
printf(" %6s", "");
|
||||
|
||||
if (cpu_has_mmx()) {
|
||||
printf(" %6s", "");
|
||||
}
|
||||
|
||||
if (cpu_has_sse2()) {
|
||||
printf(" %6s", "");
|
||||
|
||||
#if defined(__x86_64__)
|
||||
printf(" %6s", "");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
cauchyPP_ssse3(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf(" %6"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
cauchyPP_ssse3ext(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf(" %6"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
|
||||
/* CAUCHYHP */
|
||||
printf("%10s", "cauchyHP");
|
||||
fflush(stdout);
|
||||
|
||||
SPEED_START {
|
||||
cauchyHP_int8(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf(" %6"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
printf(" %6s", "");
|
||||
printf(" %6s", "");
|
||||
|
||||
if (cpu_has_mmx()) {
|
||||
printf(" %6s", "");
|
||||
}
|
||||
|
||||
if (cpu_has_sse2()) {
|
||||
printf(" %6s", "");
|
||||
|
||||
#if defined(__x86_64__)
|
||||
printf(" %6s", "");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (cpu_has_ssse3()) {
|
||||
SPEED_START {
|
||||
cauchyHP_ssse3(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf(" %6"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
|
||||
#if defined(__x86_64__)
|
||||
SPEED_START {
|
||||
cauchyHP_ssse3ext(buffer, diskmax, block_size);
|
||||
} SPEED_STOP
|
||||
|
||||
printf(" %6"PRIu64, ds / dt);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
|
||||
free(buffer_alloc);
|
||||
|
|
|
|||
12
state.c
12
state.c
|
|
@ -32,6 +32,8 @@ const char* lev_name(unsigned l)
|
|||
case 1 : return "Q-Parity";
|
||||
case 2 : return "R-Parity";
|
||||
case 3 : return "S-Parity";
|
||||
case 4 : return "T-Parity";
|
||||
case 5 : return "U-Parity";
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -44,6 +46,8 @@ const char* lev_config_name(unsigned l)
|
|||
case 1 : return "q-parity";
|
||||
case 2 : return "r-parity";
|
||||
case 3 : return "s-parity";
|
||||
case 4 : return "t-parity";
|
||||
case 5 : return "u-parity";
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -179,14 +183,14 @@ static void state_config_check(struct snapraid_state* state, const char* path)
|
|||
++diskcount;
|
||||
}
|
||||
|
||||
if (state->level >= 2 && diskcount > RAID6_DATA_LIMIT) {
|
||||
if (state->level >= 2 && diskcount > RAID_POWER_DATA_LIMIT) {
|
||||
/* RAID6 parity works for up to 255 drives, no more */
|
||||
fprintf(stderr, "Too many disks for RAID6. No more than %u.\n", RAID6_DATA_LIMIT);
|
||||
fprintf(stderr, "Too many disks for RAID6. No more than %u.\n", RAID_POWER_DATA_LIMIT);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (state->level >= 4 && diskcount > RAIDQP_DATA_LIMIT) {
|
||||
if (state->level >= 4 && diskcount > RAID_POWER_QP_DATA_LIMIT) {
|
||||
/* RAIDQP parity works for up to 21 drives, no more */
|
||||
fprintf(stderr, "Too many disks for RAIDQP. No more than %u.\n", RAIDQP_DATA_LIMIT);
|
||||
fprintf(stderr, "Too many disks for RAIDQP. No more than %u.\n", RAID_POWER_QP_DATA_LIMIT);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
|||
4
state.h
4
state.h
|
|
@ -18,13 +18,15 @@
|
|||
#ifndef __STATE_H
|
||||
#define __STATE_H
|
||||
|
||||
#include "elem.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* parity level */
|
||||
|
||||
/**
|
||||
* Max level of parity supported.
|
||||
*/
|
||||
#define LEV_MAX 4
|
||||
#define LEV_MAX 6
|
||||
|
||||
/**
|
||||
* Returns the parity name: Parity, Q-Parity, R-Parity, S-Parity.
|
||||
|
|
|
|||
2
sync.c
2
sync.c
|
|
@ -374,7 +374,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* updates the parity only if really needed */
|
||||
if (parity_needs_to_be_updated) {
|
||||
/* compute the parity */
|
||||
raid_gen(state->level, buffer, diskmax, state->block_size);
|
||||
raid_gen(RAID_POWER, state->level, buffer, diskmax, state->block_size);
|
||||
|
||||
/* write the parity */
|
||||
for(l=0;l<state->level;++l) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue