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

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