mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Improves recovering after an aborted sync.
This commit is contained in:
parent
f14ab1aa3b
commit
55fae37e7f
13 changed files with 758 additions and 137 deletions
70
sync.c
70
sync.c
|
|
@ -65,10 +65,12 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* for each disk */
|
||||
one_invalid = 0;
|
||||
for(j=0;j<diskmax;++j) {
|
||||
struct snapraid_block* block = 0;
|
||||
struct snapraid_block* block = BLOCK_EMPTY;
|
||||
if (handle[j].disk)
|
||||
block = disk_block_get(handle[j].disk, i);
|
||||
if (block && !block_flag_has(block, BLOCK_HAS_HASH | BLOCK_HAS_PARITY)) {
|
||||
if (block_is_valid(block)
|
||||
&& block_state_get(block) != BLOCK_STATE_BLK
|
||||
) {
|
||||
one_invalid = 1;
|
||||
break;
|
||||
}
|
||||
|
|
@ -92,18 +94,36 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* for each disk */
|
||||
one_invalid = 0;
|
||||
for(j=0;j<diskmax;++j) {
|
||||
struct snapraid_block* block = 0;
|
||||
struct snapraid_block* block = BLOCK_EMPTY;
|
||||
if (handle[j].disk)
|
||||
block = disk_block_get(handle[j].disk, i);
|
||||
if (block && !block_flag_has(block, BLOCK_HAS_HASH | BLOCK_HAS_PARITY)) {
|
||||
if (block_is_valid(block)
|
||||
&& block_state_get(block) != BLOCK_STATE_BLK
|
||||
) {
|
||||
one_invalid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if no invalid block skip */
|
||||
if (!one_invalid)
|
||||
if (!one_invalid) {
|
||||
/* cleanup all the deleted blocks */
|
||||
for(j=0;j<diskmax;++j) {
|
||||
struct snapraid_block* block = BLOCK_EMPTY;
|
||||
if (handle[j].disk)
|
||||
block = disk_block_get(handle[j].disk, i);
|
||||
if (block == BLOCK_DELETED) {
|
||||
/* set it to empty */
|
||||
tommy_array_set(&handle[j].disk->blockarr, i, BLOCK_EMPTY);
|
||||
|
||||
/* mark the state as needing write */
|
||||
state->need_write = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* by default process the block, and skip it if something go wrong */
|
||||
skip_this_block = 0;
|
||||
|
|
@ -123,7 +143,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
|
||||
/* if the disk block is not used */
|
||||
block = disk_block_get(handle[j].disk, i);
|
||||
if (!block) {
|
||||
if (!block_is_valid(block)) {
|
||||
/* use an empty block */
|
||||
memset(buffer[j], 0, state->block_size);
|
||||
continue;
|
||||
|
|
@ -196,10 +216,12 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
goto bail;
|
||||
}
|
||||
|
||||
countsize += read_size;
|
||||
|
||||
/* now compute the hash */
|
||||
memhash(state->hash, hash, buffer[j], read_size);
|
||||
|
||||
if (block_flag_has(block, BLOCK_HAS_HASH)) {
|
||||
if (block_has_hash(block)) {
|
||||
/* compare the hash */
|
||||
if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
|
||||
fprintf(stderr, "%u: Data error for file %s at position %u\n", i, block_file_get(block)->sub, block_file_pos(block));
|
||||
|
|
@ -213,8 +235,6 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* this allow on error to do not save the failed computation */
|
||||
memcpy(block->hash, hash, HASH_SIZE);
|
||||
}
|
||||
|
||||
countsize += read_size;
|
||||
}
|
||||
|
||||
/* if we have read all the data required, proceed with the parity */
|
||||
|
|
@ -245,14 +265,23 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
|
||||
/* for each disk, mark the blocks as processed */
|
||||
for(j=0;j<diskmax;++j) {
|
||||
struct snapraid_block* block = 0;
|
||||
struct snapraid_block* block = BLOCK_EMPTY;
|
||||
if (handle[j].disk)
|
||||
block = disk_block_get(handle[j].disk, i);
|
||||
if (!block)
|
||||
|
||||
if (block == BLOCK_EMPTY) {
|
||||
/* nothing to do */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (block == BLOCK_DELETED) {
|
||||
/* the parity is not updated without this block, so it's now empty */
|
||||
tommy_array_set(&handle[j].disk->blockarr, i, BLOCK_EMPTY);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* now all the blocks have the hash and the parity computed */
|
||||
block_flag_set(block, BLOCK_HAS_HASH | BLOCK_HAS_PARITY);
|
||||
block_state_set(block, BLOCK_STATE_BLK);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -293,6 +322,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
|
|||
{
|
||||
block_off_t blockmax;
|
||||
data_off_t size;
|
||||
tommy_node* i;
|
||||
int ret;
|
||||
struct snapraid_parity parity;
|
||||
struct snapraid_parity qarity;
|
||||
|
|
@ -305,6 +335,22 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
|
|||
blockmax = parity_resize(state);
|
||||
size = blockmax * (data_off_t)state->block_size;
|
||||
|
||||
/* remove all the deleted blocks over the upper limit */
|
||||
for(i=state->disklist;i!=0;i=i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
block_off_t diskblockmax = tommy_array_size(&disk->blockarr);
|
||||
block_off_t block;
|
||||
|
||||
for(block=blockmax;block<diskblockmax;++block) {
|
||||
if (tommy_array_get(&disk->blockarr, block) == BLOCK_DELETED) {
|
||||
tommy_array_set(&disk->blockarr, block, BLOCK_EMPTY);
|
||||
|
||||
/* mark the state as needing write */
|
||||
state->need_write = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blockstart > blockmax) {
|
||||
fprintf(stderr, "Error in the starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue