Uses a more general interface for the RAID engine.

This commit is contained in:
Andrea Mazzoleni 2013-12-28 15:12:09 +01:00
parent 684edf2173
commit e80a5e868f
5 changed files with 108 additions and 56 deletions

View file

@ -199,7 +199,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
memcpy(buffer[diskmax+ip[i]], buffer_recov[ip[i]], state->block_size);
/* recover using one less parity, the ip[r-1] one */
raid_rec(r-1, id, ip, diskmax, state->block_size, buffer);
raid_rec_dataonly(r-1, id, ip, diskmax, state->block_size, buffer);
/* use the remaining ip[r-1] parity to check the result */
if (is_parity_matching(state, diskmax, ip[r-1], buffer, buffer_recov))
@ -239,7 +239,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
memcpy(buffer[diskmax+ip[i]], buffer_recov[ip[i]], state->block_size);
/* recover */
raid_rec(r, id, ip, diskmax, state->block_size, buffer);
raid_rec_dataonly(r, id, ip, diskmax, state->block_size, buffer);
/* use the hash to check the result */
if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero))

View file

@ -163,7 +163,7 @@ void raid_par2_int64(int nd, size_t size, void **vv)
/*
* PAR3 (triple parity with Cauchy matrix) 8bit C implementation
*
* Note that instead of a generic multiplicationt table, likely resulting
* 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.
@ -210,7 +210,7 @@ void raid_par3_int8(int nd, size_t size, void **vv)
/*
* PAR4 (quad parity with Cauchy matrix) 8bit C implementation
*
* Note that instead of a generic multiplicationt table, likely resulting
* 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.
@ -262,7 +262,7 @@ void raid_par4_int8(int nd, size_t size, void **vv)
/*
* PAR5 (penta parity with Cauchy matrix) 8bit C implementation
*
* Note that instead of a generic multiplicationt table, likely resulting
* 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.
@ -319,7 +319,7 @@ void raid_par5_int8(int nd, size_t size, void **vv)
/*
* PAR6 (hexa parity with Cauchy matrix) 8bit C implementation
*
* Note that instead of a generic multiplicationt table, likely resulting
* 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.

View file

@ -212,11 +212,21 @@ void raid_mode(int mode)
/**
* Buffer filled with 0 used in recovering.
*/
static void *raid_empty_zero_block;
static void *raid_zero_block;
void raid_zero(void *zero)
{
raid_empty_zero_block = zero;
raid_zero_block = zero;
}
/**
* Buffer for raid_rec_dataonly().
*/
static void *raid_waste_block;
void raid_waste(void *waste)
{
raid_waste_block = waste;
}
/* internal forwarder */
@ -298,7 +308,7 @@ void raid_delta_gen(int nr, const int *id, const int *ip, int nd, size_t size, v
pa[i] = v[id[i]];
/* set at zero the missing data blocks */
v[id[i]] = raid_empty_zero_block;
v[id[i]] = raid_zero_block;
/* compute the parity over the missing data blocks */
v[nd+ip[i]] = pa[i];
@ -414,17 +424,7 @@ void raid_rec2_par2(const int *id, const int *ip, int nd, size_t size, void **vv
/* internal forwarder */
void (*raid_rec_ptr[RAID_PARITY_MAX])(int nr, const int *id, const int *ip, int nd, size_t size, void **vv);
void raid_rec(int nr, const int *id, const int *ip, int nd, size_t size, void **v)
{
BUG_ON(nr > nd);
BUG_ON(size % 64 != 0);
/* if failed data is present */
if (nr != 0)
raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v);
}
void raid_recpar(int nrd, const int *id, int nrp, int *ip, int np, int nd, size_t size, void **v)
void raid_rec(int nrd, const int *id, int nrp, int *ip, int np, int nd, size_t size, void **v)
{
BUG_ON(nrd > nd);
BUG_ON(nrd + nrp > np);
@ -438,8 +438,10 @@ void raid_recpar(int nrd, const int *id, int nrp, int *ip, int np, int nd, size_
/* setup the vector of parities to use */
for (i = 0, j = 0, k = 0; i < np; ++i) {
if (ip[j] == i) {
/* this parity has to be recovered */
++j;
} else {
/* this parity is used for recovering */
iu[k] = i;
++k;
}
@ -454,3 +456,43 @@ void raid_recpar(int nrd, const int *id, int nrp, int *ip, int np, int nd, size_
raid_par(ip[nrp - 1] + 1, nd, size, v);
}
void raid_rec_dataonly(int nr, const int *id, const int *ip, int nd, size_t size, void **v)
{
BUG_ON(nr > nd);
BUG_ON(size % 64 != 0);
/* if failed data is present */
if (nr != 0) {
/* if there is a waste buffer, use it to save unused parities */
if (raid_waste_block != 0) {
void * p[RAID_PARITY_MAX];
int i, j;
int np;
/* number of parities used */
np = ip[nr - 1] + 1;
/* set unused parities to the waste buffer */
for (i = 0, j = 0; i < np; ++i) {
p[i] = v[nd+i];
if (ip[j] == i) {
/* this parity is used for recovering */
++j;
} else {
/* this parity is not used */
v[nd+i] = raid_waste_block;
}
}
raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v);
/* restore pointers */
for (i = 0; i < np; ++i)
v[nd+i] = p[i];
} else {
raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v);
}
}
}

View file

@ -67,11 +67,17 @@ void raid_mode(int mode);
/**
* Sets the zero buffer to use in recovering.
*
* Before calling raid_rec() and raid_recpar() you must provide a memory
* Before calling raid_rec_dataonly() and raid_recpar() you must provide a memory
* buffer filled with zero with the same size of the blocks to recover.
*/
void raid_zero(void *zero);
/**
* Sets an additional buffer used by raid_rec_dataonly() to avoid to overwrite
* unused parities.
*/
void raid_waste(void *zero);
/**
* Computes the parity.
*
@ -86,10 +92,42 @@ void raid_zero(void *zero);
void raid_par(int np, int nd, size_t size, void **vv);
/**
* Recovers failures of data disks using the specified parities.
* Recovers failures of data and parity blocks.
*
* Only the data blocks are recovered. The parity buffers are destroyed.
* If you want also to recompute parities, you can use raid_recpar().
* All the data and parity blocks marked as bad in the ::id and ::ip vector
* are recovered and recomputed.
*
* The parities blocks to use for recoverign are automatically selected from
* the ones NOT present in the ::ip vector.
*
* Ensure to have ::nrd + ::nrp <= ::np, otherwise recovering is not possible.
*
* \param nrd Number of failed data disks to recover.
* \param id[] Vector of ::nrd indexes of the data disks to recover.
* The indexes start from 0. They must be in order.
* \param nrp Number of failed parity disks to recover.
* \param ip[] Vector of ::nrp indexes of the parity disks 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.
* \param np Number of parity disks.
* \param nd Number of data disks.
* \param size Size of the blocks pointed by vv. It must be a multipler of 64.
* \param vv Vector of pointers to the blocks for disks and parities.
* It has (::nd + ::np) elements. The first elements are the blocks
* for data, following with the parity blocks.
* Each blocks has ::size bytes.
*/
void raid_rec(int nrd, const int *id, int nrp, int *ip, int np, int nd, size_t size, void **vv);
/**
* Recovers failures of data blocks using the specified parities.
*
* The data blocks marked as bad in the ::id vector are recovered.
*
* If you have provided an additional buffer with raid_waste(), the
* parity blocks are not modified. Without this buffer, the content of
* parities blocks not specified in the ::ip vector will be destroyed.
*
* \param nr Number of failed data disks to recover.
* \param id[] Vector of ::nr indexes of the data disks to recover.
@ -103,35 +141,7 @@ void raid_par(int np, int nd, size_t size, void **vv);
* blocks for data, following with the parity blocks.
* Each blocks has ::size bytes.
*/
void raid_rec(int nr, const int *id, const int *ip, int nd, size_t size, void **vv);
/**
* Recovers failures of data and parity disks.
*
* It's similar at raid_rec() but it also recovers parities.
*
* In case there are more parities available than needed, ones to use are
* automatically selected, excluding the ones specified in the ::ip vector.
*
* Ensure to have ::nrd + ::nrp <= ::np, otherwise recovering is not possible.
*
* \param nrd Number of failed data disks to recover.
* \param id[] Vector of ::nrd indexes of the data disks to recover.
* The indexes start from 0. They must be in order.
* \param nrp Number of failed parity disks to recover.
* \param ip[] Vector of ::nrp indexes of the parity disks to recover.
* The indexes start from 0. They must be in order.
* Note that as difference than raid_rec() these are the failed parities.
* All the parities not specified here are assumed correct, and they are
* not recomputed.
* \param np Number of parity disks.
* \param nd Number of data disks.
* \param size Size of the blocks pointed by vv. It must be a multipler of 64.
* \param vv Vector of pointers to the blocks for disks and parities.
* It has (::nd + ::np) elements. The first elements are the blocks
* for data, following with the parity blocks.
* Each blocks has ::size bytes.
*/
void raid_recpar(int nrd, const int *id, int nrp, int *ip, int np, int nd, size_t size, void **vv);
void raid_rec_dataonly(int nr, const int *id, const int *ip, int nd, size_t size, void **vv);
#endif

View file

@ -591,7 +591,7 @@ void speed(void)
SPEED_START {
for(j=0;j<nd;++j) {
/* +1 to avoid PAR1 optimized case */
/* +1 to avoid PAR2 optimized case */
raid_rec2_int8(2, id, ip + 1, nd, block_size, buffer);
}
} SPEED_STOP
@ -603,7 +603,7 @@ void speed(void)
if (raid_cpu_has_ssse3()) {
SPEED_START {
for(j=0;j<nd;++j) {
/* +1 to avoid PAR1 optimized case */
/* +1 to avoid PAR2 optimized case */
raid_rec2_ssse3(2, id, ip + 1, nd, block_size, buffer);
}
} SPEED_STOP