From 46fb4a311a3248acc02b2a8c171b2030aaff879d Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Sat, 11 Jun 2011 12:05:02 +0200 Subject: [PATCH] More precise error listing for unrecoverable files. The "Stopping" message is now always in stdout. --- TODO | 6 +++++- check.c | 58 +++++++++++++++++++++++++++++---------------------------- sync.c | 18 +++++++++--------- 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/TODO b/TODO index a5ae1fe1..4dcc963c 100644 --- a/TODO +++ b/TODO @@ -19,7 +19,11 @@ messages in check/fix. * Easy way to find files using a specified block. -* Implements a restore command to recover files, without the integrity check. +* Implements an undelete command to recover missing files, without the +integrity check of the existing ones. + +* Rename sync->backup and fix->restore. It seems to me a naming expressing +better the meaning of the commands. But not yet sure. * Allow to filter the files to check/fix based on the drive where they reside. diff --git a/check.c b/check.c index 5428a781..044c142f 100644 --- a/check.c +++ b/check.c @@ -173,6 +173,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity unsigned error; unsigned unrecoverable_error; unsigned recovered_error; + struct failed_struct* failed; /* we need disk + 2 for each parity level buffers + 1 zero buffer */ buffermax = diskmax + state->level * 2 + 1; @@ -184,6 +185,8 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity } memset(buffer[buffermax-1], 0, state->block_size); + failed = malloc_nofail(diskmax * sizeof(struct failed_struct)); + handle = malloc_nofail(diskmax * sizeof(struct snapraid_handle)); for(i=0;idiskarr, i); @@ -224,7 +227,6 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity start = time(0); last = start; for(i=blockstart;isub, block_file_pos(block)); @@ -333,6 +333,7 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity fprintf(stderr, "File '%s' is larger than expected.\n", handle[j].path); /* if fragmented, it may be reopened, so store the notification */ + /* to prevent to signal and count the error more than one time */ file_flag_set(block_file_get(block), FILE_IS_LARGER); /* this is always a recoverable error */ @@ -342,12 +343,10 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity read_size = handle_read(&handle[j], block, buffer[j], state->block_size); if (read_size == -1) { - /* save the failed block for the parity check */ - if (failed_count < 2) { - failed[failed_count].index = j; - failed[failed_count].block = block; - failed[failed_count].handle = &handle[j]; - } + /* save the failed block for the check/fix */ + failed[failed_count].index = j; + failed[failed_count].block = block; + failed[failed_count].handle = &handle[j]; ++failed_count; fprintf(stderr, "%u: Read error for file %s at position %u\n", i, block_file_get(block)->sub, block_file_pos(block)); @@ -360,12 +359,10 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity /* compare the hash */ if (memcmp(hash, block->hash, HASH_SIZE) != 0) { - /* save the failed block for the parity check */ - if (failed_count < 2) { - failed[failed_count].index = j; - failed[failed_count].block = block; - failed[failed_count].handle = &handle[j]; - } + /* save the failed block for the check/fix */ + failed[failed_count].index = j; + failed[failed_count].block = block; + failed[failed_count].handle = &handle[j]; ++failed_count; fprintf(stderr, "%u: Data error for file %s at position %u\n", i, block_file_get(block)->sub, block_file_pos(block)); @@ -420,8 +417,12 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity if (ret > 0) error += ret; - fprintf(stderr, "%u: UNRECOVERABLE error for this block\n", i); ++unrecoverable_error; + + /* print a list of all the errors in files */ + for(j=0;jsub, block_file_pos(failed[j].block)); + } } else { /* check parity and q-parity only if all the blocks have it computed */ /* if you check/fix after a partial sync, it's OK to have parity errors on the blocks with invalid parity */ @@ -457,10 +458,10 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity if (errno == EACCES) { fprintf(stderr, "WARNING! Please give write permission to the file.\n"); } else { - /* we do not use DANGER because for ENOSPC which is not always correctly reported */ + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ fprintf(stderr, "WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); } - fprintf(stderr, "Stopping at block %u\n", i); + printf("Stopping at block %u\n", i); ++unrecoverable_error; goto bail; } @@ -477,9 +478,9 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity if (buffer_parity == 0 && parity_f != -1) { ret = parity_write(state->parity, parity_f, i, buffer[diskmax], state->block_size); if (ret == -1) { - /* we do not use DANGER because for ENOSPC which is not always correctly reported */ + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ fprintf(stderr, "WARNING! Without a working Parity disk, it isn't possible to fix errors on it.\n"); - fprintf(stderr, "Stopping at block %u\n", i); + printf("Stopping at block %u\n", i); ++unrecoverable_error; goto bail; } @@ -493,9 +494,9 @@ static int state_check_process(struct snapraid_state* state, int fix, int parity if (buffer_qarity == 0 && qarity_f != -1) { ret = parity_write(state->qarity, qarity_f, i, buffer[diskmax + 1], state->block_size); if (ret == -1) { - /* we do not use DANGER because for ENOSPC which is not always correctly reported */ + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ fprintf(stderr, "WARNING! Without a working Q-Parity disk, it isn't possible to fix errors on it.\n"); - fprintf(stderr, "Stopping at block %u\n", i); + printf("Stopping at block %u\n", i); ++unrecoverable_error; goto bail; } @@ -552,6 +553,7 @@ bail: printf("No error\n"); } + free(failed); free(handle); free(buffer_alloc); free(buffer); diff --git a/sync.c b/sync.c index f66f1bfc..25b2a754 100644 --- a/sync.c +++ b/sync.c @@ -124,7 +124,7 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa /* This one is really an unexpected error, because we are only reading */ /* and closing a descriptor should never fail */ fprintf(stderr, "DANGER! Unexpected close error in a data disk, it isn't possible to sync.\n"); - fprintf(stderr, "Stopping at block %u\n", i); + printf("Stopping at block %u\n", i); ++unrecoverable_error; goto bail; } @@ -134,14 +134,14 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa if (errno == ENOENT) { fprintf(stderr, "Missing file '%s'.\n", handle[j].path); fprintf(stderr, "WARNING! You cannot modify data disk during a sync. Rerun the sync command when finished.\n"); - fprintf(stderr, "Stopping at block %u\n", i); + printf("Stopping at block %u\n", i); } else if (errno == EACCES) { fprintf(stderr, "No access at file '%s'.\n", handle[j].path); fprintf(stderr, "WARNING! Please fix the access permission in the data disk.\n"); - fprintf(stderr, "Stopping at block %u\n", i); + printf("Stopping at block %u\n", i); } else { fprintf(stderr, "DANGER! Unexpected open error in a data disk, it isn't possible to sync.\n"); - fprintf(stderr, "Stopping to allow recovery. Try with 'snapraid check'\n"); + printf("Stopping to allow recovery. Try with 'snapraid check'\n"); } ++unrecoverable_error; goto bail; @@ -159,7 +159,7 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa else fprintf(stderr, "Unexpected inode change from %"PRIu64" to %"PRIu64" at file '%s'.\n", block_file_get(block)->inode, handle[j].st.st_ino, handle[j].path); fprintf(stderr, "WARNING! You cannot modify files during a sync. Rerun the sync command when finished.\n"); - fprintf(stderr, "Stopping at block %u\n", i); + printf("Stopping at block %u\n", i); ++unrecoverable_error; goto bail; } @@ -167,7 +167,7 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa read_size = handle_read(&handle[j], block, buffer[j], state->block_size); if (read_size == -1) { fprintf(stderr, "DANGER! Unexpected read error in a data disk, it isn't possible to sync.\n"); - fprintf(stderr, "Stopping to allow recovery. Try with 'snapraid check'\n"); + printf("Stopping to allow recovery. Try with 'snapraid check'\n"); ++unrecoverable_error; goto bail; } @@ -180,7 +180,7 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa 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)); fprintf(stderr, "DANGER! Unexpected data error in a data disk, it isn't possible to sync.\n"); - fprintf(stderr, "Stopping to allow recovery. Try with 'snapraid -s %u check'\n", i); + printf("Stopping to allow recovery. Try with 'snapraid -s %u check'\n", i); ++unrecoverable_error; goto bail; } @@ -200,7 +200,7 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa ret = parity_write(state->parity, parity_f, i, buffer[diskmax], state->block_size); if (ret == -1) { fprintf(stderr, "DANGER! Write error in the Parity disk, it isn't possible to sync.\n"); - fprintf(stderr, "Stopping at block %u\n", i); + printf("Stopping at block %u\n", i); ++unrecoverable_error; goto bail; } @@ -210,7 +210,7 @@ static int state_sync_process(struct snapraid_state* state, int parity_f, int qa ret = parity_write(state->qarity, qarity_f, i, buffer[diskmax+1], state->block_size); if (ret == -1) { fprintf(stderr, "DANGER! Write error in the Q-Parity disk, it isn't possible to sync.\n"); - fprintf(stderr, "Stopping at block %u\n", i); + printf("Stopping at block %u\n", i); ++unrecoverable_error; goto bail; }