Review all the error messages

This commit is contained in:
Andrea Mazzoleni 2026-01-24 19:19:11 +01:00
parent f64d582960
commit caf9cd3961
6 changed files with 444 additions and 320 deletions

View file

@ -31,6 +31,27 @@
/****************************************************************************/
/* check */
static const char* es(int err)
{
if (err == EIO)
return "error_io";
else
return "error";
}
static void log_fatal_errno(int err, const char* name)
{
if (err == EIO) {
log_fatal("DANGER! Unexpected input/output error in disk %s. It isn't possible to continue.\n", name);
} else if (err == EACCES) {
log_fatal("WARNING! Grant permission in the disk %s. It isn't possible to continue.\n", name);
} else if (err == ENOSPC) {
log_fatal("WARNING! Ensure there is free space on the disk %s. It isn't possible to continue.\n", name);
} else {
log_fatal("WARNING! Without a working %s disk, it isn't possible to continue.\n", name);
}
}
/**
* A block that failed the hash check, or that was deleted.
*/
@ -660,8 +681,8 @@ static int file_post(struct snapraid_state* state, int fix, unsigned i, struct s
ret = handle_close(&handle[j]);
if (ret != 0) {
/* LCOV_EXCL_START */
log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected close error in a data disk.\n");
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
return -1;
/* LCOV_EXCL_STOP */
}
@ -670,8 +691,9 @@ static int file_post(struct snapraid_state* state, int fix, unsigned i, struct s
ret = rename(path, path_to);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error renaming '%s' to '%s'. %s.\n", path, path_to, strerror(errno));
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
log_fatal("Error renaming '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno));
log_tag("%s:%u:%s:%s: Rename error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
return -1;
/* LCOV_EXCL_STOP */
}
@ -692,23 +714,24 @@ static int file_post(struct snapraid_state* state, int fix, unsigned i, struct s
/* if the file is closed or different than the one expected, reopen it */
/* a different open file could happen when filtering for bad blocks */
if (handle[j].file != file) {
/* close a potential different file */
/* keep a pointer at the file we are going to close for error reporting */
struct snapraid_file* report = handle[j].file;
ret = handle_close(&handle[j]);
if (ret != 0) {
/* LCOV_EXCL_START */
log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(handle[j].file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected close error in a data disk.\n");
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
return -1;
/* LCOV_EXCL_STOP */
}
/* reopen it as readonly, as to set the mtime readonly access it's enough */
/* we know that the file exists because it has the FILE_IS_FIXED tag */
ret = handle_open(&handle[j], file, state->file_mode, log_error, 0);
ret = handle_open(&handle[j], file, state->file_mode, log_error, log_error); /* output a message for missing files */
if (ret != 0) {
/* LCOV_EXCL_START */
log_tag("error:%u:%s:%s: Open error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
log_tag("%s:%u:%s:%s: Open error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
return -1;
/* LCOV_EXCL_STOP */
}
@ -740,9 +763,11 @@ static int file_post(struct snapraid_state* state, int fix, unsigned i, struct s
ret = handle_utime(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Time error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
/* mark the file as damaged */
file_flag_set(file, FILE_IS_DAMAGED);
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
return -1;
/* LCOV_EXCL_STOP */
}
@ -782,8 +807,8 @@ close_and_continue:
ret = handle_close(&handle[j]);
if (ret != 0) {
/* LCOV_EXCL_START */
log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected close error in a data disk.\n");
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
return -1;
/* LCOV_EXCL_STOP */
}
@ -1049,13 +1074,15 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
/* if the file is closed or different than the current one */
if (handle[j].file == 0 || handle[j].file != file) {
/* close the old one, if any */
/* keep a pointer at the file we are going to close for error reporting */
struct snapraid_file* report = handle[j].file;
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(handle[j].file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected close error in a data disk.\n");
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1067,12 +1094,10 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = handle_create(&handle[j], file, state->file_mode);
if (ret == -1) {
/* LCOV_EXCL_START */
if (errno == EACCES) {
log_fatal("WARNING! Please give write permission to the file.\n");
} else {
log_fatal("DANGER! Without a working data disk, it isn't possible to fix errors on it.\n");
}
log_tag("%s:%u:%s:%s: Create error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1086,10 +1111,12 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
}
} else {
/* open the file only for reading */
if (!file_flag_has(file, FILE_IS_MISSING))
if (!file_flag_has(file, FILE_IS_MISSING)) {
ret = handle_open(&handle[j], file, state->file_mode, log_error, state->opt.expected_missing ? log_expected : 0);
else
} else {
errno = ENOENT;
ret = -1; /* if the file is missing, we cannot open it */
}
if (ret == -1) {
/* save the failed block for the check/fix */
failed[failed_count].is_bad = 1;
@ -1102,7 +1129,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
failed[failed_count].handle = &handle[j];
++failed_count;
log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos);
log_tag("%s:%u:%s:%s: Open error at position %u. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno));
++error;
/* mark the file as missing, to avoid to retry to open it again */
@ -1142,8 +1169,10 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = handle_truncate(&handle[j], file);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Unexpected truncate error in a data disk, it isn't possible to fix.\n");
log_tag("%s:%u:%s:%s: Truncate error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1174,7 +1203,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
failed[failed_count].handle = &handle[j];
++failed_count;
log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos);
log_tag("%s:%u:%s:%s: Read error at position %u. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno));
++error;
continue;
}
@ -1264,9 +1293,10 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
if (parity[l]) {
ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error);
if (ret == -1) {
log_tag("parity_%s:%u:%s: Read error. %s.\n", es(errno), i, lev_config_name(l), strerror(errno));
buffer_recov[l] = 0; /* no parity to use */
log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l));
++error;
}
} else {
@ -1351,16 +1381,13 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Write error. %s.\n", es(errno), i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, failed[j].disk->name);
log_fatal("Stopping at block %u\n", i);
/* mark the file as damaged */
file_flag_set(failed[j].file, FILE_IS_DAMAGED);
if (errno == EACCES) {
log_fatal("WARNING! Please give write permission to the file.\n");
} else {
/* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
}
log_fatal("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1404,9 +1431,10 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size);
if (ret == -1) {
/* LCOV_EXCL_START */
/* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
log_fatal("WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l));
log_tag("%s:%u:%s: Write error. %s.\n", es(errno), i, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
log_fatal("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1442,6 +1470,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("Stopping at block %u\n", i);
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1510,16 +1539,18 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
unsuccessful = 1;
log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno));
log_tag("empty_error:%s:%s: Empty file stat error\n", disk->name, esc_tag(file->sub, esc_buffer));
log_tag("empty_%s:%s:%s: Empty file stat error\n", es(errno), disk->name, esc_tag(file->sub, esc_buffer));
++error;
} else if (!S_ISREG(st.st_mode)) {
unsuccessful = 1;
log_error("Error stating empty file '%s' for not regular file.\n", path);
log_tag("empty_error:%s:%s: Empty file error for not regular file\n", disk->name, esc_tag(file->sub, esc_buffer));
++error;
} else if (st.st_size != 0) {
unsuccessful = 1;
log_error("Error stating empty file '%s' for not empty file.\n", path);
log_tag("empty_error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc_tag(file->sub, esc_buffer), (uint64_t)st.st_size);
++error;
}
@ -1531,8 +1562,11 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = mkancestor(path);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
log_fatal("Error creating ancestor '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno));
log_tag("empty_%s:%u:%s:%s: Create ancestor error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1543,14 +1577,11 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600);
if (f == -1) {
/* LCOV_EXCL_START */
log_fatal("Error creating empty file '%s'. %s.\n", path, strerror(errno));
if (errno == EACCES) {
log_fatal("WARNING! Please give write permission to the file.\n");
} else {
/* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
}
log_fatal("Error creating '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno));
log_tag("empty_%s:%u:%s:%s: Create error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1560,11 +1591,13 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = fmtime(f, file->mtime_sec, file->mtime_nsec);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error timing '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno));
log_tag("empty_%s:%u:%s:%s: Time error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
close(f);
log_fatal("Error timing file '%s'. %s.\n", file->sub, strerror(errno));
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1574,8 +1607,11 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = close(f);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
log_fatal("Error closing '%s%s'. %s.\n", disk->dir, file->sub, strerror(errno));
log_tag("empty_%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1618,11 +1654,12 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
unsuccessful = 1;
log_error("Error stating hardlink '%s'. %s.\n", path, strerror(errno));
log_tag("hardlink_error:%s:%s:%s: Hardlink stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
log_tag("hardlink_%s:%s:%s:%s: Hardlink stat error. %s.\n", es(errno), disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt), strerror(errno));
++error;
} else if (!S_ISREG(st.st_mode)) {
unsuccessful = 1;
log_error("Error stating hardlink '%s' for not regular file.\n", path);
log_tag("hardlink_error:%s:%s:%s: Hardlink error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
++error;
}
@ -1648,11 +1685,12 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
}
log_error("Error stating hardlink-to '%s'. %s.\n", pathto, strerror(errno));
log_tag("hardlink_error:%s:%s:%s: Hardlink to stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
log_tag("hardlink_%s:%s:%s:%s: Hardlink to stat error. %s.\n", es(errno), disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt), strerror(errno));
++error;
} else if (!S_ISREG(stto.st_mode)) {
unsuccessful = 1;
log_error("Error stating hardlink-to '%s' for not regular file.\n", path);
log_tag("hardlink_error:%s:%s:%s: Hardlink-to error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt));
++error;
} else if (!unsuccessful && st.st_ino != stto.st_ino) {
@ -1670,13 +1708,13 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
unsuccessful = 1;
log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno));
log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer));
log_tag("symlink_%s:%s:%s: Symlink read error. %s.\n", es(errno), disk->name, esc_tag(slink->sub, esc_buffer), strerror(errno));
++error;
} else if (ret >= PATH_MAX) {
unsuccessful = 1;
log_error("Error reading symlink '%s'. Symlink too long.\n", path);
log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer));
log_tag("symlink_error:%s:%s: Symlink too long\n", disk->name, esc_tag(slink->sub, esc_buffer));
++error;
} else {
linkto[ret] = 0;
@ -1691,12 +1729,17 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
}
if (fix && unsuccessful && !unrecoverable) {
const char* link = link_flag_has(slink, FILE_IS_HARDLINK) ? "hard" : "sym";
/* create the ancestor directories */
ret = mkancestor(path);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
log_fatal("Error creating ancestor '%s%s'. %s.\n", disk->dir, slink->sub, strerror(errno));
log_tag("%slink_%s:%u:%s:%s: Create ancestor error. %s.\n", link, es(errno), i, disk->name, esc_tag(slink->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1706,9 +1749,11 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = remove(path);
if (ret != 0 && errno != ENOENT) {
/* LCOV_EXCL_START */
log_fatal("Error removing '%s'. %s.\n", path, strerror(errno));
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
log_fatal("Error removing '%s%s'. %s.\n", disk->dir, slink->sub, strerror(errno));
log_tag("%slink_%s:%u:%s:%s: Remove error. %s.\n", link, es(errno), i, disk->name, esc_tag(slink->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1720,13 +1765,10 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error writing hardlink '%s' to '%s'. %s.\n", path, pathto, strerror(errno));
if (errno == EACCES) {
log_fatal("WARNING! Please give write permission to the hardlink.\n");
} else {
/* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
}
log_tag("hardlink_%s:%u:%s:%s: Hardlink error. %s.\n", es(errno), i, disk->name, esc_tag(slink->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1739,13 +1781,10 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error writing symlink '%s' to '%s'. %s.\n", path, slink->linkto, strerror(errno));
if (errno == EACCES) {
log_fatal("WARNING! Please give write permission to the symlink.\n");
} else {
/* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
}
log_tag("symlink_%s:%u:%s:%s: Hardlink error. %s.\n", es(errno), i, disk->name, esc_tag(slink->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1784,7 +1823,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
unsuccessful = 1;
log_error("Error stating dir '%s'. %s.\n", path, strerror(errno));
log_tag("dir_error:%s:%s: Dir stat error\n", disk->name, esc_tag(dir->sub, esc_buffer));
log_tag("dir_%s:%s:%s: Dir stat error. %s.\n", es(errno), disk->name, esc_tag(dir->sub, esc_buffer), strerror(errno));
++error;
} else if (!S_ISDIR(st.st_mode)) {
unsuccessful = 1;
@ -1798,8 +1837,11 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = mkancestor(path);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
log_fatal("Error creating ancestor '%s%s'. %s.\n", disk->dir, dir->sub, strerror(errno));
log_tag("dir_%s:%u:%s:%s: Create ancestor error. %s.\n", es(errno), i, disk->name, esc_tag(dir->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1809,14 +1851,11 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error creating dir '%s'. %s.\n", path, strerror(errno));
if (errno == EACCES) {
log_fatal("WARNING! Please give write permission to the dir.\n");
} else {
/* we do not use DANGER because it could be ENOSPC which is not always correctly reported */
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
}
log_fatal("Error creating directory '%s%s'. %s.\n", disk->dir, dir->sub, strerror(errno));
log_tag("dir_%s:%u:%s:%s: Create directory error. %s.\n", es(errno), i, disk->name, esc_tag(dir->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping\n");
++unrecoverable_error;
goto bail;
/* LCOV_EXCL_STOP */
@ -1842,8 +1881,9 @@ bail:
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected close error in a data disk.\n");
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
++unrecoverable_error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
@ -1892,7 +1932,9 @@ bail:
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error removing '%s'. %s.\n", path, strerror(errno));
log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n");
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
++unrecoverable_error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
@ -2028,6 +2070,12 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b
/* open for reading, and ignore error */
ret = parity_open(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
if (ret == -1) {
log_tag("parity_%s:%u:%s: Open error. %s.\n", es(errno), blockmax, lev_config_name(l), strerror(errno));
if (errno == EIO) {
log_fatal_errno(errno, lev_config_name(l));
exit(EXIT_FAILURE);
}
/* continue anyway */
parity_ptr[l] = 0;
}
@ -2036,7 +2084,8 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b
ret = parity_create(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("WARNING! Without an accessible %s file, it isn't possible to fix any error.\n", lev_name(l));
log_tag("parity_%s:%u:%s: Create error. %s.\n", es(errno), 0, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -2044,7 +2093,8 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b
ret = parity_chsize(parity_ptr[l], &state->parity[l], 0, size, state->block_size, state->opt.skip_fallocate, state->opt.skip_space_holder);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));
log_tag("parity_%s:%u:%s: Create error. %s.\n", es(errno), 0, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -2057,7 +2107,14 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b
parity_ptr[l] = &parity[l];
ret = parity_open(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
if (ret == -1) {
log_tag("parity_%s:%u:%s: Open error. %s.\n", es(errno), blockmax, lev_config_name(l), strerror(errno));
if (errno == EIO) {
log_fatal_errno(errno, lev_config_name(l));
exit(EXIT_FAILURE);
}
msg_status("No accessible %s file, only files will be checked.\n", lev_name(l));
/* continue anyway */
parity_ptr[l] = 0;
}
@ -2089,7 +2146,9 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b
ret = parity_truncate(parity_ptr[l]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Unexpected truncate error in %s disk.\n", lev_name(l));
log_tag("parity_%s:%u:%s: Truncate error. %s.\n", es(errno), blockmax, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
@ -2099,7 +2158,9 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b
ret = parity_close(parity_ptr[l]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l));
log_tag("parity_%s:%u:%s: Close error. %s.\n", es(errno), blockmax, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */

View file

@ -28,6 +28,34 @@
/****************************************************************************/
/* dry */
static const char* es(int err)
{
if (err == EIO)
return "error_io";
else
return "error";
}
static void log_fatal_errno(int err, const char* name)
{
if (err == EIO) {
log_fatal("DANGER! Unexpected input/output error in disk %s. It isn't possible to continue.\n", name);
} else if (err == EACCES) {
log_fatal("WARNING! Grant permission in the disk %s. It isn't possible to continue.\n", name);
} else if (err == ENOSPC) {
log_fatal("WARNING! Ensure there is free space on the disk %s. It isn't possible to continue.\n", name);
} else {
log_fatal("WARNING! Without a working %s disk, it isn't possible to continue.\n", name);
}
}
static void log_error_errno(int err, const char* name)
{
if (err == EIO) {
log_fatal("DANGER! Unexpected input/output error in disk %s.\n", name);
}
}
static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task* task)
{
struct snapraid_io* io = worker->io;
@ -70,57 +98,49 @@ static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task
/* LCOV_EXCL_START */
/* This one is really an unexpected error, because we are only reading */
/* and closing a descriptor should never fail */
if (errno == EIO) {
log_tag("error:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to dry.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_IOERROR;
return;
}
log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to dry.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle->path);
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_ERROR;
if (errno == EIO) {
task->state = TASK_STATE_IOERROR;
} else {
task->state = TASK_STATE_ERROR;
}
return;
/* LCOV_EXCL_STOP */
}
}
ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
ret = handle_open(handle, task->file, state->file_mode, log_error, 0); /* for missing file don't output a message */
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Open error. %s.\n", es(errno), blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
if (errno == EIO) {
log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to dry.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
/* LCOV_EXCL_START */
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_IOERROR;
return;
/* LCOV_EXCL_STOP */
}
log_tag("error:%u:%s:%s: Open error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
task->state = TASK_STATE_ERROR_CONTINUE;
return;
/* LCOV_EXCL_STOP */
}
task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
if (task->read_size == -1) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Read error at position %u. %s.\n", es(errno), blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
if (errno == EIO) {
log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos);
/* LCOV_EXCL_START */
log_error_errno(errno, disk->name);
task->state = TASK_STATE_IOERROR_CONTINUE;
return;
/* LCOV_EXCL_STOP */
}
log_tag("error:%u:%s:%s: Read error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
task->state = TASK_STATE_ERROR_CONTINUE;
return;
/* LCOV_EXCL_STOP */
}
/* store the path of the opened file */
@ -142,18 +162,17 @@ static void dry_parity_reader(struct snapraid_worker* worker, struct snapraid_ta
/* read the parity */
ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("parity_%s:%u:%s: Read error. %s.\n", es(errno), blockcur, lev_config_name(level), strerror(errno));
if (errno == EIO) {
log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno));
log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur);
/* LCOV_EXCL_START */
log_error_errno(errno, lev_config_name(level));
task->state = TASK_STATE_IOERROR_CONTINUE;
return;
/* LCOV_EXCL_STOP */
}
log_tag("parity_error:%u:%s: Read error. %s\n", blockcur, lev_config_name(level), strerror(errno));
task->state = TASK_STATE_ERROR_CONTINUE;
return;
/* LCOV_EXCL_STOP */
}
task->state = TASK_STATE_DONE;
@ -203,6 +222,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
/* start all the worker threads */
io_start(&io, blockstart, blockmax, 0);
blockcur = blockstart;
if (!state_progress_begin(state, blockstart, blockmax, countmax))
goto end;
@ -270,8 +290,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
++io_error;
if (io_error >= state->opt.io_error_limit) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Too many input/output read errors in a data disk, it isn't possible to scrub.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, task->path);
log_fatal("DANGER! Too many input/output errors in the %s disk. It isn't possible to continue.\n", disk->dir);
log_fatal("Stopping at block %u\n", blockcur);
goto bail;
/* LCOV_EXCL_STOP */
@ -324,8 +343,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
++io_error;
if (io_error >= state->opt.io_error_limit) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Too many input/output read errors in the %s disk, it isn't possible to scrub.\n", lev_name(levcur));
log_fatal("Ensure that disk '%s' is sane and can be read.\n", lev_config_name(levcur));
log_fatal("DANGER! Too many input/output errors in the %s disk. It isn't possible to continue.\n", lev_name(levcur));
log_fatal("Stopping at block %u\n", blockcur);
goto bail;
/* LCOV_EXCL_STOP */
@ -381,9 +399,14 @@ bail:
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected close error in a data disk.\n");
++error;
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
if (errno == EIO) {
++io_error;
} else {
++error;
}
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
@ -402,6 +425,14 @@ bail:
if (io_error)
log_fatal("DANGER! Unexpected input/output errors!\n");
log_tag("summary:error_file:%u\n", error);
log_tag("summary:error_io:%u\n", io_error);
if (error + io_error == 0)
log_tag("summary:exit:ok\n");
else
log_tag("summary:exit:error\n");
log_flush();
free(handle);
free(waiting_map);
io_done(&io);
@ -441,7 +472,8 @@ int state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
ret = parity_open(&parity_handle[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("WARNING! Without an accessible %s file, it isn't possible to dry.\n", lev_name(l));
log_tag("parity_%s:%u:%s: Open error. %s.\n", es(errno), blockmax, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -465,6 +497,9 @@ int state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t
ret = parity_close(&parity_handle[l]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("parity_%s:%u:%s: Close error. %s.\n", es(errno), blockmax, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */

View file

@ -175,6 +175,8 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int
if (errno == ENOENT)
out_missing("Missing file '%s'.\n", handle->path);
else if (errno == EACCES)
out("Permission denied for file '%s'.\n", handle->path);
else
out("Error opening file '%s'. %s.\n", handle->path, strerror(errno));
return -1;
@ -250,16 +252,20 @@ int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned c
/* check if we are going to read only not initialized data */
if (offset >= handle->valid_size) {
/* if the file is missing, it's at 0 size, or it's rebuilt while reading */
if (offset == handle->valid_size || handle->valid_size == 0)
out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
else
out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
if (offset == handle->valid_size || handle->valid_size == 0) {
out_missing("Reading missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
errno = ENOENT;
} else {
out("Reading over the end from file '%s' at offset %" PRIu64 ".\n", handle->path, offset);
errno = ENXIO;
}
return -1;
}
read_size = file_block_size(handle->file, file_pos, block_size);
count = 0;
errno = 0;
do {
bw_limit(handle->bw, block_size - count);
@ -273,6 +279,8 @@ int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned c
}
if (read_ret == 0) {
out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno));
if (errno == 0)
errno = ENXIO;
return -1;
}
@ -310,6 +318,8 @@ int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned
if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */
/* LCOV_EXCL_START */
log_fatal("Error writing file '%s'. %s.\n", handle->path, strerror(errno));
if (errno == 0)
errno = ENXIO;
return -1;
/* LCOV_EXCL_STOP */
}

View file

@ -266,8 +266,10 @@ static int parity_handle_grow(struct snapraid_split_handle* split, data_off_t pr
(void)previous_size;
/* simulate a failure for testing limits */
if (split->limit_size != 0 && size > (data_off_t)split->limit_size)
if (split->limit_size != 0 && size > (data_off_t)split->limit_size) {
errno = ENXIO;
return -1;
}
#if HAVE_FALLOCATE
if (!skip_fallocate) {
@ -565,6 +567,7 @@ int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity*
if (size < 0) {
/* LCOV_EXCL_START */
errno = ENXIO;
return -1;
/* LCOV_EXCL_STOP */
}
@ -589,6 +592,7 @@ int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity*
if ((run & block_mask) != 0) {
/* LCOV_EXCL_START */
log_fatal("Internal inconsistency in split '%s' size with extra '%" PRIu64 "' bytes.\n", split->path, run & block_mask);
errno = ENXIO;
return -1;
/* LCOV_EXCL_STOP */
}
@ -608,11 +612,13 @@ int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity*
if (split->st.st_size > run) {
/* LCOV_EXCL_START */
log_fatal("Unexpected over resizing parity file '%s' to size %" PRIu64 " resulting in size %" PRIu64 ".\n", split->path, run, (uint64_t)split->st.st_size);
errno = ENXIO;
return -1;
/* LCOV_EXCL_STOP */
} else if (is_fixed && split->st.st_size < run) {
/* LCOV_EXCL_START */
log_fatal("Failed restoring parity file '%s' to size %" PRIu64 " resulting in size %" PRIu64 ".\n", split->path, run, (uint64_t)split->st.st_size);
errno = ENXIO;
return -1;
/* LCOV_EXCL_STOP */
} else {
@ -638,6 +644,7 @@ int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity*
if (size != 0) {
/* LCOV_EXCL_START */
log_fatal("Failed to allocate all the required parity space. You miss %" PRIu64 " bytes.\n", size);
errno = ENXIO;
return -1;
/* LCOV_EXCL_STOP */
}
@ -872,8 +879,10 @@ int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigne
if (errno == ENOSPC) {
log_fatal("Failed to grow parity file '%s' using write due lack of space.\n", split->path);
} else {
log_fatal("Error writing file '%s'. %s.\n", split->path, strerror(errno));
log_fatal("Error writing parity file '%s'. %s.\n", split->path, strerror(errno));
}
if (errno == 0)
errno = ENXIO;
return -1;
/* LCOV_EXCL_STOP */
}
@ -910,25 +919,28 @@ int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned
/* if read is completely out of the valid range */
if (offset >= split->valid_size) {
/* LCOV_EXCL_START */
out("Missing data reading file '%s' at offset %" PRIu64 " for size %u.\n", split->path, offset, block_size);
out("Reading over the end from parity file '%s' at offset %" PRIu64 " for size %u.\n", split->path, offset, block_size);
return -1;
/* LCOV_EXCL_STOP */
}
count = 0;
errno = 0;
do {
bw_limit(handle->bw, block_size - count);
read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count);
if (read_ret < 0) {
/* LCOV_EXCL_START */
out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", split->path, offset + count, block_size - count, strerror(errno));
out("Error reading parity file '%s' at offset %" PRIu64 " for size %u. %s.\n", split->path, offset + count, block_size - count, strerror(errno));
return -1;
/* LCOV_EXCL_STOP */
}
if (read_ret == 0) {
/* LCOV_EXCL_START */
out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", split->path, offset, strerror(errno));
out("Unexpected end of parity file '%s' at offset %" PRIu64 ". %s.\n", split->path, offset, strerror(errno));
if (errno == 0)
errno = ENXIO;
return -1;
/* LCOV_EXCL_STOP */
}

View file

@ -28,6 +28,34 @@
/****************************************************************************/
/* scrub */
static const char* es(int err)
{
if (err == EIO)
return "error_io";
else
return "error";
}
static void log_fatal_errno(int err, const char* name)
{
if (err == EIO) {
log_fatal("DANGER! Unexpected input/output error in disk %s. It isn't possible to continue.\n", name);
} else if (err == EACCES) {
log_fatal("WARNING! Grant permission in the disk %s. It isn't possible to continue.\n", name);
} else if (err == ENOSPC) {
log_fatal("WARNING! Ensure there is free space on the disk %s. It isn't possible to continue.\n", name);
} else {
log_fatal("WARNING! Without a working %s disk, it isn't possible to continue.\n", name);
}
}
static void log_error_errno(int err, const char* name)
{
if (err == EIO) {
log_fatal("DANGER! Unexpected input/output error in disk %s.\n", name);
}
}
/**
* Buffer for storing the new hashes.
*/
@ -142,39 +170,32 @@ static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_ta
/* LCOV_EXCL_START */
/* This one is really an unexpected error, because we are only reading */
/* and closing a descriptor should never fail */
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to scrub.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_IOERROR;
return;
}
log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to scrub.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle->path);
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_ERROR;
if (errno == EIO) {
task->state = TASK_STATE_IOERROR;
} else {
task->state = TASK_STATE_ERROR;
}
return;
/* LCOV_EXCL_STOP */
}
}
ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
ret = handle_open(handle, task->file, state->file_mode, log_error, 0); /* for missing file don't output a message */
if (ret == -1) {
log_tag("%s:%u:%s:%s: Open error. %s.\n", es(errno), blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
if (errno == EIO) {
/* LCOV_EXCL_START */
log_tag("error_io:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to scrub.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_IOERROR;
return;
/* LCOV_EXCL_STOP */
}
log_tag("error:%u:%s:%s: Open error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
task->state = TASK_STATE_ERROR_CONTINUE;
return;
}
@ -196,15 +217,15 @@ static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_ta
task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
if (task->read_size == -1) {
log_tag("%s:%u:%s:%s: Read error at position %u. %s.\n", es(errno), blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
log_error("DANGER! Unexpected input/output error in a data disk, it isn't possible to scrub.\n");
log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos);
/* LCOV_EXCL_START */
log_error_errno(errno, disk->name);
task->state = TASK_STATE_IOERROR_CONTINUE;
return;
/* LCOV_EXCL_STOP */
}
log_tag("error:%u:%s:%s: Read error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
task->state = TASK_STATE_ERROR_CONTINUE;
return;
}
@ -228,15 +249,15 @@ static void scrub_parity_reader(struct snapraid_worker* worker, struct snapraid_
/* read the parity */
ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error);
if (ret == -1) {
log_tag("parity_%s:%u:%s: Read error. %s.\n", es(errno), blockcur, lev_config_name(level), strerror(errno));
if (errno == EIO) {
log_tag("parity_error_io:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno));
log_error("DANGER! Unexpected input/output error in a parity disk, it isn't possible to scrub.\n");
log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur);
/* LCOV_EXCL_START */
log_error_errno(errno, lev_config_name(level));
task->state = TASK_STATE_IOERROR_CONTINUE;
return;
/* LCOV_EXCL_STOP */
}
log_tag("parity_error:%u:%s: Read error. %s\n", blockcur, lev_config_name(level), strerror(errno));
task->state = TASK_STATE_ERROR_CONTINUE;
return;
}
@ -445,8 +466,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
++io_error;
if (io_error >= state->opt.io_error_limit) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Too many input/output read error in a data disk, it isn't possible to scrub.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, task->path);
log_fatal("DANGER! Too many input/output errors in the %s disk. It isn't possible to continue.\n", disk->dir);
log_fatal("Stopping at block %u\n", blockcur);
goto bail;
/* LCOV_EXCL_STOP */
@ -544,8 +564,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
++io_error;
if (io_error >= state->opt.io_error_limit) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Too many input/output read error in the %s disk, it isn't possible to scrub.\n", lev_name(levcur));
log_fatal("Ensure that disk '%s' is sane and can be read.\n", lev_config_name(levcur));
log_fatal("DANGER! Too many input/output errors in the %s disk. It isn't possible to continue.\n", lev_name(levcur));
log_fatal("Stopping at block %u\n", blockcur);
goto bail;
/* LCOV_EXCL_STOP */
@ -719,15 +738,12 @@ bail:
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output close error in a data disk.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle[j].path);
++io_error;
} else {
log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected close error in a data disk.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle[j].path);
++error;
}
/* continue, as we are already exiting */
@ -927,7 +943,8 @@ int state_scrub(struct snapraid_state* state, int plan, int olderthan)
ret = parity_open(&parity_handle[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("WARNING! Without an accessible %s file, it isn't possible to scrub.\n", lev_name(l));
log_tag("parity_%s:%u:%s: Open error. %s.\n", es(errno), blockmax, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -945,7 +962,9 @@ int state_scrub(struct snapraid_state* state, int plan, int olderthan)
ret = parity_close(&parity_handle[l]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l));
log_tag("parity_%s:%u:%s: Close error. %s.\n", es(errno), blockmax, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */

View file

@ -28,6 +28,42 @@
/****************************************************************************/
/* hash */
static const char* es(int err)
{
if (err == EIO)
return "error_io";
else
return "error";
}
static void log_fatal_errno(int err, const char* name)
{
if (err == EIO) {
log_fatal("DANGER! Unexpected input/output error in disk %s. It isn't possible to continue.\n", name);
} else if (err == EACCES) {
log_fatal("WARNING! Grant permission in the disk %s. It isn't possible to continue.\n", name);
} else if (err == ENOSPC) {
log_fatal("WARNING! Ensure there is free space on the disk %s. It isn't possible to continue.\n", name);
} else {
log_fatal("WARNING! Without a working %s disk, it isn't possible to continue.\n", name);
}
}
static void log_error_errno(int err, const char* name)
{
if (err == EIO) {
log_fatal("DANGER! Unexpected input/output error in disk %s.\n", name);
} else if (err == EACCES) {
log_error("WARNING! Grant permission in the disk %s.\n", name);
log_error("Rerun the sync command when finished.\n");
} else if (err == ENOSPC) {
log_error("WARNING! Ensure there is free space on the disk %s.\n", name);
} else if (err == ENOENT) {
log_error("WARNING! You cannot modify files during a sync.\n");
log_error("Rerun the sync command when finished.\n");
}
}
static int state_hash_process(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, int* skip_sync)
{
struct snapraid_handle* handle;
@ -138,43 +174,26 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
/* LCOV_EXCL_START */
/* This one is really an unexpected error, because we are only reading */
/* and closing a descriptor should never fail */
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Close EIO error. %s\n", i, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle[j].path);
log_fatal("Stopping at block %u\n", i);
++io_error;
goto bail;
}
log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle[j].path);
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", i);
++error;
if (errno == EIO) {
++io_error;
} else {
++error;
}
goto bail;
/* LCOV_EXCL_STOP */
}
}
ret = handle_open(&handle[j], file, state->file_mode, log_error, 0);
ret = handle_open(&handle[j], file, state->file_mode, log_error, log_error); /* output a message for missing files */
if (ret == -1) {
if (errno == EIO) {
/* LCOV_EXCL_START */
log_tag("error_io:%u:%s:%s: Open EIO error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle[j].path);
log_fatal("Stopping at block %u\n", i);
++io_error;
goto bail;
/* LCOV_EXCL_STOP */
}
log_tag("%s:%u:%s:%s: Open error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
if (errno == ENOENT) {
log_tag("error:%u:%s:%s: Open ENOENT error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_error("Missing file '%s'.\n", handle[j].path);
log_error("WARNING! You cannot modify data disk during a sync.\n");
log_error("Rerun the sync command when finished.\n");
log_error_errno(errno, disk->name);
++error;
/* if the file is missing, it means that it was removed during sync */
/* this isn't a serious error, so we skip this block, and continue with others */
@ -182,21 +201,23 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
}
if (errno == EACCES) {
log_tag("error:%u:%s:%s: Open EACCES error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_error("No access at file '%s'.\n", handle[j].path);
log_error("WARNING! Please fix the access permission in the data disk.\n");
log_error("Rerun the sync command when finished.\n");
log_error_errno(errno, disk->name);
++error;
/* this isn't a serious error, so we skip this block, and continue with others */
continue;
}
/* LCOV_EXCL_START */
log_tag("error:%u:%s:%s: Open error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected open error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle[j].path);
log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, file->sub, esc_buffer));
++error;
log_fatal_errno(errno, disk->name);
if (errno == EIO) {
log_fatal("Stopping at block %u\n", i);
++io_error;
} else {
log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, file->sub, esc_buffer));
++error;
}
goto bail;
/* LCOV_EXCL_STOP */
}
@ -218,9 +239,10 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
log_tag("error:%u:%s:%s: Unexpected inode change\n", i, disk->name, esc_tag(file->sub, esc_buffer));
log_error("Unexpected inode change from %" PRIu64 " to %" PRIu64 " at file '%s'.\n", file->inode, (uint64_t)handle[j].st.st_ino, handle[j].path);
}
log_error("WARNING! You cannot modify files during a sync.\n");
log_error("Rerun the sync command when finished.\n");
log_error_errno(ENOENT, disk->name); /* same message for ENOENT */
++error;
/* if the file is changed, it means that it was modified during sync */
/* this isn't a serious error, so we skip this block, and continue with others */
continue;
@ -229,20 +251,16 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
read_size = handle_read(&handle[j], file_pos, buffer, state->block_size, log_fatal, 0);
if (read_size == -1) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Read error at position %u. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno));
log_fatal_errno(errno, disk->name);
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Read EIO error at position %u. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno));
log_fatal("DANGER! Unexpected input/output read error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be read.\n", disk->dir, handle[j].path);
log_fatal("Stopping at block %u\n", i);
++io_error;
goto bail;
} else {
log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, file->sub, esc_buffer));
++error;
}
log_tag("error:%u:%s:%s: Read error at position %u. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno));
log_fatal("WARNING! Unexpected read error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that file '%s' can be read.\n", handle[j].path);
log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, file->sub, esc_buffer));
++error;
goto bail;
/* LCOV_EXCL_STOP */
}
@ -322,20 +340,15 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
/* LCOV_EXCL_START */
/* This one is really an unexpected error, because we are only reading */
/* and closing a descriptor should never fail */
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Close EIO error. %s\n", blockmax, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle[j].path);
log_fatal("Stopping at block %u\n", blockmax);
++io_error;
goto bail;
}
log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle[j].path);
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), blockmax, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", blockmax);
++error;
if (errno == EIO) {
++io_error;
} else {
++error;
}
goto bail;
/* LCOV_EXCL_STOP */
}
@ -379,15 +392,12 @@ bail:
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Close EIO error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output close error in a data disk.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle[j].path);
++io_error;
} else {
log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected close error in a data disk.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle[j].path);
++error;
}
/* continue, as we are already exiting */
@ -528,43 +538,26 @@ static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_tas
/* LCOV_EXCL_START */
/* This one is really an unexpected error, because we are only reading */
/* and closing a descriptor should never fail */
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_IOERROR;
return;
}
log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle->path);
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_ERROR;
if (errno == EIO) {
task->state = TASK_STATE_IOERROR;
} else {
task->state = TASK_STATE_ERROR;
}
return;
/* LCOV_EXCL_STOP */
}
}
ret = handle_open(handle, task->file, state->file_mode, log_error, 0);
ret = handle_open(handle, task->file, state->file_mode, log_error, log_error); /* output a message for missing files */
if (ret == -1) {
if (errno == EIO) {
/* LCOV_EXCL_START */
log_tag("error_io:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path);
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_IOERROR;
return;
/* LCOV_EXCL_STOP */
}
log_tag("%s:%u:%s:%s: Open error. %s.\n", es(errno), blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
if (errno == ENOENT) {
log_tag("error:%u:%s:%s: Open ENOENT error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
log_error("Missing file '%s'.\n", handle->path);
log_error("WARNING! You cannot modify data disk during a sync.\n");
log_error("Rerun the sync command when finished.\n");
log_error_errno(errno, disk->name);
/* if the file is missing, it means that it was removed during sync */
/* this isn't a serious error, so we skip this block, and continue with others */
task->state = TASK_STATE_ERROR_CONTINUE;
@ -572,21 +565,23 @@ static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_tas
}
if (errno == EACCES) {
log_tag("error:%u:%s:%s: Open EACCES error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
log_error("No access at file '%s'.\n", handle->path);
log_error("WARNING! Please fix the access permission in the data disk.\n");
log_error("Rerun the sync command when finished.\n");
log_error_errno(errno, disk->name);
/* this isn't a serious error, so we skip this block, and continue with others */
task->state = TASK_STATE_ERROR_CONTINUE;
return;
}
/* LCOV_EXCL_START */
log_tag("error:%u:%s:%s: Open error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected open error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle->path);
log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, task->file->sub, esc_buffer));
task->state = TASK_STATE_ERROR;
log_fatal_errno(errno, disk->name);
if (errno == EIO) {
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_IOERROR;
} else {
log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, task->file->sub, esc_buffer));
task->state = TASK_STATE_ERROR;
}
return;
/* LCOV_EXCL_STOP */
}
@ -606,8 +601,8 @@ static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_tas
} else {
log_error("Unexpected inode change from %" PRIu64 " to %" PRIu64 " at file '%s'.\n", task->file->inode, (uint64_t)handle->st.st_ino, handle->path);
}
log_error("WARNING! You cannot modify files during a sync.\n");
log_error("Rerun the sync command when finished.\n");
log_error_errno(ENOENT, disk->name); /* same message for ENOENT */
/* if the file is changed, it means that it was modified during sync */
/* this isn't a serious error, so we skip this block, and continue with others */
task->state = TASK_STATE_ERROR_CONTINUE;
@ -617,19 +612,17 @@ static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_tas
task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0);
if (task->read_size == -1) {
/* LCOV_EXCL_START */
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
log_fatal("DANGER! Unexpected input/output read error in a data disk, it isn't possible to sync.\n");
log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos);
task->state = TASK_STATE_IOERROR_CONTINUE;
return;
}
log_tag("%s:%u:%s:%s: Read error at position %u. %s.\n", es(errno), blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
log_tag("error:%u:%s:%s: Read error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno));
log_fatal("WARNING! Unexpected read error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that file '%s' can be read.\n", handle->path);
log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, task->file->sub, esc_buffer));
task->state = TASK_STATE_ERROR;
if (errno == EIO) {
log_error_errno(errno, disk->name);
/* continue until the error limit is reached */
task->state = TASK_STATE_IOERROR_CONTINUE;
} else {
log_fatal_errno(errno, disk->name);
log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, task->file->sub, esc_buffer));
task->state = TASK_STATE_ERROR;
}
return;
/* LCOV_EXCL_STOP */
}
@ -654,18 +647,17 @@ static void sync_parity_writer(struct snapraid_worker* worker, struct snapraid_t
ret = parity_write(parity_handle, blockcur, buffer, state->block_size);
if (ret == -1) {
/* LCOV_EXCL_START */
if (errno == EIO) {
log_tag("parity_error_io:%u:%s: Write EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno));
log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur);
task->state = TASK_STATE_IOERROR_CONTINUE;
return;
}
log_tag("parity_%s:%u:%s: Write error. %s.\n", es(errno), blockcur, lev_config_name(level), strerror(errno));
log_tag("parity_error:%u:%s: Write error. %s\n", blockcur, lev_config_name(level), strerror(errno));
log_fatal("WARNING! Unexpected write error in the %s disk, it isn't possible to sync.\n", lev_name(level));
log_fatal("Ensure that disk '%s' has some free space available.\n", lev_config_name(level));
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_ERROR;
if (errno == EIO) {
log_error_errno(errno, lev_config_name(level));
/* continue until the error limit is reached */
task->state = TASK_STATE_IOERROR_CONTINUE;
} else {
log_fatal_errno(errno, lev_config_name(level));
log_fatal("Stopping at block %u\n", blockcur);
task->state = TASK_STATE_ERROR;
}
return;
/* LCOV_EXCL_STOP */
}
@ -927,8 +919,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
++io_error;
if (io_error >= state->opt.io_error_limit) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Unexpected input/output read error in a data disk, it isn't possible to sync.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be read.\n", disk->dir, task->path);
log_fatal("DANGER! Too many input/output errors in the %s disk. It isn't possible to continue.\n", disk->dir);
log_fatal("Stopping at block %u\n", blockcur);
goto bail;
/* LCOV_EXCL_STOP */
@ -1089,25 +1080,22 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
ret = parity_read(&parity_handle[l], blockcur, buffer[diskmax + l], state->block_size, log_error);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("parity_%s:%u:%s: Read error. %s.\n", es(errno), blockcur, lev_config_name(l), strerror(errno));
if (errno == EIO) {
log_tag("parity_error_io:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(l), strerror(errno));
log_error_errno(errno, lev_config_name(l));
if (io_error >= state->opt.io_error_limit) {
log_fatal("DANGER! Unexpected input/output read error in the %s disk, it isn't possible to sync.\n", lev_name(l));
log_fatal("Ensure that disk '%s' is sane and can be read.\n", lev_config_name(l));
log_fatal("DANGER! Too many input/output errors in the %s disk. It isn't possible to continue.\n", lev_config_name(l));
log_fatal("Stopping at block %u\n", blockcur);
++io_error;
goto bail;
}
log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(l), blockcur);
++io_error;
io_error_on_this_block = 1;
continue;
}
log_tag("parity_error:%u:%s: Read error. %s\n", blockcur, lev_config_name(l), strerror(errno));
log_fatal("WARNING! Unexpected read error in the %s disk, it isn't possible to sync.\n", lev_name(l));
log_fatal("Ensure that disk '%s' can be read.\n", lev_config_name(l));
log_fatal_errno(errno, lev_config_name(l));
log_fatal("Stopping at block %u\n", blockcur);
++error;
goto bail;
@ -1275,7 +1263,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
++io_error;
if (io_error >= state->opt.io_error_limit) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Unexpected input/output write error in a parity disk, it isn't possible to sync.\n");
log_fatal("DANGER! Too many input/output errors in a parity disk. It isn't possible to continue.\n");
log_fatal("Stopping at block %u\n", blockcur);
goto bail;
/* LCOV_EXCL_STOP */
@ -1440,18 +1428,14 @@ bail:
ret = handle_close(&handle[j]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_tag("%s:%u:%s:%s: Close error. %s.\n", es(errno), blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal_errno(errno, disk->name);
if (errno == EIO) {
log_tag("error_io:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("DANGER! Unexpected input/output close error in a data disk.\n");
log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle[j].path);
++io_error;
} else {
log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno));
log_fatal("WARNING! Unexpected close error in a data disk.\n");
log_fatal("Ensure that file '%s' can be accessed.\n", handle[j].path);
++error;
}
++error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
}
@ -1521,7 +1505,8 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
ret = parity_create(&parity_handle[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l));
log_tag("parity_%s:%u:%s: Create error. %s.\n", es(errno), 0, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
exit(EXIT_FAILURE);
/* LCOV_EXCL_STOP */
}
@ -1647,7 +1632,9 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
ret = parity_close(&parity_handle[l]);
if (ret == -1) {
/* LCOV_EXCL_START */
log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l));
log_tag("parity_%s:%u:%s: Close error. %s.\n", es(errno), blockmax, lev_config_name(l), strerror(errno));
log_fatal_errno(errno, lev_config_name(l));
++unrecoverable_error;
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */