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:
Andrea Mazzoleni 2013-08-21 22:24:12 +02:00
parent 9ad388724e
commit e0afd0edf7
6 changed files with 50 additions and 34 deletions

View file

@ -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
View file

@ -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
View file

@ -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.
*

View file

@ -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
View file

@ -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
View file

@ -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));