mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Removes the specific recovering functions.
We now always use the generic ones.
This commit is contained in:
parent
9af05bce98
commit
f4c1e288b2
3 changed files with 122 additions and 551 deletions
261
raid.c
261
raid.c
|
|
@ -1232,8 +1232,8 @@ void raid_gen(unsigned level, unsigned char** buffer, unsigned diskmax, unsigned
|
|||
* This method is also the same used by ZFS to implement its RAIDTP
|
||||
* support.
|
||||
*
|
||||
* Note that the same extension is not possible for Quad Parity because
|
||||
* in the approach used in the paper we don't have the guarantee to always have
|
||||
* To support RAIDQP (Quad Parity) we go futher using also the parity generator "8".
|
||||
* Note that in this case we don't have the guarantee to always have
|
||||
* a system of independent linear equations, and for Quad Parity in some cases
|
||||
* the system is not solvable.
|
||||
*
|
||||
|
|
@ -1258,18 +1258,18 @@ void raid_gen(unsigned level, unsigned char** buffer, unsigned diskmax, unsigned
|
|||
* Q = sum(2^i * Di) 0<=i<n
|
||||
* R = sum(4^i * Di) 0<=i<n
|
||||
*
|
||||
* To recover from a failure of three disks at indes x,y,z,
|
||||
* To recover from a failure of three disks at indexes x,y,z,
|
||||
* with 0<=x<y<z<n, we compute the syndromes of the available disks:
|
||||
*
|
||||
* Pxyz = sum(Di) 0<=i<n,i!=x,i!=y,i!=z
|
||||
* Qxyz = sum(2^i * Di) 0<=i<n,i!=x,i!=y,i!=z
|
||||
* Rxyz = sum(4^i * Di) 0<=i<n,i!=x,i!=y,i!=z
|
||||
* Pa = sum(Di) 0<=i<n,i!=x,i!=y,i!=z
|
||||
* Qa = sum(2^i * Di) 0<=i<n,i!=x,i!=y,i!=z
|
||||
* Ra = sum(4^i * Di) 0<=i<n,i!=x,i!=y,i!=z
|
||||
*
|
||||
* and if we define:
|
||||
*
|
||||
* Pd = Pxyz + P
|
||||
* Qd = Qxyz + Q
|
||||
* Rd = Rxyz + R
|
||||
* Pd = Pa + P
|
||||
* Qd = Qa + Q
|
||||
* Rd = Ra + R
|
||||
*
|
||||
* we can sum these two set equations, obtaining:
|
||||
*
|
||||
|
|
@ -1277,27 +1277,31 @@ void raid_gen(unsigned level, unsigned char** buffer, unsigned diskmax, unsigned
|
|||
* Qd = 2^x * Dx + 2^y * Dy + 2^z * Dz
|
||||
* Rd = 4^x * Dx + 4^y * Dy + 4^z * Dz
|
||||
*
|
||||
* A linear system of three equations solvable by substitution on Dx, Dy and Dz,
|
||||
* because all the others variables are known and the equations are independent
|
||||
* for any 0<=x<y<z<255.
|
||||
* We can prove that the equations are independent by brute-force, trying all the
|
||||
* possible combinations of x,y,z.
|
||||
* A linear system always solvable because the coefficients matrix is always
|
||||
* not singular, including all its submatrix.
|
||||
* We can prove that by brute-force, trying all the possible combinations
|
||||
* of x,y,z with 0<=x<y<z<255.
|
||||
*
|
||||
* The other recovering cases are a simplification of the general one,
|
||||
* with some equations or addends removed.
|
||||
*
|
||||
* We have in total 7 different recovering strategies:
|
||||
* For Quad Parity we follow the same method starting with:
|
||||
*
|
||||
* RAID5 - Dx recovered with P
|
||||
* RAID6 - Dx recovered with Q
|
||||
* RAID6 - Dx and Dy recovered with P,Q
|
||||
* RAIDTP - Dx recovered with R
|
||||
* RAIDTP - Dx,Dy recovered with P,R
|
||||
* RAIDTP - Dx,Dy recovered with Q,R
|
||||
* RAIDTP - Dx,Dy,Dz recovered with P,Q,R
|
||||
* P = sum(Di) 0<=i<n
|
||||
* Q = sum(2^i * Di) 0<=i<n
|
||||
* R = sum(4^i * Di) 0<=i<n
|
||||
* S = sum(8^i * Di) 0<=i<n
|
||||
*
|
||||
* each one implemented in a different function using linear system
|
||||
* of equations with a different solution.
|
||||
* obtaining:
|
||||
*
|
||||
* Pd = Dx + Dy + Dz + Dv
|
||||
* Qd = 2^x * Dx + 2^y * Dy + 2^z * Dz + 2^v * Dv
|
||||
* Rd = 4^x * Dx + 4^y * Dy + 4^z * Dz + 4^v * Dv
|
||||
* Sd = 8^x * Dx + 8^y * Dy + 8^z * Dz + 8^v * Dv
|
||||
*
|
||||
* In this case the coefficients matrix and all its submatrix are not singular
|
||||
* only with up to 21 data disk (0<=x<y<z<v<21 with GF primitive poly 285).
|
||||
* Note that the cases failing with 22 data disk are some matrix 3x3.
|
||||
*
|
||||
* References:
|
||||
* [1] Anvin, "The mathematics of RAID-6", 2004
|
||||
|
|
@ -1390,7 +1394,9 @@ static inline const unsigned char* table(unsigned char a)
|
|||
return gfmul[a];
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Recover failure of one data block for RAID5.
|
||||
*
|
||||
* Starting from the equation:
|
||||
*
|
||||
* Pd = Dx
|
||||
|
|
@ -1399,7 +1405,7 @@ static inline const unsigned char* table(unsigned char a)
|
|||
*
|
||||
* Dx = Pd (this one is easy :D)
|
||||
*/
|
||||
void raid5_recov_data(unsigned char** dptrs, unsigned diskmax, unsigned size, int x)
|
||||
static void raid5_recov_data(unsigned char** dptrs, unsigned diskmax, unsigned size, int x)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* dp;
|
||||
|
|
@ -1418,7 +1424,9 @@ void raid5_recov_data(unsigned char** dptrs, unsigned diskmax, unsigned size, in
|
|||
dptrs[diskmax] = p;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Recover failure of two data blocks for RAID6.
|
||||
*
|
||||
* Starting from the equations:
|
||||
*
|
||||
* Pd = Dx + Dy
|
||||
|
|
@ -1439,7 +1447,7 @@ void raid5_recov_data(unsigned char** dptrs, unsigned diskmax, unsigned size, in
|
|||
*
|
||||
* That are always satisfied for any 0<=x<y<255.
|
||||
*/
|
||||
void raid6_recov_2data(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, int y, unsigned char* zero)
|
||||
static void raid6_recov_2data(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, int y, unsigned char* zero)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* dp;
|
||||
|
|
@ -1498,120 +1506,9 @@ void raid6_recov_2data(unsigned char** dptrs, unsigned diskmax, unsigned size, i
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting from the equations:
|
||||
/**
|
||||
* Recover failure of two data blocks without Q for RAIDTP.
|
||||
*
|
||||
* Qd = 2^x * Dx
|
||||
*
|
||||
* and solving we get:
|
||||
*
|
||||
* Dx = 2^(-x) * Qd
|
||||
*
|
||||
* with conditions:
|
||||
*
|
||||
* 2^x != 0
|
||||
*
|
||||
* That are always satisfied for any 0<=x<y<255.
|
||||
*/
|
||||
void raid6_recov_datap(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, unsigned char* zero)
|
||||
{
|
||||
unsigned char* q;
|
||||
unsigned char* dq;
|
||||
const unsigned char* qxmul; /* Q multiplier to compute Dx */
|
||||
|
||||
q = dptrs[diskmax+1];
|
||||
|
||||
/* compute syndrome with zero for the missing data page */
|
||||
/* use the dead data page as temporary storage for delta q */
|
||||
dq = dptrs[x];
|
||||
dptrs[x] = zero;
|
||||
dptrs[diskmax+1] = dq;
|
||||
|
||||
raid6_gen(dptrs, diskmax, size);
|
||||
|
||||
/* restore pointers */
|
||||
dptrs[x] = dq;
|
||||
dptrs[diskmax+1] = q;
|
||||
|
||||
/* select tables */
|
||||
qxmul = table( inv(pow2(x)) );
|
||||
|
||||
while (size--) {
|
||||
/* delta */
|
||||
unsigned char Qd = *q ^ *dq;
|
||||
|
||||
/* addends to reconstruct Dx */
|
||||
unsigned char qam = qxmul[Qd];
|
||||
|
||||
/* reconstruct Dx */
|
||||
unsigned char Dx = qam;
|
||||
|
||||
/* set */
|
||||
*dq = Dx;
|
||||
|
||||
++q;
|
||||
++dq;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting from the equation:
|
||||
*
|
||||
* Rd = 4^x * Dx
|
||||
*
|
||||
* and solving we get:
|
||||
*
|
||||
* Dx = 4^(-x) * Rd
|
||||
*
|
||||
* with conditions:
|
||||
*
|
||||
* 4^x != 0
|
||||
*
|
||||
* That are always satisfied for any 0<=x<y<255.
|
||||
*
|
||||
*/
|
||||
void raidTP_recov_datapq(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, unsigned char* zero)
|
||||
{
|
||||
unsigned char* r;
|
||||
unsigned char* dr;
|
||||
const unsigned char* rxmul; /* R multiplier to compute Dx */
|
||||
|
||||
r = dptrs[diskmax+2];
|
||||
|
||||
/* compute syndrome with zero for the missing data page */
|
||||
/* use the dead data page as temporary storage for delta r */
|
||||
dr = dptrs[x];
|
||||
dptrs[x] = zero;
|
||||
dptrs[diskmax+2] = dr;
|
||||
|
||||
raidTP_gen(dptrs, diskmax, size);
|
||||
|
||||
/* restore pointers */
|
||||
dptrs[x] = dr;
|
||||
dptrs[diskmax+2] = r;
|
||||
|
||||
/* select tables */
|
||||
rxmul = table( inv(pow4(x)) );
|
||||
|
||||
while (size--) {
|
||||
/* delta */
|
||||
unsigned char Rd = *r ^ *dr;
|
||||
|
||||
/* addends to reconstruct Dx */
|
||||
unsigned char rxm = rxmul[Rd];
|
||||
|
||||
/* reconstruct Dx */
|
||||
unsigned char Dx = rxm;
|
||||
|
||||
/* set */
|
||||
*dr = Dx;
|
||||
|
||||
++r;
|
||||
++dr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Starting from the equations:
|
||||
*
|
||||
* Pd = Dx + Dy
|
||||
|
|
@ -1632,7 +1529,7 @@ void raidTP_recov_datapq(unsigned char** dptrs, unsigned diskmax, unsigned size,
|
|||
*
|
||||
* That are always satisfied for any 0<=x<y<255.
|
||||
*/
|
||||
void raidTP_recov_2dataq(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, int y, unsigned char* zero)
|
||||
static void raidTP_recov_2dataq(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, int y, unsigned char* zero)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* dp;
|
||||
|
|
@ -1693,7 +1590,9 @@ void raidTP_recov_2dataq(unsigned char** dptrs, unsigned diskmax, unsigned size,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Recover failure of two data blocks without P for RAIDTP.
|
||||
*
|
||||
* Starting from the equations:
|
||||
*
|
||||
* Qd = 2^x * Dx + 2^y * Dy
|
||||
|
|
@ -1715,7 +1614,7 @@ void raidTP_recov_2dataq(unsigned char** dptrs, unsigned diskmax, unsigned size,
|
|||
*
|
||||
* That are always satisfied for any 0<=x<y<255.
|
||||
*/
|
||||
void raidTP_recov_2datap(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, int y, unsigned char* zero)
|
||||
static void raidTP_recov_2datap(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, int y, unsigned char* zero)
|
||||
{
|
||||
unsigned char* q;
|
||||
unsigned char* dq;
|
||||
|
|
@ -1784,7 +1683,9 @@ void raidTP_recov_2datap(unsigned char** dptrs, unsigned diskmax, unsigned size,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Recover failure of three data blocks for RAIDTP.
|
||||
*
|
||||
* Starting from the equations:
|
||||
*
|
||||
* Pd = Dx + Dy + Dz
|
||||
|
|
@ -1817,7 +1718,7 @@ void raidTP_recov_2datap(unsigned char** dptrs, unsigned diskmax, unsigned size,
|
|||
*
|
||||
* That are always satisfied for any 0<=x<y<z<255.
|
||||
*/
|
||||
void raidTP_recov_3data(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, int y, int z, unsigned char* zero)
|
||||
static void raidTP_recov_3data(unsigned char** dptrs, unsigned diskmax, unsigned size, int x, int y, int z, unsigned char* zero)
|
||||
{
|
||||
unsigned char* p;
|
||||
unsigned char* dp;
|
||||
|
|
@ -1972,18 +1873,20 @@ static void invert(unsigned char* M, unsigned char* V, unsigned n)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Recover failure of one data block x using parity i for any RAID level.
|
||||
*
|
||||
* Starting from the equation:
|
||||
*
|
||||
* Sd = 2^i^x * Dx
|
||||
* Sd = (2^i)^x * Dx
|
||||
*
|
||||
* and solving we get:
|
||||
*
|
||||
* Dx = 2^i^(-x) * Sd
|
||||
* Dx = (2^i)^(-x) * Sd
|
||||
*
|
||||
* with conditions:
|
||||
*
|
||||
* 2^i^x != 0
|
||||
* (2^i)^x != 0
|
||||
*
|
||||
* That are always satisfied for any 0<=x<y<255.
|
||||
*/
|
||||
|
|
@ -1993,9 +1896,11 @@ void raid_recov_1data(unsigned char** dptrs, unsigned diskmax, unsigned size, in
|
|||
unsigned char* dp;
|
||||
const unsigned char* pxmul; /* P multiplier to compute Dx */
|
||||
|
||||
/* if i is P use the fast one */
|
||||
if (i == 0)
|
||||
/* if it's RAID5 uses the dedicated and faster function */
|
||||
if (i == 0) {
|
||||
raid5_recov_data(dptrs, diskmax, size, x);
|
||||
return;
|
||||
}
|
||||
|
||||
p = dptrs[diskmax+i];
|
||||
|
||||
|
|
@ -2032,11 +1937,13 @@ void raid_recov_1data(unsigned char** dptrs, unsigned diskmax, unsigned size, in
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Recover failure of two data blocks x,y using parity i,j for any RAID level.
|
||||
*
|
||||
* Starting from the equations:
|
||||
*
|
||||
* Pd = 2^i^x * Dx + 2^i^y * Dy
|
||||
* Qd = 2^j^x * Dx + 2^j^y * Dy
|
||||
* Pd = (2^i)^x * Dx + (2^i)^y * Dy
|
||||
* Qd = (2^j)^x * Dx + (2^j)^y * Dy
|
||||
*
|
||||
* we solve inverting the coefficients matrix.
|
||||
*/
|
||||
|
|
@ -2054,6 +1961,22 @@ void raid_recov_2data(unsigned char** dptrs, unsigned diskmax, unsigned size, in
|
|||
unsigned char V[2*2];
|
||||
unsigned n = 2;
|
||||
|
||||
/* if it's RAID6 uses the dedicated and faster function */
|
||||
if (i == 0 && j == 1) {
|
||||
raid6_recov_2data(dptrs, diskmax, size, x, y, zero);
|
||||
return;
|
||||
}
|
||||
/* if it's RAIDTP uses the dedicated and faster function */
|
||||
if (i == 0 && j == 2) {
|
||||
raidTP_recov_2dataq(dptrs, diskmax, size, x, y, zero);
|
||||
return;
|
||||
}
|
||||
/* if it's RAIDTP uses the dedicated and faster function */
|
||||
if (i == 1 && j == 2) {
|
||||
raidTP_recov_2datap(dptrs, diskmax, size, x, y, zero);
|
||||
return;
|
||||
}
|
||||
|
||||
p = dptrs[diskmax+i];
|
||||
q = dptrs[diskmax+j];
|
||||
|
||||
|
|
@ -2127,12 +2050,14 @@ void raid_recov_2data(unsigned char** dptrs, unsigned diskmax, unsigned size, in
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Recover failure of three data blocks x,y,z using parity i,j,k for any RAID level.
|
||||
*
|
||||
* Starting from the equations:
|
||||
*
|
||||
* Pd = 2^i^x * Dx + 2^i^y * Dy + 2^i^z * Dz
|
||||
* Qd = 2^j^x * Dx + 2^j^y * Dy + 2^j^z * Dz
|
||||
* Rd = 2^k^x * Dx + 2^k^y * Dy + 2^k^z * Dz
|
||||
* Pd = (2^i)^x * Dx + (2^i)^y * Dy + (2^i)^z * Dz
|
||||
* Qd = (2^j)^x * Dx + (2^j)^y * Dy + (2^j)^z * Dz
|
||||
* Rd = (2^k)^x * Dx + (2^k)^y * Dy + (2^k)^z * Dz
|
||||
*
|
||||
* we solve inverting the coefficients matrix.
|
||||
*/
|
||||
|
|
@ -2157,6 +2082,12 @@ void raid_recov_3data(unsigned char** dptrs, unsigned diskmax, unsigned size, in
|
|||
unsigned char V[3*3];
|
||||
unsigned n = 3;
|
||||
|
||||
/* if it's RAIDTP uses the dedicated and faster function */
|
||||
if (i == 0 && j == 1 && k == 2) {
|
||||
raidTP_recov_3data(dptrs, diskmax, size, x, y, z, zero);
|
||||
return;
|
||||
}
|
||||
|
||||
p = dptrs[diskmax+i];
|
||||
q = dptrs[diskmax+j];
|
||||
r = dptrs[diskmax+k];
|
||||
|
|
@ -2260,13 +2191,15 @@ void raid_recov_3data(unsigned char** dptrs, unsigned diskmax, unsigned size, in
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Recover failure of four data blocks x,y,z,v using parity i,j,k,l for any RAID level.
|
||||
*
|
||||
* Starting from the equations:
|
||||
*
|
||||
* Pd = 2^i^x * Dx + 2^i^y * Dy + 2^i^z * Dz + 2^i^v * Dv
|
||||
* Qd = 2^j^x * Dx + 2^j^y * Dy + 2^j^z * Dz + 2^j^v * Dv
|
||||
* Rd = 2^k^x * Dx + 2^k^y * Dy + 2^k^z * Dz + 2^k^v * Dv
|
||||
* Sd = 2^l^x * Dx + 2^l^y * Dy + 2^l^z * Dz + 2^l^v * Dv
|
||||
* Pd = (2^i)^x * Dx + (2^i)^y * Dy + (2^i)^z * Dz + (2^i)^v * Dv
|
||||
* Qd = (2^j)^x * Dx + (2^j)^y * Dy + (2^j)^z * Dz + (2^j)^v * Dv
|
||||
* Rd = (2^k)^x * Dx + (2^k)^y * Dy + (2^k)^z * Dz + (2^k)^v * Dv
|
||||
* Sd = (2^l)^x * Dx + (2^l)^y * Dy + (2^l)^z * Dz + (2^l)^v * Dv
|
||||
*
|
||||
* we solve inverting the coefficients matrix.
|
||||
*/
|
||||
|
|
|
|||
44
raid.h
44
raid.h
|
|
@ -21,50 +21,16 @@
|
|||
/****************************************************************************/
|
||||
/* raid */
|
||||
|
||||
/**
|
||||
* Max number of data disks for quad parity.
|
||||
*/
|
||||
#define RAID_QUAD_DATA_LIMIT 21
|
||||
|
||||
/**
|
||||
* Syndrome computation.
|
||||
*/
|
||||
void raid_gen(unsigned level, unsigned char** buffer, unsigned diskmax, unsigned size);
|
||||
|
||||
/*
|
||||
* Recover failure of one data block.
|
||||
*/
|
||||
void raid5_recov_data(unsigned char** dptrs, unsigned diskmax, unsigned size, int faila);
|
||||
|
||||
/*
|
||||
* Recover two failed data blocks.
|
||||
*/
|
||||
void raid6_recov_2data(unsigned char** dptrs, unsigned diskmax, unsigned size, int faila, int failb, unsigned char* zero);
|
||||
|
||||
/*
|
||||
* Recover failure of one data block ignoring P.
|
||||
* Note that P content is not recovered.
|
||||
*/
|
||||
void raid6_recov_datap(unsigned char** dptrs, unsigned diskmax, unsigned size, int faila, unsigned char* zero);
|
||||
|
||||
/*
|
||||
* Recover failure of one data block ignoring P and Q.
|
||||
* Note that P and Q content is not recovered.
|
||||
*/
|
||||
void raidTP_recov_datapq(unsigned char** dptrs, unsigned diskmax, unsigned size, int faila, unsigned char* zero);
|
||||
|
||||
/*
|
||||
* Recover failure of two data blocks ignoring P.
|
||||
* Note that P content is not recovered.
|
||||
*/
|
||||
void raidTP_recov_2datap(unsigned char** dptrs, unsigned diskmax, unsigned size, int faila, int failb, unsigned char* zero);
|
||||
|
||||
/*
|
||||
* Recover failure of two data blocks ignoring Q.
|
||||
* Note that Q content is not recovered.
|
||||
*/
|
||||
void raidTP_recov_2dataq(unsigned char** dptrs, unsigned diskmax, unsigned size, int faila, int failb, unsigned char* zero);
|
||||
|
||||
/*
|
||||
* Recover failure of three data blocks.
|
||||
*/
|
||||
void raidTP_recov_3data(unsigned char** dptrs, unsigned diskmax, unsigned size, int faila, int failb, int failc, unsigned char* zero);
|
||||
|
||||
/*
|
||||
* Recover failure of one data block x using parity i.
|
||||
*/
|
||||
|
|
|
|||
368
selftest.c
368
selftest.c
|
|
@ -20,6 +20,8 @@
|
|||
#include "snapraid.h"
|
||||
#include "util.h"
|
||||
#include "raid.h"
|
||||
#include "elem.h"
|
||||
#include "state.h"
|
||||
|
||||
struct hash_test_vector {
|
||||
const char* data;
|
||||
|
|
@ -43,338 +45,7 @@ static struct hash_test_vector TEST_SPOOKY2[] = {
|
|||
{ 0, 0, { 0 } }
|
||||
};
|
||||
|
||||
static void raid5test(unsigned diskmax, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
unsigned char** buffer;
|
||||
unsigned char* buffer_test;
|
||||
unsigned buffermax;
|
||||
unsigned i, j;
|
||||
|
||||
buffermax = diskmax + 1 + 1;
|
||||
|
||||
buffer = malloc_nofail_vector_align(buffermax, block_size, &buffer_alloc);
|
||||
|
||||
buffer_test = buffer[buffermax-1];
|
||||
|
||||
/* fill with random */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
for(j=0;j<block_size;++j)
|
||||
buffer[i][j] = rand();
|
||||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(1, buffer, diskmax, block_size);
|
||||
|
||||
for(i=0;i<diskmax;++i) {
|
||||
unsigned char* a;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
|
||||
/* damage */
|
||||
buffer[i] = buffer_test;
|
||||
|
||||
/* recover */
|
||||
raid5_recov_data(buffer, diskmax, block_size, i);
|
||||
|
||||
/* restore */
|
||||
buffer[i] = a;
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test, buffer[i], block_size) != 0) {
|
||||
fprintf(stderr, "Failed RAID5 test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void raid6test(unsigned diskmax, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
unsigned char** buffer;
|
||||
unsigned char* buffer_test0;
|
||||
unsigned char* buffer_test1;
|
||||
unsigned char* buffer_zero;
|
||||
unsigned char* buffer_bad;
|
||||
unsigned buffermax;
|
||||
unsigned i, j;
|
||||
|
||||
buffermax = diskmax + 2 + 2 + 1 + 1;
|
||||
|
||||
buffer = malloc_nofail_vector_align(buffermax, block_size, &buffer_alloc);
|
||||
|
||||
buffer_test0 = buffer[buffermax-4];
|
||||
buffer_test1 = buffer[buffermax-3];
|
||||
buffer_zero = buffer[buffermax-2];
|
||||
buffer_bad = buffer[buffermax-1];
|
||||
memset(buffer_zero, 0, block_size);
|
||||
memset(buffer_bad, 0xA5, block_size);
|
||||
|
||||
/* fill with random */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
for(j=0;j<block_size;++j)
|
||||
buffer[i][j] = rand();
|
||||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(2, buffer, diskmax, block_size);
|
||||
|
||||
/* check 2data */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
for(j=i+1;j<diskmax;++j) {
|
||||
unsigned char* a;
|
||||
unsigned char* b;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
b = buffer[j];
|
||||
|
||||
/* damage */
|
||||
buffer[i] = buffer_test0;
|
||||
buffer[j] = buffer_test1;
|
||||
|
||||
/* recover */
|
||||
raid6_recov_2data(buffer, diskmax, block_size, i, j, buffer_zero);
|
||||
|
||||
/* restore */
|
||||
buffer[i] = a;
|
||||
buffer[j] = b;
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, buffer[i], block_size) != 0
|
||||
|| memcmp(buffer_test1, buffer[j], block_size) != 0
|
||||
) {
|
||||
fprintf(stderr, "Failed RAID6 test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check datap */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
unsigned char* a;
|
||||
unsigned char* p;
|
||||
|
||||
/* other is p */
|
||||
j = diskmax;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
p = buffer[j];
|
||||
|
||||
/* damage */
|
||||
buffer[i] = buffer_test0;
|
||||
buffer[j] = buffer_bad;
|
||||
|
||||
/* recover */
|
||||
raid6_recov_datap(buffer, diskmax, block_size, i, buffer_zero);
|
||||
|
||||
/* restore */
|
||||
buffer[i] = a;
|
||||
buffer[j] = p;
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, buffer[i], block_size) != 0) {
|
||||
fprintf(stderr, "Failed RAID6 test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void raidTPtest(unsigned diskmax, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
unsigned char** buffer;
|
||||
unsigned char* buffer_test0;
|
||||
unsigned char* buffer_test1;
|
||||
unsigned char* buffer_test2;
|
||||
unsigned char* buffer_zero;
|
||||
unsigned char* buffer_bad;
|
||||
unsigned buffermax;
|
||||
unsigned i, j, k;
|
||||
|
||||
buffermax = diskmax + 3 + 3 + 1 + 1;
|
||||
|
||||
buffer = malloc_nofail_vector_align(buffermax, block_size, &buffer_alloc);
|
||||
|
||||
buffer_test0 = buffer[buffermax-5];
|
||||
buffer_test1 = buffer[buffermax-4];
|
||||
buffer_test2 = buffer[buffermax-3];
|
||||
buffer_zero = buffer[buffermax-2];
|
||||
buffer_bad = buffer[buffermax-1];
|
||||
memset(buffer_zero, 0, block_size);
|
||||
memset(buffer_bad, 0xA5, block_size);
|
||||
|
||||
/* fill with random */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
for(j=0;j<block_size;++j)
|
||||
buffer[i][j] = rand();
|
||||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(3, buffer, diskmax, block_size);
|
||||
|
||||
/* check 3data */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
for(j=i+1;j<diskmax;++j) {
|
||||
for(k=j+1;k<diskmax;++k) {
|
||||
unsigned char* a;
|
||||
unsigned char* b;
|
||||
unsigned char* c;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
b = buffer[j];
|
||||
c = buffer[k];
|
||||
|
||||
/* damage */
|
||||
buffer[i] = buffer_test0;
|
||||
buffer[j] = buffer_test1;
|
||||
buffer[k] = buffer_test2;
|
||||
|
||||
/* recover */
|
||||
raidTP_recov_3data(buffer, diskmax, block_size, i, j, k, buffer_zero);
|
||||
|
||||
/* restore */
|
||||
buffer[i] = a;
|
||||
buffer[j] = b;
|
||||
buffer[k] = c;
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, buffer[i], block_size) != 0
|
||||
|| memcmp(buffer_test1, buffer[j], block_size) != 0
|
||||
|| memcmp(buffer_test2, buffer[k], block_size) != 0
|
||||
) {
|
||||
fprintf(stderr, "Failed RAIDTP test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check 2dataq */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
for(j=i+1;j<diskmax;++j) {
|
||||
unsigned char* a;
|
||||
unsigned char* b;
|
||||
unsigned char* q;
|
||||
|
||||
/* other is q */
|
||||
k = diskmax + 1;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
b = buffer[j];
|
||||
q = buffer[k];
|
||||
|
||||
/* damage */
|
||||
buffer[i] = buffer_test0;
|
||||
buffer[j] = buffer_test1;
|
||||
buffer[k] = buffer_bad;
|
||||
|
||||
/* recover */
|
||||
raidTP_recov_2dataq(buffer, diskmax, block_size, i, j, buffer_zero);
|
||||
|
||||
/* restore */
|
||||
buffer[i] = a;
|
||||
buffer[j] = b;
|
||||
buffer[k] = q;
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, buffer[i], block_size) != 0
|
||||
|| memcmp(buffer_test1, buffer[j], block_size) != 0
|
||||
) {
|
||||
fprintf(stderr, "Failed RAIDTP test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check 2datap */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
for(j=i+1;j<diskmax;++j) {
|
||||
unsigned char* a;
|
||||
unsigned char* b;
|
||||
unsigned char* p;
|
||||
|
||||
/* other is p */
|
||||
k = diskmax;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
b = buffer[j];
|
||||
p = buffer[k];
|
||||
|
||||
/* damage */
|
||||
buffer[i] = buffer_test0;
|
||||
buffer[j] = buffer_test1;
|
||||
buffer[k] = buffer_bad;
|
||||
|
||||
/* recover */
|
||||
raidTP_recov_2datap(buffer, diskmax, block_size, i, j, buffer_zero);
|
||||
|
||||
/* restore */
|
||||
buffer[i] = a;
|
||||
buffer[j] = b;
|
||||
buffer[k] = p;
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, buffer[i], block_size) != 0
|
||||
|| memcmp(buffer_test1, buffer[j], block_size) != 0
|
||||
) {
|
||||
fprintf(stderr, "Failed RAIDTP test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check datapq */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
unsigned char* a;
|
||||
unsigned char* p;
|
||||
unsigned char* q;
|
||||
|
||||
/* others are p,q */
|
||||
j = diskmax;
|
||||
k = diskmax + 1;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
p = buffer[j];
|
||||
q = buffer[k];
|
||||
|
||||
/* damage */
|
||||
buffer[i] = buffer_test0;
|
||||
buffer[j] = buffer_bad;
|
||||
buffer[k] = buffer_bad;
|
||||
|
||||
/* recover */
|
||||
raidTP_recov_datapq(buffer, diskmax, block_size, i, buffer_zero);
|
||||
|
||||
/* restore */
|
||||
buffer[i] = a;
|
||||
buffer[j] = p;
|
||||
buffer[k] = q;
|
||||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, buffer[i], block_size) != 0) {
|
||||
fprintf(stderr, "Failed RAIDTP test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer_alloc);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void raidQPtest(unsigned diskmax, unsigned block_size)
|
||||
static void raidtest(unsigned diskmax, unsigned block_size)
|
||||
{
|
||||
void* buffer_alloc;
|
||||
unsigned char** buffer;
|
||||
|
|
@ -391,7 +62,7 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
struct combo1 {
|
||||
int ignore[3];
|
||||
int use;
|
||||
} COMBO1[4] = {
|
||||
} COMBO1[] = {
|
||||
{ { 1, 2, 3 }, 0 },
|
||||
{ { 0, 2, 3 }, 1 },
|
||||
{ { 0, 1, 3 }, 2 },
|
||||
|
|
@ -401,7 +72,7 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
struct combo2 {
|
||||
int ignore[2];
|
||||
int use[2];
|
||||
} COMBO2[6] = {
|
||||
} COMBO2[] = {
|
||||
{ { 0, 1 }, { 2, 3 } },
|
||||
{ { 0, 2 }, { 1, 3 } },
|
||||
{ { 0, 3 }, { 1, 2 } },
|
||||
|
|
@ -413,14 +84,14 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
struct combo3 {
|
||||
int ignore;
|
||||
int use[3];
|
||||
} COMBO3[4] = {
|
||||
} COMBO3[] = {
|
||||
{ 0, { 1, 2, 3 } },
|
||||
{ 1, { 0, 2, 3 } },
|
||||
{ 2, { 0, 1, 3 } },
|
||||
{ 3, { 0, 1, 2 } }
|
||||
};
|
||||
|
||||
buffermax = diskmax + 4 + 4 + 1 + 1;
|
||||
buffermax = diskmax + LEV_MAX * 2 + 1 + 1;
|
||||
|
||||
buffer = malloc_nofail_vector_align(buffermax, block_size, &buffer_alloc);
|
||||
|
||||
|
|
@ -440,7 +111,7 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
}
|
||||
|
||||
/* compute the parity */
|
||||
raid_gen(4, buffer, diskmax, block_size);
|
||||
raid_gen(LEV_MAX, buffer, diskmax, block_size);
|
||||
|
||||
/* check 4data */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
|
|
@ -473,7 +144,7 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
|| memcmp(buffer_test2, c, block_size) != 0
|
||||
|| memcmp(buffer_test3, d, block_size) != 0
|
||||
) {
|
||||
fprintf(stderr, "Failed RAIDQP test\n");
|
||||
fprintf(stderr, "Failed RAID test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -491,12 +162,16 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
for(i=0;i<diskmax;++i) {
|
||||
for(j=i+1;j<diskmax;++j) {
|
||||
for(k=j+1;k<diskmax;++k) {
|
||||
for(n=0;n<4;++n) {
|
||||
for(n=0;n<sizeof(COMBO3)/sizeof(COMBO3[0]);++n) {
|
||||
unsigned char* a;
|
||||
unsigned char* b;
|
||||
unsigned char* c;
|
||||
unsigned char* p;
|
||||
|
||||
/* this is the point where quad parity fails over RAID_QUAD_DATA_LIMIT data disks */
|
||||
if (diskmax > RAID_QUAD_DATA_LIMIT && COMBO3[n].use[2] >= 3)
|
||||
continue;
|
||||
|
||||
/* save */
|
||||
a = buffer[i];
|
||||
b = buffer[j];
|
||||
|
|
@ -520,7 +195,7 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
|| memcmp(buffer_test1, b, block_size) != 0
|
||||
|| memcmp(buffer_test2, c, block_size) != 0
|
||||
) {
|
||||
fprintf(stderr, "Failed RAIDQP test 1\n");
|
||||
fprintf(stderr, "Failed RAID test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -539,7 +214,7 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
/* check 2data */
|
||||
for(i=0;i<diskmax;++i) {
|
||||
for(j=i+1;j<diskmax;++j) {
|
||||
for(n=0;n<6;++n) {
|
||||
for(n=0;n<sizeof(COMBO2)/sizeof(COMBO2[0]);++n) {
|
||||
unsigned char* a;
|
||||
unsigned char* b;
|
||||
unsigned char* p;
|
||||
|
|
@ -568,7 +243,7 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
if (memcmp(buffer_test0, a, block_size) != 0
|
||||
|| memcmp(buffer_test1, b, block_size) != 0
|
||||
) {
|
||||
fprintf(stderr, "Failed RAIDQP test 1\n");
|
||||
fprintf(stderr, "Failed RAID test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -584,7 +259,7 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
}
|
||||
|
||||
/* check 1data */
|
||||
for(n=0;n<4;++n) {
|
||||
for(n=0;n<sizeof(COMBO1)/sizeof(COMBO1[0]);++n) {
|
||||
for(i=0;i<diskmax;++i) {
|
||||
unsigned char* a;
|
||||
unsigned char* p;
|
||||
|
|
@ -613,7 +288,7 @@ static void raidQPtest(unsigned diskmax, unsigned block_size)
|
|||
|
||||
/* check */
|
||||
if (memcmp(buffer_test0, a, block_size) != 0) {
|
||||
fprintf(stderr, "Failed RAIDQP test\n");
|
||||
fprintf(stderr, "Failed RAID test\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
@ -746,9 +421,6 @@ void selftest(int gui)
|
|||
|
||||
hashtest();
|
||||
crc32ctest();
|
||||
raid5test(33, 1024);
|
||||
raid6test(33, 1024);
|
||||
raidTPtest(33, 1024);
|
||||
raidQPtest(21, 1024);
|
||||
raidtest(24, 2048);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue