From e80a5e868f6ee9d9c19390899037bc821c9bae80 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Sat, 28 Dec 2013 15:12:09 +0100 Subject: [PATCH] Uses a more general interface for the RAID engine. --- check.c | 4 +-- raid/int.c | 8 +++--- raid/raid.c | 70 +++++++++++++++++++++++++++++++++++++---------- raid/raid.h | 78 ++++++++++++++++++++++++++++++----------------------- speed.c | 4 +-- 5 files changed, 108 insertions(+), 56 deletions(-) diff --git a/check.c b/check.c index ad4c62a2..bf07adca 100644 --- a/check.c +++ b/check.c @@ -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)) diff --git a/raid/int.c b/raid/int.c index 437e1acd..d15622a5 100644 --- a/raid/int.c +++ b/raid/int.c @@ -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. diff --git a/raid/raid.c b/raid/raid.c index 714cbf8d..a66f3031 100644 --- a/raid/raid.c +++ b/raid/raid.c @@ -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); + } + } +} + diff --git a/raid/raid.h b/raid/raid.h index 0782db38..90293b9b 100644 --- a/raid/raid.h +++ b/raid/raid.h @@ -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 + diff --git a/speed.c b/speed.c index 839ae53e..fce475e3 100644 --- a/speed.c +++ b/speed.c @@ -591,7 +591,7 @@ void speed(void) SPEED_START { for(j=0;j