mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Assumes also CHG blocks with a NULL hash without needing an info block.
Some refactoring and renaming of other hash functions to avoid misunderstanding.
This commit is contained in:
parent
9ad388724e
commit
e0afd0edf7
6 changed files with 50 additions and 34 deletions
8
check.c
8
check.c
|
|
@ -112,7 +112,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
/* if there isn't, we have to sacrifice a parity block to check that the result is correct */
|
||||
has_hash = 0;
|
||||
for(j=0;j<failed_count;++j) {
|
||||
if (block_has_hash(failed[failed_map[j]].block)) /* if the block can be checked */
|
||||
if (block_has_updated_hash(failed[failed_map[j]].block)) /* if the block can be checked */
|
||||
has_hash = 1;
|
||||
}
|
||||
|
||||
|
|
@ -128,7 +128,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
|
||||
/* check if the recovered blocks are OK */
|
||||
for(j=0;j<1;++j) {
|
||||
if (block_has_hash(failed[failed_map[j]].block)) { /* if the block can be checked */
|
||||
if (block_has_updated_hash(failed[failed_map[j]].block)) { /* if the block can be checked */
|
||||
hash_checked = 1;
|
||||
if (blockcmp(state, rehash, failed[failed_map[j]].block, buffer[failed[failed_map[j]].index], buffer_zero) != 0)
|
||||
break;
|
||||
|
|
@ -158,7 +158,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
|
||||
/* check if the recovered blocks are OK */
|
||||
for(j=0;j<1;++j) {
|
||||
if (block_has_hash(failed[failed_map[j]].block)) { /* if the block can be checked */
|
||||
if (block_has_updated_hash(failed[failed_map[j]].block)) { /* if the block can be checked */
|
||||
hash_checked = 1;
|
||||
if (blockcmp(state, rehash, failed[failed_map[j]].block, buffer[failed[failed_map[j]].index], buffer_zero) != 0)
|
||||
break;
|
||||
|
|
@ -208,7 +208,7 @@ static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, u
|
|||
|
||||
/* check if the recovered blocks are OK */
|
||||
for(j=0;j<2;++j) {
|
||||
if (block_has_hash(failed[failed_map[j]].block)) { /* if the block can be checked */
|
||||
if (block_has_updated_hash(failed[failed_map[j]].block)) { /* if the block can be checked */
|
||||
hash_checked = 1;
|
||||
if (blockcmp(state, rehash, failed[failed_map[j]].block, buffer[failed[failed_map[j]].index], buffer_zero) != 0)
|
||||
break;
|
||||
|
|
|
|||
2
dup.c
2
dup.c
|
|
@ -52,7 +52,7 @@ struct snapraid_hash* hash_alloc(struct snapraid_state* state, struct snapraid_d
|
|||
for(i=0;i<file->blockmax;++i) {
|
||||
memcpy(buf + i * HASH_SIZE, file->blockvec[i].hash, HASH_SIZE);
|
||||
|
||||
if (!block_has_hash(&file->blockvec[i])) {
|
||||
if (!block_has_updated_hash(&file->blockvec[i])) {
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
45
elem.h
45
elem.h
|
|
@ -89,10 +89,12 @@ struct snapraid_filter {
|
|||
* The block is new and not yet hashed, and it's using the space of a block not existing anymore.
|
||||
* This happens when a new block overwrite a just removed block.
|
||||
*
|
||||
* The block hash field IS set, and it represents the hash of the previous data.
|
||||
* The block hash field IS set, and it represents the hash of the previous data,
|
||||
* but only if it's different by all 0.
|
||||
* The parity for this disk is not updated, but it contains the old data referenced by the hash.
|
||||
*
|
||||
* If the hash is completely filled with 0, it means that its lost.
|
||||
* If the hash is completely filled with 0, it means that the hash is lost.
|
||||
* This could happen if a NEW block is converted to a CHG one in an interrupted sync.
|
||||
*/
|
||||
#define BLOCK_STATE_CHG 3
|
||||
|
||||
|
|
@ -100,12 +102,12 @@ struct snapraid_filter {
|
|||
* This block is a deleted one.
|
||||
* This happens when a file is deleted.
|
||||
*
|
||||
* The block hash field IS set, and it represents the hash of the previous data, but only
|
||||
* if it's different by all 0.
|
||||
* The block hash field IS set, and it represents the hash of the previous data,
|
||||
* but only if it's different by all 0.
|
||||
* The parity for this disk is not updated, but it contains the old data referenced by the hash.
|
||||
*
|
||||
* If the hash is completely filled with 0, it means that the hash is lost.
|
||||
* This could happen if a NEW block is deleted in an interrupted sync.
|
||||
* This could happen if a NEW block is DELETED in an interrupted sync.
|
||||
*/
|
||||
#define BLOCK_STATE_DELETED 4
|
||||
|
||||
|
|
@ -435,17 +437,44 @@ static inline void block_state_set(struct snapraid_block* block, unsigned state)
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified block has a valid and updated hash.
|
||||
* Checks if the specified block is valid and has an updated hash.
|
||||
*
|
||||
* Note that EMPTY return 0.
|
||||
* Note that EMPTY / CHG / NEW / DELETED return 0.
|
||||
*/
|
||||
static inline int block_has_hash(const struct snapraid_block* block)
|
||||
static inline int block_has_updated_hash(const struct snapraid_block* block)
|
||||
{
|
||||
unsigned state = block_state_get(block);
|
||||
|
||||
return state == BLOCK_STATE_BLK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified block has any kind of hash.
|
||||
* Even a not updated one.
|
||||
*
|
||||
* Note that for DELETED / CHG with a NULL hash returns 0,
|
||||
* because in these cases the hash is lost.
|
||||
*/
|
||||
static inline int block_has_any_hash(const struct snapraid_block* block)
|
||||
{
|
||||
unsigned block_state = block_state_get(block);
|
||||
unsigned i;
|
||||
|
||||
switch (block_state) {
|
||||
case BLOCK_STATE_BLK :
|
||||
return 1;
|
||||
case BLOCK_STATE_CHG :
|
||||
case BLOCK_STATE_DELETED :
|
||||
/* the hash is valid only if different than 0 */
|
||||
for(i=0;i<HASH_SIZE;++i)
|
||||
if (block->hash[i] != 0)
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified block is part of a file.
|
||||
*
|
||||
|
|
|
|||
2
scrub.c
2
scrub.c
|
|
@ -266,7 +266,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
|||
memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
|
||||
}
|
||||
|
||||
if (block_has_hash(block)) {
|
||||
if (block_has_updated_hash(block)) {
|
||||
/* compare the hash */
|
||||
if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
|
||||
fprintf(stdlog, "error:%u:%s:%s: Data error at position %u\n", i, handle[j].disk->name, block_file_get(block)->sub, block_file_pos(block));
|
||||
|
|
|
|||
25
state.c
25
state.c
|
|
@ -826,30 +826,17 @@ static void state_content_check(struct snapraid_state* state, const char* path)
|
|||
* and has a hash value.
|
||||
* Note that we include DELETED blocks, but only if they have a not NULL hash.
|
||||
*/
|
||||
static int position_has_hash(struct snapraid_state* state, block_off_t pos)
|
||||
static int position_has_any_hash(struct snapraid_state* state, block_off_t pos)
|
||||
{
|
||||
tommy_node* i;
|
||||
unsigned j;
|
||||
|
||||
/* check for each disk if block is really used */
|
||||
for(i=state->disklist;i!=0;i=i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
struct snapraid_block* block = disk_block_get(disk, pos);
|
||||
|
||||
unsigned block_state = block_state_get(block);
|
||||
|
||||
switch (block_state) {
|
||||
case BLOCK_STATE_BLK :
|
||||
case BLOCK_STATE_CHG :
|
||||
if (block_has_any_hash(block))
|
||||
return 1;
|
||||
case BLOCK_STATE_DELETED :
|
||||
for(j=0;j<HASH_SIZE;++j)
|
||||
if (block->hash[j] != 0)
|
||||
break;
|
||||
if (j != HASH_SIZE)
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1660,7 +1647,7 @@ static void state_write_text(struct snapraid_state* state, STREAM* f)
|
|||
info_has_rehash = 0; /* if there is a rehash info */
|
||||
for(b=0;b<blockmax;++b) {
|
||||
/* if the position is used */
|
||||
if (position_has_hash(state, b)) {
|
||||
if (position_has_any_hash(state, b)) {
|
||||
snapraid_info info = info_get(&state->infoarr, b);
|
||||
|
||||
/* only if there is some info to store */
|
||||
|
|
@ -1898,7 +1885,7 @@ static void state_write_text(struct snapraid_state* state, STREAM* f)
|
|||
/* write the info for each block */
|
||||
for(b=0;b<blockmax;++b) {
|
||||
/* if the position is used */
|
||||
if (position_has_hash(state, b)) {
|
||||
if (position_has_any_hash(state, b)) {
|
||||
snapraid_info info = info_get(&state->infoarr, b);
|
||||
|
||||
/* save only stuffs different than 0 */
|
||||
|
|
@ -2280,7 +2267,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST
|
|||
info_set(&state->infoarr, v_pos, info);
|
||||
|
||||
/* ensure that an info is present only for used positions */
|
||||
if (position_has_hash(state, v_pos)) {
|
||||
if (position_has_any_hash(state, v_pos)) {
|
||||
if (!info) {
|
||||
decoding_error(path, f);
|
||||
fprintf(stderr, "Internal incosistency for missing info!\n");
|
||||
|
|
@ -2701,7 +2688,7 @@ static void state_write_binary(struct snapraid_state* state, STREAM* f)
|
|||
info_has_rehash = 0; /* if there is a rehash info */
|
||||
for(b=0;b<blockmax;++b) {
|
||||
/* if the position is used */
|
||||
if (position_has_hash(state, b)) {
|
||||
if (position_has_any_hash(state, b)) {
|
||||
snapraid_info info = info_get(&state->infoarr, b);
|
||||
|
||||
/* only if there is some info to store */
|
||||
|
|
|
|||
2
sync.c
2
sync.c
|
|
@ -280,7 +280,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
memhash(state->hash, state->hashseed, hash, buffer[j], read_size);
|
||||
}
|
||||
|
||||
if (block_has_hash(block)) {
|
||||
if (block_has_updated_hash(block)) {
|
||||
/* compare the hash */
|
||||
if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
|
||||
fprintf(stderr, "Data error in file '%s' at position '%u'\n", handle[j].path, block_file_pos(block));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue