From bc4d2dc3f64d36cfbae6c7acaba62153371e47b4 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Sun, 7 Dec 2014 00:07:36 +0100 Subject: [PATCH] Keeps track of IO errors in scrub like we do for silent errors. --- HISTORY | 6 ++++++ TODO | 4 ++++ cmdline/scrub.c | 45 ++++++++++++++++++++++++++++++++------------- cmdline/sync.c | 6 +++--- snapraid.1 | 14 +++++++++----- snapraid.d | 14 +++++++++----- snapraid.txt | 14 +++++++++----- 7 files changed, 72 insertions(+), 31 deletions(-) diff --git a/HISTORY b/HISTORY index 64bcd2d9..1e795a74 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,12 @@ SnapRAID HISTORY ================ +7.1 2014/12 (BETA) +================== + * In 'scrub' keeps track of Input/Output errors like for silent + error to show them in the 'status' report, and to allow to + use the -e, --filter-error filter in 'check' and 'fix'. + 7.0 2014/11 =========== * In 'check' and 'fix' the array is scanned to find any moved files diff --git a/TODO b/TODO index ae91fd88..5a98602d 100644 --- a/TODO +++ b/TODO @@ -5,6 +5,10 @@ This is the list of TODO items for SnapRAID. - Next +* copy report in diff is wrong. +If "copy" is printed, avoid to print "add" and "remove". +Now with "copy" we don't count add, but we cound "remove". + * Avoid to do optimized move operation if more files with same timestamp/size are present. diff --git a/cmdline/scrub.c b/cmdline/scrub.c index 19b1825b..5afe7ec6 100644 --- a/cmdline/scrub.c +++ b/cmdline/scrub.c @@ -56,6 +56,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par int ret; unsigned error; unsigned silent_error; + unsigned io_error; unsigned l; /* maps the disks to handles */ @@ -73,6 +74,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par error = 0; silent_error = 0; + io_error = 0; /* first count the number of blocks to process */ countmax = 0; @@ -139,6 +141,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par snapraid_info info; int error_on_this_block; int silent_error_on_this_block; + int io_error_on_this_block; int block_is_unsynced; int rehash; @@ -185,6 +188,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par /* by default process the block, and skip it if something goes wrong */ error_on_this_block = 0; silent_error_on_this_block = 0; + io_error_on_this_block = 0; /* if all the blocks at this address are synced */ /* if not, parity is not even checked */ @@ -282,9 +286,15 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par read_size = handle_read(&handle[j], block, buffer[j], state->block_size, stderr); if (read_size == -1) { - fprintf(stdlog, "error:%u:%s:%s: Read error at position %u\n", i, disk->name, handle[j].file->sub, block_file_pos(block)); - ++error; - error_on_this_block = 1; + if (errno == EIO) { + fprintf(stdlog, "error:%u:%s:%s: Input/Output error at position %u. %s\n", i, disk->name, handle[j].file->sub, block_file_pos(block), strerror(errno)); + ++io_error; + io_error_on_this_block = 1; + } else { + fprintf(stdlog, "error:%u:%s:%s: Read error at position %u. %s\n", i, disk->name, handle[j].file->sub, block_file_pos(block), strerror(errno)); + ++error; + error_on_this_block = 1; + } continue; } @@ -327,7 +337,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par } /* if we have read all the data required and it's correct, proceed with the parity check */ - if (!error_on_this_block && !silent_error_on_this_block) { + if (!error_on_this_block && !silent_error_on_this_block && !io_error_on_this_block) { unsigned char* buffer_recov[LEV_MAX]; /* until now is CPU */ @@ -344,9 +354,16 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, stdlog); if (ret == -1) { buffer_recov[l] = 0; - fprintf(stdlog, "parity_error:%u:%s: Read error\n", i, lev_config_name(l)); - ++error; - error_on_this_block = 1; + + if (errno == EIO) { + fprintf(stdlog, "parity_error:%u:%s: Input/Output error. %s\n", i, lev_config_name(l), strerror(errno)); + ++io_error; + io_error_on_this_block = 1; + } else { + fprintf(stdlog, "parity_error:%u:%s: Read error. %s\n", i, lev_config_name(l), strerror(errno)); + ++error; + error_on_this_block = 1; + } /* follow */ } @@ -379,7 +396,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par } } - if (silent_error_on_this_block) { + if (silent_error_on_this_block || io_error_on_this_block) { /* set the error status keeping the existing time and hash */ info_set(&state->infoarr, i, info_set_bad(info)); } else if (error_on_this_block) { @@ -439,9 +456,10 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par state_usage_print(state); - if (error || silent_error) { + if (error || silent_error || io_error) { printf("\n"); - printf("%8u read errors\n", error); + printf("%8u other errors\n", error); + printf("%8u io errors\n", io_error); printf("%8u data errors\n", silent_error); printf("WARNING! There are errors!\n"); } else { @@ -450,7 +468,8 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par printf("Everything OK\n"); } - fprintf(stdlog, "summary:error_read:%u\n", error); + fprintf(stdlog, "summary:error_other:%u\n", error); + fprintf(stdlog, "summary:error_io:%u\n", io_error); fprintf(stdlog, "summary:error_data:%u\n", silent_error); if (error + silent_error == 0) fprintf(stdlog, "summary:exit:ok\n"); @@ -476,10 +495,10 @@ bail: free(rehandle_alloc); if (state->opt.expect_recoverable) { - if (error + silent_error == 0) + if (error + silent_error + io_error == 0) return -1; } else { - if (error + silent_error != 0) + if (error + silent_error + io_error != 0) return -1; } return 0; diff --git a/cmdline/sync.c b/cmdline/sync.c index d8aa1f12..ac2b15ca 100644 --- a/cmdline/sync.c +++ b/cmdline/sync.c @@ -145,7 +145,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta /* file we are processing for error reporting */ struct snapraid_file* file = block_file_get(block); if (errno == ENOENT) { - fprintf(stdlog, "error:%u:%s:%s: Open missing error\n", i, disk->name, file->sub); + fprintf(stdlog, "error:%u:%s:%s: Open missing error. %s\n", i, disk->name, file->sub, strerror(errno)); fprintf(stderr, "Missing file '%s'.\n", handle[j].path); fprintf(stderr, "WARNING! You cannot modify data disk during a sync.\n"); fprintf(stderr, "Rerun the sync command when finished.\n"); @@ -157,7 +157,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta continue; } if (errno == EACCES) { - fprintf(stdlog, "error:%u:%s:%s: Open access error\n", i, disk->name, file->sub); + fprintf(stdlog, "error:%u:%s:%s: Open access error. %s\n", i, disk->name, file->sub, strerror(errno)); 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, "Rerun the sync command when finished.\n"); @@ -211,7 +211,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta /* LCOV_EXCL_START */ /* file we are processing for error reporting */ struct snapraid_file* file = block_file_get(block); - fprintf(stdlog, "error:%u:%s:%s: Read error at position %u\n", i, disk->name, file->sub, block_file_pos(block)); + fprintf(stdlog, "error:%u:%s:%s: Read error at position %u. %s\n", i, disk->name, file->sub, block_file_pos(block), strerror(errno)); fprintf(stderr, "DANGER! Unexpected read error in a data disk, it isn't possible to sync.\n"); fprintf(stderr, "Ensure that disk '%s' is sane and that file '%s' can be read.\n", disk->dir, handle[j].path); printf("Stopping to allow recovery. Try with 'snapraid check -f %s'\n", file->sub); diff --git a/snapraid.1 b/snapraid.1 index 2748aeca..87a770c6 100644 --- a/snapraid.1 +++ b/snapraid.1 @@ -319,7 +319,7 @@ snapraid scrub .PP This command verifies only the oldest data in your array. Every run of the command checks about 12% of the array, -but nothing newer than 10 days. +but not newer than 10 days. You can use the \-p, \-\-percentage option to specify a different amount, and the \-o, \-\-older\-than option to specify a different age in days. For example, to check 5% of the array older than 20 days use: @@ -331,8 +331,8 @@ snapraid \-p 5 \-o 20 scrub .PD .RE .PP -If silent errors are found, the corresponding blocks are marked as bad -in the \[dq]content\[dq] file, and listed in the \[dq]status\[dq] command. +If a silent or input error is found, the corresponding block is marked +as bad in the \[dq]content\[dq] file, and listed in the \[dq]status\[dq] command. .PP .RS 4 snapraid status @@ -341,8 +341,8 @@ snapraid status .PD .RE .PP -To fix them, you can use the \[dq]fix\[dq] command filtering for files -containing bad blocks: +To fix them, you can use the \[dq]fix\[dq] command filtering for files containing +bad blocks: .PP .RS 4 snapraid \-e fix @@ -361,6 +361,10 @@ snapraid \-p 0 scrub .PP .PD .RE +.PP +Take care that running scrub on a not synced array may result in +errors caused by removed or modified files. These errors are reported +in the \[dq]scrub\[dq] result, but related blocks are not marked as bad. .SS Pooling To have all the files in your array shown in the same directory tree, you can enable \[dq]pooling\[dq], that consists in creating a virtual view of all diff --git a/snapraid.d b/snapraid.d index b0ddb233..51d0c0bf 100644 --- a/snapraid.d +++ b/snapraid.d @@ -179,20 +179,20 @@ Getting Started This command verifies only the oldest data in your array. Every run of the command checks about 12% of the array, - but nothing newer than 10 days. + but not newer than 10 days. You can use the -p, --percentage option to specify a different amount, and the -o, --older-than option to specify a different age in days. For example, to check 5% of the array older than 20 days use: :snapraid -p 5 -o 20 scrub - If silent errors are found, the corresponding blocks are marked as bad - in the "content" file, and listed in the "status" command. + If a silent or input error is found, the corresponding block is marked + as bad in the "content" file, and listed in the "status" command. :snapraid status - To fix them, you can use the "fix" command filtering for files - containing bad blocks: + To fix them, you can use the "fix" command filtering for files containing + bad blocks: :snapraid -e fix @@ -202,6 +202,10 @@ Getting Started :snapraid -p 0 scrub + Take care that running scrub on a not synced array may result in + errors caused by removed or modified files. These errors are reported + in the "scrub" result, but related blocks are not marked as bad. + Pooling To have all the files in your array shown in the same directory tree, you can enable "pooling", that consists in creating a virtual view of all diff --git a/snapraid.txt b/snapraid.txt index f4a42fcf..316b9b65 100644 --- a/snapraid.txt +++ b/snapraid.txt @@ -196,20 +196,20 @@ run the "scrub" command. This command verifies only the oldest data in your array. Every run of the command checks about 12% of the array, -but nothing newer than 10 days. +but not newer than 10 days. You can use the -p, --percentage option to specify a different amount, and the -o, --older-than option to specify a different age in days. For example, to check 5% of the array older than 20 days use: snapraid -p 5 -o 20 scrub -If silent errors are found, the corresponding blocks are marked as bad -in the "content" file, and listed in the "status" command. +If a silent or input error is found, the corresponding block is marked +as bad in the "content" file, and listed in the "status" command. snapraid status -To fix them, you can use the "fix" command filtering for files -containing bad blocks: +To fix them, you can use the "fix" command filtering for files containing +bad blocks: snapraid -e fix @@ -219,6 +219,10 @@ marked as bad. snapraid -p 0 scrub +Take care that running scrub on a not synced array may result in +errors caused by removed or modified files. These errors are reported +in the "scrub" result, but related blocks are not marked as bad. + 4.3 Pooling -----------