mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Eliminate obsolete raid_zero API and dedicated zero buffers
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-arm32 (push) Waiting to run
Build / build-win (push) Waiting to run
Build / build-freebsd (push) Waiting to run
Build / build-musl (push) Waiting to run
CodeQL Advanced / Analyze (c-cpp) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
Some checks are pending
Build / build-mac (push) Waiting to run
Build / build-linux (push) Waiting to run
Build / build-arm32 (push) Waiting to run
Build / build-win (push) Waiting to run
Build / build-freebsd (push) Waiting to run
Build / build-musl (push) Waiting to run
CodeQL Advanced / Analyze (c-cpp) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
This commit is contained in:
parent
8f27c393d6
commit
0b64fb2eae
7 changed files with 66 additions and 68 deletions
|
|
@ -280,7 +280,7 @@ struct failed_struct {
|
|||
* Check if a block hash matches the specified buffer.
|
||||
* Return ==0 if equal
|
||||
*/
|
||||
static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, size_t pos_size, unsigned char* buffer, unsigned char* buffer_zero)
|
||||
static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, size_t pos_size, unsigned char* buffer)
|
||||
{
|
||||
unsigned char hash[HASH_MAX];
|
||||
|
||||
|
|
@ -304,7 +304,7 @@ static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_bl
|
|||
* but also makes the canonical-block invariant explicit.
|
||||
*/
|
||||
if (pos_size < state->block_size) {
|
||||
if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) {
|
||||
if (!mem_is_zero(buffer + pos_size, state->block_size - pos_size)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
@ -315,7 +315,7 @@ static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_bl
|
|||
/**
|
||||
* Check if the hash of all the failed blocks we are expecting to recover are now matching.
|
||||
*/
|
||||
static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void* buffer_zero)
|
||||
static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer)
|
||||
{
|
||||
unsigned j;
|
||||
int hash_checked;
|
||||
|
|
@ -331,7 +331,7 @@ static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned d
|
|||
) {
|
||||
/* if a hash doesn't match, fail the check */
|
||||
size_t pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size);
|
||||
if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) {
|
||||
if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index]) != 0) {
|
||||
log_tag("repair_hash_error:%u: Hash mismatch\n", failed_map[j]);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -389,7 +389,7 @@ static int is_parity_matching(struct snapraid_state* state, unsigned diskmax, un
|
|||
*
|
||||
* On success all parity levels are recomputed in buffer.
|
||||
*/
|
||||
static int repair_step(struct snapraid_state* state, int rehash, block_off_t pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero)
|
||||
static int repair_step(struct snapraid_state* state, int rehash, block_off_t pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov)
|
||||
{
|
||||
unsigned i, n;
|
||||
int error;
|
||||
|
|
@ -515,7 +515,7 @@ static int repair_step(struct snapraid_state* state, int rehash, block_off_t pos
|
|||
raid_data(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))
|
||||
if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer))
|
||||
return 0;
|
||||
|
||||
/* log */
|
||||
|
|
@ -647,9 +647,6 @@ static int repair_step(struct snapraid_state* state, int rehash, block_off_t pos
|
|||
* the corresponding parity level is unavailable or cannot be
|
||||
* trusted for recovery.
|
||||
*
|
||||
* buffer_zero A full block containing zeroes, used both for ZERO-state CHGs
|
||||
* and for validating zero padding.
|
||||
*
|
||||
* Return value:
|
||||
*
|
||||
* 0 A RAID solution was successfully validated under one of the two history
|
||||
|
|
@ -667,7 +664,7 @@ static int repair_step(struct snapraid_state* state, int rehash, block_off_t pos
|
|||
* On successful return buffer[] contains the recovered data and parity
|
||||
* recomputed from that data.
|
||||
*/
|
||||
static int repair(struct snapraid_state* state, int rehash, block_off_t pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero)
|
||||
static int repair(struct snapraid_state* state, int rehash, block_off_t pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov)
|
||||
{
|
||||
int ret;
|
||||
int error;
|
||||
|
|
@ -848,7 +845,7 @@ static int repair(struct snapraid_state* state, int rehash, block_off_t pos, uns
|
|||
* only OLD and CURRENT generations, allowing their generation to be inferred
|
||||
* after the RAID solution itself has been validated.
|
||||
*/
|
||||
ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero);
|
||||
ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov);
|
||||
|
||||
if (ret == 0) {
|
||||
int has_recovered_chg;
|
||||
|
|
@ -958,7 +955,7 @@ static int repair(struct snapraid_state* state, int rehash, block_off_t pos, uns
|
|||
* A zero candidate is ambiguous because OLD and CURRENT
|
||||
* may legitimately contain the same zero block.
|
||||
*/
|
||||
if (memcmp(buffer[failed[j].index], buffer_zero, state->block_size) != 0)
|
||||
if (!mem_is_zero(buffer[failed[j].index], state->block_size))
|
||||
current_generation_proven = 1;
|
||||
} else {
|
||||
size_t pos_size;
|
||||
|
|
@ -973,7 +970,7 @@ static int repair(struct snapraid_state* state, int rehash, block_off_t pos, uns
|
|||
* candidate != OLD and therefore identifies this validated RAID
|
||||
* solution as CURRENT.
|
||||
*/
|
||||
if (blockcmp(state, rehash, failed[j].block, pos_size, buffer[failed[j].index], buffer_zero) != 0)
|
||||
if (blockcmp(state, rehash, failed[j].block, pos_size, buffer[failed[j].index]) != 0)
|
||||
current_generation_proven = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1186,7 +1183,7 @@ static int repair(struct snapraid_state* state, int rehash, block_off_t pos, uns
|
|||
* or would just repeat the same recovery equations already attempted.
|
||||
*/
|
||||
if (something_to_recover && something_unsynced) {
|
||||
ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero);
|
||||
ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov);
|
||||
|
||||
if (ret == 0) {
|
||||
/*
|
||||
|
|
@ -1593,17 +1590,13 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
|
|||
if (parity[j])
|
||||
parity[j]->bw = &bw;
|
||||
|
||||
/* we need 1 * data + 2 * parity + 1 * zero */
|
||||
buffermax = diskmax + 2 * state->level + 1;
|
||||
/* we need 1 * data + 2 * parity */
|
||||
buffermax = diskmax + 2 * state->level;
|
||||
|
||||
buffer = malloc_nofail_vector_align(buffermax, state->block_size, &buffer_alloc);
|
||||
if (!state->opt.skip_self)
|
||||
mtest_vector(buffermax, state->block_size, buffer);
|
||||
|
||||
/* fill up the zero buffer */
|
||||
memset(buffer[buffermax - 1], 0, state->block_size);
|
||||
raid_zero(buffer[buffermax - 1]);
|
||||
|
||||
failed = nalloc_nofail(diskmax, sizeof(struct failed_struct));
|
||||
failed_map = nalloc_nofail(diskmax, sizeof(unsigned));
|
||||
|
||||
|
|
@ -2016,7 +2009,6 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
|
|||
/* now read and check the parity if requested */
|
||||
if (!state->opt.auditonly) {
|
||||
void* buffer_recov[LEV_MAX];
|
||||
void* buffer_zero;
|
||||
|
||||
/* buffers for parity read and not computed */
|
||||
for (l = 0; l < state->level; ++l)
|
||||
|
|
@ -2024,9 +2016,6 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
|
|||
for (; l < LEV_MAX; ++l)
|
||||
buffer_recov[l] = 0;
|
||||
|
||||
/* the zero buffer is the last one */
|
||||
buffer_zero = buffer[buffermax - 1];
|
||||
|
||||
/* read the parity */
|
||||
for (l = 0; l < state->level; ++l) {
|
||||
if (parity[l]) {
|
||||
|
|
@ -2056,7 +2045,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
|
|||
}
|
||||
|
||||
/* try all the recovering strategies */
|
||||
ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero);
|
||||
ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov);
|
||||
if (ret != 0) {
|
||||
/* increment the number of errors */
|
||||
if (ret > 0)
|
||||
|
|
|
|||
|
|
@ -2038,6 +2038,26 @@ static void test_misc(int argc, char* argv[])
|
|||
assert(strcmp(esc_tag(""), "") == 0);
|
||||
assert(strcmp(esc_tag("\n\r:\\\\"), "\\n\\r\\d\\\\\\\\") == 0);
|
||||
|
||||
{
|
||||
unsigned char zbuf[64];
|
||||
unsigned zi, zj;
|
||||
|
||||
memset(zbuf, 0, sizeof(zbuf));
|
||||
assert(mem_is_zero(zbuf, 0) != 0);
|
||||
|
||||
for (zi = 0; zi < sizeof(zbuf); ++zi) {
|
||||
for (zj = zi; zj <= sizeof(zbuf); ++zj) {
|
||||
assert(mem_is_zero(zbuf + zi, zj - zi) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (zi = 0; zi < sizeof(zbuf); ++zi) {
|
||||
zbuf[zi] = 1;
|
||||
assert(mem_is_zero(zbuf, sizeof(zbuf)) == 0);
|
||||
zbuf[zi] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 2; i < argc; ++i) {
|
||||
printf("argv[%d]\n", i);
|
||||
printf("\t#%s#\n", argv[i]);
|
||||
|
|
|
|||
|
|
@ -2362,7 +2362,7 @@ void speed(int period, int nd, int size)
|
|||
|
||||
delta = period >= 1000 ? 10 : 1;
|
||||
|
||||
nv = nd + RAID_PARITY_MAX + 1;
|
||||
nv = nd + RAID_PARITY_MAX;
|
||||
|
||||
v = malloc_nofail_vector_align(nv, size, &v_alloc);
|
||||
|
||||
|
|
@ -2370,10 +2370,6 @@ void speed(int period, int nd, int size)
|
|||
for (i = 0; i < nd; ++i)
|
||||
memset(v[i], i, size);
|
||||
|
||||
/* zero buffer */
|
||||
memset(v[nd + RAID_PARITY_MAX], 0, size);
|
||||
raid_zero(v[nd + RAID_PARITY_MAX]);
|
||||
|
||||
printf(PACKAGE " v" VERSION " by Andrea Mazzoleni, " PACKAGE_URL "\n");
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
|
|
|||
|
|
@ -940,8 +940,6 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
unsigned diskmax;
|
||||
block_off_t blockcur;
|
||||
unsigned j;
|
||||
void* zero_alloc;
|
||||
void** zero;
|
||||
void* copy_alloc;
|
||||
void** copy;
|
||||
unsigned buffermax;
|
||||
|
|
@ -981,11 +979,6 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* allocate the copy buffer */
|
||||
copy = malloc_nofail_vector_align(diskmax, state->block_size, ©_alloc);
|
||||
|
||||
/* allocate and fill the zero buffer */
|
||||
zero = malloc_nofail_align(state->block_size, &zero_alloc);
|
||||
memset(zero, 0, state->block_size);
|
||||
raid_zero(zero);
|
||||
|
||||
failed = nalloc_nofail(diskmax, sizeof(struct failed_struct));
|
||||
failed_map = nalloc_nofail(diskmax, sizeof(unsigned));
|
||||
|
||||
|
|
@ -1799,7 +1792,6 @@ bail:
|
|||
}
|
||||
|
||||
free(handle);
|
||||
free(zero_alloc);
|
||||
free(copy_alloc);
|
||||
free(copy);
|
||||
free(rehandle_alloc);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,37 @@ void* malloc_nofail_test(size_t size);
|
|||
*/
|
||||
void mtest_vector(int n, size_t size, void** vv);
|
||||
|
||||
/**
|
||||
* Return !=0 if the memory region is completely filled with zeros.
|
||||
*/
|
||||
static inline int mem_is_zero(const void* ptr, size_t size)
|
||||
{
|
||||
const unsigned char* p = ptr;
|
||||
|
||||
while (size != 0 && ((uintptr_t)p % sizeof(size_t)) != 0) {
|
||||
if (*p != 0)
|
||||
return 0;
|
||||
++p;
|
||||
--size;
|
||||
}
|
||||
|
||||
while (size >= sizeof(size_t)) {
|
||||
if (*(const size_t*)p != 0)
|
||||
return 0;
|
||||
p += sizeof(size_t);
|
||||
size -= sizeof(size_t);
|
||||
}
|
||||
|
||||
while (size != 0) {
|
||||
if (*p != 0)
|
||||
return 0;
|
||||
++p;
|
||||
--size;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* crc */
|
||||
|
||||
|
|
|
|||
|
|
@ -215,15 +215,7 @@
|
|||
* [5] Plank, "Screaming Fast Galois Field Arithmetic Using Intel SIMD Instructions", 2013
|
||||
*/
|
||||
|
||||
/**
|
||||
* Buffer filled with 0 used in recovering.
|
||||
*/
|
||||
static void *raid_zero_block;
|
||||
|
||||
void raid_zero(void *zero)
|
||||
{
|
||||
raid_zero_block = zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts the square matrix M of size nxn into V.
|
||||
|
|
|
|||
22
raid/raid.h
22
raid/raid.h
|
|
@ -161,32 +161,10 @@ int raid_mode(int mode);
|
|||
* The test modifies global RAID state and must not be called concurrently
|
||||
* with any other RAID function.
|
||||
*
|
||||
* The test resets the zero buffer to 0 via raid_zero(0) upon completion.
|
||||
* A valid zero buffer must be set with raid_zero() afterwards before calling
|
||||
* recovery functions (raid_rec(), raid_data()).
|
||||
*
|
||||
* It returns 0 on success.
|
||||
*/
|
||||
int raid_selftest(void);
|
||||
|
||||
/**
|
||||
* Sets the zero buffer to use during recovery.
|
||||
*
|
||||
* Before calling raid_rec() and raid_data() you must provide a memory
|
||||
* buffer filled with zeros of the same size as the blocks to recover.
|
||||
*
|
||||
* The buffer pointed to by @zero must be aligned to a 64-byte boundary.
|
||||
*
|
||||
* This buffer is only read and never written.
|
||||
*
|
||||
* The selected zero buffer is global to the RAID library. raid_zero() must
|
||||
* not be called concurrently with any other RAID function.
|
||||
*
|
||||
* Once set, the buffer must remain valid and unchanged while it is being
|
||||
* used by recovery operations.
|
||||
*/
|
||||
void raid_zero(void *zero);
|
||||
|
||||
/**
|
||||
* Block aliasing
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue