Keeps track of IO errors in scrub like we do for silent errors.

This commit is contained in:
Andrea Mazzoleni 2014-12-07 00:07:36 +01:00
parent f200a1f6b8
commit bc4d2dc3f6
7 changed files with 72 additions and 31 deletions

View file

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

4
TODO
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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