From ce2d03bd806682464e0a282fb0481b1f3303a25a Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Tue, 26 Aug 2014 12:39:06 +0200 Subject: [PATCH] Extends the RAID engine to remove the waste buffer need. It's possible to reuse another parity buffer, instead of requiring a specific one. --- raid/raid.c | 120 +++++++++++++++++++++++++--------------------------- raid/raid.h | 19 +++------ 2 files changed, 64 insertions(+), 75 deletions(-) diff --git a/raid/raid.c b/raid/raid.c index da435bd4..5bf56bbd 100644 --- a/raid/raid.c +++ b/raid/raid.c @@ -194,16 +194,6 @@ void raid_zero(void *zero) raid_zero_block = zero; } -/** - * Buffer for raid_rec_dataonly(). - */ -static void *raid_waste_block; - -void raid_waste(void *waste) -{ - raid_waste_block = waste; -} - /* * Forwarders for parity computation. * @@ -287,40 +277,76 @@ void raid_invert(uint8_t *M, uint8_t *V, int n) * * This is the parity expressed as Pa,Qa,Ra,Sa,Ta,Ua * in the equations. - * - * Note that all the other parities not in the ip[] vector - * are destroyed. */ void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v) { void *p[RAID_PARITY_MAX]; void *pa[RAID_PARITY_MAX]; - int i; + int i, j; + int np; + void* latest; - for (i = 0; i < nr; ++i) { - /* keep a copy of the parity buffer */ - p[i] = v[nd+ip[i]]; + /* number of parities used */ + np = ip[nr - 1] + 1; - /* buffer for missing data blocks */ - pa[i] = v[id[i]]; + /* latest missing data block */ + latest = v[id[nr - 1]]; - /* set at zero the missing data blocks */ - v[id[i]] = raid_zero_block; + /* setup pointers for delta computation */ + for (i = 0, j = 0; i < np; ++i) { + /* keep a copy of the original parity vector */ + p[i] = v[nd + i]; - /* compute the parity over the missing data blocks */ - v[nd+ip[i]] = pa[i]; + if (j < nr && ip[j] == i) { + /* + * Set used parities to point to the missing + * data blocks. + * + * The related data blocks are instead set + * to point to the "zero" buffer. + */ + + /* buffer for missing data blocks */ + pa[j] = v[id[j]]; + + /* set at zero the missing data blocks */ + v[id[j]] = raid_zero_block; + + /* compute the parity over the missing data blocks */ + v[nd + i] = pa[j]; + + /* check for the next used entry */ + ++j; + } else { + /* + * Unused parities are going to be rewritten with + * not significative data, becase we don't have + * functions able to compute only a subset of + * parities. + * + * To avoid this, we use reuse parity buffers, assuming + * that all the parity functions write parities in order. + * + * We assign the unused parity block to the same block of the + * latest used parity that we know it will be written. + * + * This means that this block will be written multiple times + * and only the latest write will contain the correct data. + */ + v[nd + i] = latest; + } } /* recompute the minimal parity required */ - raid_gen(nd, ip[nr - 1] + 1, size, v); + raid_gen(nd, np, size, v); - for (i = 0; i < nr; ++i) { - /* restore disk buffers as before */ - v[id[i]] = pa[i]; + /* restore data buffers as before */ + for (j = 0; j < nr; ++j) + v[id[j]] = pa[j]; - /* restore parity buffers as before */ - v[nd+ip[i]] = p[i]; - } + /* restore parity buffers as before */ + for (i = 0; i < np; ++i) + v[nd + i] = p[i]; } /** @@ -507,37 +533,7 @@ void raid_rec_dataonly(int nr, int *id, int *ip, int nd, size_t size, void **v) 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 (j < nr && 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); - } - } + if (nr != 0) + raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v); } diff --git a/raid/raid.h b/raid/raid.h index ca329bbb..17855d71 100644 --- a/raid/raid.h +++ b/raid/raid.h @@ -70,17 +70,13 @@ void raid_mode(int mode); /** * Sets the zero buffer to use in recovering. * - * Before calling raid_rec_dataonly() and raid_recpar() you must provide a memory + * Before calling raid_rec() and raid_rec_dataonly() you must provide a memory * buffer filled with zero with the same size of the blocks to recover. + * + * This buffer is only read and never written. */ 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 blocks. * @@ -118,7 +114,7 @@ void raid_gen(int nd, int np, size_t size, void **v); * provided parities are correct the resulting data will be also correct. * If parities are wrong, also the resulting recovered data will be wrong. * This happens even in the case you have more parities blocks than needed, - * and some form of integrity verification is possible. + * and some form of integrity verification would be possible. * * @nr Number of failed data and parity blocks to recover. * @ir[] Vector of @nr indexes of the data and parity blocks to recover. @@ -139,13 +135,10 @@ void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v); * Recovers failures of data blocks using the specified parities. * * 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. + * The parity blocks are not modified. * * @nr Number of failed data blocks to recover. - * @id[] Vector of @nr indexes of the data blocksto recover. + * @id[] Vector of @nr indexes of the data blocks to recover. * The indexes start from 0. They must be in order. * @ip[] Vector of @nr indexes of the parity blocks to use for recovering. * The indexes start from 0. They must be in order.