diff --git a/cmdline/check.c b/cmdline/check.c index 596cdaca..8ca21b31 100644 --- a/cmdline/check.c +++ b/cmdline/check.c @@ -899,7 +899,9 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna data_off_t countsize; block_off_t countpos; block_off_t countmax; - unsigned error; + unsigned soft_error; + unsigned io_error; + unsigned silent_error; unsigned unrecoverable_error; unsigned recovered_error; struct failed_struct* failed; @@ -936,7 +938,9 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna failed = malloc_nofail(diskmax * sizeof(struct failed_struct)); failed_map = malloc_nofail(diskmax * sizeof(unsigned)); - error = 0; + soft_error = 0; + io_error = 0; + silent_error = 0; unrecoverable_error = 0; recovered_error = 0; @@ -1125,7 +1129,12 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna ++failed_count; 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; + + if (errno == EIO) { + ++io_error; + } else { + ++soft_error; + } /* mark the file as missing, to avoid to retry to open it again */ /* note that this can be done only if we are not fixing it */ @@ -1158,7 +1167,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna ) { log_error("File '%s' is larger than expected.\n", handle[j].path); log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc_tag(file->sub, esc_buffer)); - ++error; + ++soft_error; if (fix) { ret = handle_truncate(&handle[j], file); @@ -1199,7 +1208,12 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna ++failed_count; 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; + + if (errno == EIO) { + ++io_error; + } else { + ++soft_error; + } continue; } @@ -1248,7 +1262,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna ++failed_count; log_tag("error:%u:%s:%s: Data error at position %u, diff hash bits %u/%u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); - ++error; + ++silent_error; continue; } @@ -1292,7 +1306,11 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna buffer_recov[l] = 0; /* no parity to use */ - ++error; + if (errno == EIO) { + ++io_error; + } else { + ++soft_error; + } } } else { buffer_recov[l] = 0; @@ -1304,7 +1322,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna if (ret != 0) { /* increment the number of errors */ if (ret > 0) - error += ret; + silent_error += ret; ++unrecoverable_error; /* print a list of all the errors in files */ @@ -1332,7 +1350,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna } } if (partial_recover_error != 0) { - error += partial_recover_error; + silent_error += partial_recover_error; ++unrecoverable_error; } @@ -1355,7 +1373,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna buffer_recov[l] = 0; log_tag("parity_error:%u:%s: Data error, diff parity bits %u/%u\n", i, lev_config_name(l), diff, state->block_size * 8); - ++error; + ++silent_error; } } } @@ -1535,19 +1553,24 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno)); log_tag("empty_%s:%s:%s: Empty file stat error\n", es(errno), disk->name, esc_tag(file->sub, esc_buffer)); - ++error; + + if (errno == EIO) { + ++io_error; + } else { + ++soft_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; + ++soft_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; + ++soft_error; } if (fix && unsuccessful) { @@ -1650,13 +1673,18 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna log_error("Error stating hardlink '%s'. %s.\n", path, strerror(errno)); 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; + + if (errno == EIO) { + ++io_error; + } else { + ++soft_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; + ++soft_error; } /* stat the "to" file */ @@ -1671,29 +1699,32 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna /* if the target doesn't exist, it's unrecoverable */ /* because we cannot create an hardlink of a file that */ /* doesn't exists */ - ++unrecoverable_error; - } else { /* but in check, we can assume that fixing will recover */ /* such missing file, so we assume a less drastic error */ - ++error; + ++unrecoverable_error; } } log_error("Error stating hardlink-to '%s'. %s.\n", pathto, strerror(errno)); 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; + + if (errno == EIO) { + ++io_error; + } else { + ++soft_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; + ++soft_error; } else if (!unsuccessful && st.st_ino != stto.st_ino) { unsuccessful = 1; log_error("Mismatch hardlink '%s' and '%s'. Different inode.\n", path, pathto); log_tag("hardlink_error:%s:%s:%s: Hardlink mismatch for different inode\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); - ++error; + ++soft_error; } } else { /* read the symlink */ @@ -1704,13 +1735,18 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno)); log_tag("symlink_%s:%s:%s: Symlink read error. %s.\n", es(errno), disk->name, esc_tag(slink->sub, esc_buffer), strerror(errno)); - ++error; + + if (errno == EIO) { + ++io_error; + } else { + ++soft_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 too long\n", disk->name, esc_tag(slink->sub, esc_buffer)); - ++error; + ++soft_error; } else { linkto[ret] = 0; @@ -1718,7 +1754,7 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna unsuccessful = 1; log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc_tag(slink->sub, esc_buffer), linkto, slink->linkto); - ++error; + ++soft_error; } } } @@ -1819,12 +1855,17 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna log_error("Error stating dir '%s'. %s.\n", path, strerror(errno)); log_tag("dir_%s:%s:%s: Dir stat error. %s.\n", es(errno), disk->name, esc_tag(dir->sub, esc_buffer), strerror(errno)); - ++error; + + if (errno == EIO) { + ++io_error; + } else { + ++soft_error; + } } else if (!S_ISDIR(st.st_mode)) { unsuccessful = 1; log_tag("dir_error:%s:%s: Dir error for not directory\n", disk->name, esc_tag(dir->sub, esc_buffer)); - ++error; + ++soft_error; } if (fix && unsuccessful) { @@ -1938,9 +1979,11 @@ bail: } } - if (error || recovered_error || unrecoverable_error) { + if (soft_error || io_error || silent_error || recovered_error || unrecoverable_error) { msg_status("\n"); - msg_status("%8u errors\n", error); + msg_status("%8u soft errors\n", soft_error); + msg_status("%8u io errors\n", io_error); + msg_status("%8u data errors\n", silent_error); if (fix) { msg_status("%8u recovered errors\n", recovered_error); } @@ -1957,33 +2000,37 @@ bail: msg_status("Everything OK\n"); } - if (error && !fix) + if ((soft_error || io_error || silent_error) && !fix) log_fatal("WARNING! There are errors!\n"); if (unrecoverable_error) log_fatal("DANGER! Unrecoverable errors detected!\n"); - log_tag("summary:error:%u\n", error); + log_tag("summary:error_soft:%u\n", soft_error); + log_tag("summary:error_io:%u\n", io_error); + log_tag("summary:error_data:%u\n", silent_error); if (fix) log_tag("summary:error_recovered:%u\n", recovered_error); if (!state->opt.auditonly) log_tag("summary:error_unrecoverable:%u\n", unrecoverable_error); if (fix) { - if (error + recovered_error + unrecoverable_error == 0) + if (soft_error + io_error + silent_error + recovered_error + unrecoverable_error == 0) log_tag("summary:exit:ok\n"); else if (unrecoverable_error == 0) log_tag("summary:exit:recovered\n"); else log_tag("summary:exit:unrecoverable\n"); } else if (!state->opt.auditonly) { - if (error + unrecoverable_error == 0) + if (soft_error + io_error + silent_error + unrecoverable_error == 0) log_tag("summary:exit:ok\n"); else if (unrecoverable_error == 0) log_tag("summary:exit:recoverable\n"); else log_tag("summary:exit:unrecoverable\n"); } else { /* audit only */ - if (error == 0) + if (soft_error + silent_error + io_error == 0) log_tag("summary:exit:ok\n"); + else if (silent_error + io_error == 0) + log_tag("summary:exit:warning\n"); else log_tag("summary:exit:error\n"); } @@ -2010,10 +2057,14 @@ bail: if (unrecoverable_error == 0) return -1; } else if (state->opt.expect_recoverable) { - if (unrecoverable_error != 0 || error == 0) + if (unrecoverable_error != 0) + return -1; + if (soft_error + silent_error + io_error == 0) return -1; } else { - if (error != 0 || unrecoverable_error != 0) + if (unrecoverable_error != 0) + return -1; + if (soft_error + silent_error + io_error != 0) return -1; } } @@ -2028,7 +2079,7 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b int ret; struct snapraid_parity_handle parity[LEV_MAX]; struct snapraid_parity_handle* parity_ptr[LEV_MAX]; - unsigned error; + unsigned process_error; unsigned l; msg_progress("Initializing...\n"); @@ -2120,14 +2171,14 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b parity_ptr[l] = 0; } - error = 0; + process_error = 0; /* skip degenerated cases of empty parity, or skipping all */ if (blockstart < blockmax) { ret = state_check_process(state, fix, parity_ptr, blockstart, blockmax); if (ret == -1) { /* LCOV_EXCL_START */ - ++error; + ++process_error; /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ } @@ -2144,7 +2195,7 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b 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; + ++process_error; /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ } @@ -2156,15 +2207,14 @@ int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, b 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; + ++process_error; /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ } } } - /* abort if error are present */ - if (error != 0) + if (process_error != 0) return -1; return 0; } diff --git a/cmdline/dry.c b/cmdline/dry.c index c22dca91..bd4669d1 100644 --- a/cmdline/dry.c +++ b/cmdline/dry.c @@ -190,7 +190,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit data_off_t countsize; block_off_t countpos; block_off_t countmax; - unsigned error; + unsigned soft_error; unsigned io_error; unsigned l; unsigned* waiting_map; @@ -209,7 +209,7 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit waiting_mac = diskmax > RAID_PARITY_MAX ? diskmax : RAID_PARITY_MAX; waiting_map = malloc_nofail(waiting_mac * sizeof(unsigned)); - error = 0; + soft_error = 0; io_error = 0; /* drop until now */ @@ -278,12 +278,12 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit } if (task->state == TASK_STATE_ERROR) { /* LCOV_EXCL_START */ - ++error; + ++soft_error; goto bail; /* LCOV_EXCL_STOP */ } if (task->state == TASK_STATE_ERROR_CONTINUE) { - ++error; + ++soft_error; continue; } if (task->state == TASK_STATE_IOERROR_CONTINUE) { @@ -331,12 +331,12 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit } if (task->state == TASK_STATE_ERROR) { /* LCOV_EXCL_START */ - ++error; + ++soft_error; goto bail; /* LCOV_EXCL_STOP */ } if (task->state == TASK_STATE_ERROR_CONTINUE) { - ++error; + ++soft_error; continue; } if (task->state == TASK_STATE_IOERROR_CONTINUE) { @@ -405,29 +405,29 @@ bail: if (errno == EIO) { ++io_error; } else { - ++error; + ++soft_error; } /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ } } - if (error || io_error) { + if (soft_error || io_error) { msg_status("\n"); - msg_status("%8u file errors\n", error); + msg_status("%8u soft errors\n", soft_error); msg_status("%8u io errors\n", io_error); } else { msg_status("Everything OK\n"); } - if (error) + if (soft_error) log_fatal("DANGER! Unexpected errors!\n"); if (io_error) log_fatal("DANGER! Unexpected input/output errors!\n"); - log_tag("summary:error_file:%u\n", error); + log_tag("summary:error_soft:%u\n", soft_error); log_tag("summary:error_io:%u\n", io_error); - if (error + io_error == 0) + if (soft_error + io_error == 0) log_tag("summary:exit:ok\n"); else log_tag("summary:exit:error\n"); @@ -437,7 +437,7 @@ bail: free(waiting_map); io_done(&io); - if (error + io_error != 0) + if (soft_error + io_error != 0) return -1; return 0; } @@ -447,7 +447,7 @@ int state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t block_off_t blockmax; int ret; struct snapraid_parity_handle parity_handle[LEV_MAX]; - unsigned error; + unsigned process_error; unsigned l; msg_progress("Drying...\n"); @@ -479,14 +479,14 @@ int state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t } } - error = 0; + process_error = 0; /* skip degenerated cases of empty parity, or skipping all */ if (blockstart < blockmax) { ret = state_dry_process(state, parity_handle, blockstart, blockmax); if (ret == -1) { /* LCOV_EXCL_START */ - ++error; + ++process_error; /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ } @@ -500,13 +500,13 @@ int state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t 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; + ++process_error; /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ } } - if (error != 0) + if (process_error != 0) return -1; return 0; } diff --git a/cmdline/scrub.c b/cmdline/scrub.c index 9f7e0f18..e9513312 100644 --- a/cmdline/scrub.c +++ b/cmdline/scrub.c @@ -283,7 +283,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par block_off_t autosavelimit; block_off_t autosavemissing; int ret; - unsigned error; + unsigned soft_error; unsigned silent_error; unsigned io_error; unsigned l; @@ -308,7 +308,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par waiting_mac = diskmax > RAID_PARITY_MAX ? diskmax : RAID_PARITY_MAX; waiting_map = malloc_nofail(waiting_mac * sizeof(unsigned)); - error = 0; + soft_error = 0; silent_error = 0; io_error = 0; @@ -453,12 +453,12 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par } if (task->state == TASK_STATE_ERROR) { /* LCOV_EXCL_START */ - ++error; + ++soft_error; goto bail; /* LCOV_EXCL_STOP */ } if (task->state == TASK_STATE_ERROR_CONTINUE) { - ++error; + ++soft_error; error_on_this_block = 1; continue; } @@ -507,7 +507,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par /* it's a silent error only if we are dealing with synced files */ if (file_is_unsynced) { log_tag("error:%u:%s:%s: Data error at position %u, diff hash bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); - ++error; + ++soft_error; error_on_this_block = 1; } else { log_tag("error_data:%u:%s:%s: Data error at position %u, diff hash bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); @@ -548,12 +548,12 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par } if (task->state == TASK_STATE_ERROR) { /* LCOV_EXCL_START */ - ++error; + ++soft_error; goto bail; /* LCOV_EXCL_STOP */ } if (task->state == TASK_STATE_ERROR_CONTINUE) { - ++error; + ++soft_error; error_on_this_block = 1; /* if continuing on error, clear the missing buffer */ @@ -599,7 +599,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par /* it's a silent error only if we are dealing with synced blocks */ if (block_is_unsynced) { log_tag("parity_error:%u:%s: Data error, diff parity bits %u/%u\n", blockcur, lev_config_name(l), diff, state->block_size * 8); - ++error; + ++soft_error; error_on_this_block = 1; } else { log_tag("parity_error_data:%u:%s: Data error, diff parity bits %u/%u\n", blockcur, lev_config_name(l), diff, state->block_size * 8); @@ -694,9 +694,9 @@ end: state_usage_print(state); - if (error || silent_error || io_error) { + if (soft_error || silent_error || io_error) { msg_status("\n"); - msg_status("%8u file errors\n", error); + msg_status("%8u soft errors\n", soft_error); msg_status("%8u io errors\n", io_error); msg_status("%8u data errors\n", silent_error); } else { @@ -705,8 +705,8 @@ end: msg_status("Everything OK\n"); } - if (error) - log_fatal("WARNING! Unexpected file errors!\n"); + if (soft_error) + log_fatal("WARNING! Unexpected soft errors!\n"); if (io_error) log_fatal("DANGER! Unexpected input/output errors! The failing blocks are now marked as bad!\n"); if (silent_error) @@ -717,10 +717,10 @@ end: log_fatal("Use 'snapraid -p bad scrub' to recheck after fixing to clear the bad state.\n"); } - log_tag("summary:error_file:%u\n", error); + log_tag("summary:error_soft:%u\n", soft_error); log_tag("summary:error_io:%u\n", io_error); log_tag("summary:error_data:%u\n", silent_error); - if (error + silent_error + io_error == 0) + if (soft_error + silent_error + io_error == 0) log_tag("summary:exit:ok\n"); else if (silent_error + io_error == 0) log_tag("summary:exit:warning\n"); @@ -744,7 +744,7 @@ bail: if (errno == EIO) { ++io_error; } else { - ++error; + ++soft_error; } /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ @@ -758,10 +758,10 @@ bail: free(block_enabled); if (state->opt.expect_recoverable) { - if (error + silent_error + io_error == 0) + if (soft_error + silent_error + io_error == 0) return -1; } else { - if (error + silent_error + io_error != 0) + if (soft_error + silent_error + io_error != 0) return -1; } return 0; @@ -792,7 +792,7 @@ int state_scrub(struct snapraid_state* state, int plan, int olderthan) struct snapraid_parity_handle parity_handle[LEV_MAX]; struct snapraid_plan ps; time_t* timemap; - unsigned error; + unsigned process_error; time_t now; unsigned l; @@ -950,11 +950,11 @@ int state_scrub(struct snapraid_state* state, int plan, int olderthan) } } - error = 0; + process_error = 0; ret = state_scrub_process(state, parity_handle, 0, blockmax, &ps, now); if (ret == -1) { - ++error; + ++process_error; /* continue, as we are already exiting */ } @@ -965,14 +965,13 @@ int state_scrub(struct snapraid_state* state, int plan, int olderthan) 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; + ++process_error; /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ } } - /* abort if required */ - if (error != 0) + if (process_error != 0) return -1; return 0; } diff --git a/cmdline/sync.c b/cmdline/sync.c index 6f391725..34ddd409 100644 --- a/cmdline/sync.c +++ b/cmdline/sync.c @@ -76,7 +76,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta block_off_t countpos; block_off_t countmax; int ret; - unsigned error; + unsigned soft_error; unsigned silent_error; unsigned io_error; char esc_buffer[ESC_MAX]; @@ -89,7 +89,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta if (!state->opt.skip_self) mtest_vector(1, state->block_size, &buffer); - error = 0; + soft_error = 0; silent_error = 0; io_error = 0; @@ -181,7 +181,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta if (errno == EIO) { ++io_error; } else { - ++error; + ++soft_error; } goto bail; /* LCOV_EXCL_STOP */ @@ -194,7 +194,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta if (errno == ENOENT) { log_error_errno(errno, disk->name); - ++error; + ++soft_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 */ continue; @@ -203,7 +203,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta if (errno == EACCES) { log_error_errno(errno, disk->name); - ++error; + ++soft_error; /* this isn't a serious error, so we skip this block, and continue with others */ continue; } @@ -216,7 +216,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta ++io_error; } else { log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, file->sub, esc_buffer)); - ++error; + ++soft_error; } goto bail; /* LCOV_EXCL_STOP */ @@ -241,7 +241,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta } log_error_errno(ENOENT, disk->name); /* same message for ENOENT */ - ++error; + ++soft_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 */ @@ -259,7 +259,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta ++io_error; } else { log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, file->sub, esc_buffer)); - ++error; + ++soft_error; } goto bail; /* LCOV_EXCL_STOP */ @@ -347,7 +347,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta if (errno == EIO) { ++io_error; } else { - ++error; + ++soft_error; } goto bail; /* LCOV_EXCL_STOP */ @@ -362,9 +362,9 @@ end: /* because at the first one we bail out */ assert(io_error == 0); - if (error || io_error || silent_error) { + if (soft_error || io_error || silent_error) { msg_status("\n"); - msg_status("%8u file errors\n", error); + msg_status("%8u soft errors\n", soft_error); msg_status("%8u io errors\n", io_error); msg_status("%8u data errors\n", silent_error); } else { @@ -373,10 +373,10 @@ end: msg_status("Everything OK\n"); } - if (error) - log_fatal("WARNING! Unexpected file errors!\n"); + if (soft_error) + log_fatal("WARNING! Unexpected soft errors!\n"); - log_tag("hash_summary:error_file:%u\n", error); + log_tag("hash_summary:error_soft:%u\n", soft_error); /* proceed without bailing out */ goto finish; @@ -398,7 +398,7 @@ bail: if (errno == EIO) { ++io_error; } else { - ++error; + ++soft_error; } /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ @@ -409,7 +409,7 @@ finish: free(handle); free(buffer_alloc); - if (error + io_error + silent_error != 0) + if (soft_error + io_error + silent_error != 0) return -1; return 0; } @@ -687,7 +687,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari block_off_t autosavelimit; block_off_t autosavemissing; int ret; - unsigned error; + unsigned soft_error; unsigned silent_error; unsigned io_error; time_t now; @@ -733,7 +733,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari waiting_mac = diskmax > RAID_PARITY_MAX ? diskmax : RAID_PARITY_MAX; waiting_map = malloc_nofail(waiting_mac * sizeof(unsigned)); - error = 0; + soft_error = 0; silent_error = 0; io_error = 0; @@ -906,12 +906,12 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari } if (task->state == TASK_STATE_ERROR) { /* LCOV_EXCL_START */ - ++error; + ++soft_error; goto bail; /* LCOV_EXCL_STOP */ } if (task->state == TASK_STATE_ERROR_CONTINUE) { - ++error; + ++soft_error; error_on_this_block = 1; continue; } @@ -970,7 +970,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari log_error("Try removing the file from the array and rerun the 'sync' command!\n"); } - ++error; + ++soft_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 */ @@ -1097,7 +1097,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari log_fatal_errno(errno, lev_config_name(l)); log_fatal("Stopping at block %u\n", blockcur); - ++error; + ++soft_error; goto bail; /* LCOV_EXCL_STOP */ } @@ -1270,7 +1270,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari } break; case TASK_STATE_ERROR_CONTINUE : - ++error; + ++soft_error; break; case TASK_STATE_IOERROR : /* LCOV_EXCL_START */ @@ -1279,7 +1279,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari /* LCOV_EXCL_STOP */ case TASK_STATE_ERROR : /* LCOV_EXCL_START */ - ++error; + ++soft_error; goto bail; /* LCOV_EXCL_STOP */ } @@ -1385,9 +1385,9 @@ end: state_usage_print(state); - if (error || silent_error || io_error) { + if (soft_error || silent_error || io_error) { msg_status("\n"); - msg_status("%8u file errors\n", error); + msg_status("%8u soft errors\n", soft_error); msg_status("%8u io errors\n", io_error); msg_status("%8u data errors\n", silent_error); } else { @@ -1396,21 +1396,21 @@ end: msg_status("Everything OK\n"); } - if (error) - log_fatal("WARNING! Unexpected file errors!\n"); + if (soft_error) + log_fatal("WARNING! Unexpected soft errors!\n"); if (io_error) log_fatal("DANGER! Unexpected input/output errors! The failing blocks are now marked as bad!\n"); if (silent_error) - log_fatal("DANGER! Unexpected data errors! The failing blocks are now marked as bad!\n"); + log_fatal("DANGER! Unexpected silent data errors! The failing blocks are now marked as bad!\n"); if (io_error || silent_error) { log_fatal("Use 'snapraid status' to list the bad blocks.\n"); log_fatal("Use 'snapraid -e fix' to recover.\n"); } - log_tag("summary:error_file:%u\n", error); + log_tag("summary:error_soft:%u\n", soft_error); log_tag("summary:error_io:%u\n", io_error); log_tag("summary:error_data:%u\n", silent_error); - if (error + silent_error + io_error == 0) + if (soft_error + silent_error + io_error == 0) log_tag("summary:exit:ok\n"); else if (silent_error + io_error == 0) log_tag("summary:exit:warning\n"); @@ -1434,7 +1434,7 @@ bail: if (errno == EIO) { ++io_error; } else { - ++error; + ++soft_error; } /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ @@ -1453,10 +1453,10 @@ bail: free(block_enabled); if (state->opt.expect_recoverable) { - if (error + silent_error + io_error == 0) + if (soft_error + silent_error + io_error == 0) return -1; } else { - if (error + silent_error + io_error != 0) + if (soft_error + silent_error + io_error != 0) return -1; } return 0; @@ -1470,7 +1470,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t data_off_t size; int ret; struct snapraid_parity_handle parity_handle[LEV_MAX]; - unsigned unrecoverable_error; + unsigned process_error; unsigned l; int skip_sync = 0; @@ -1545,7 +1545,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t } } - unrecoverable_error = 0; + process_error = 0; if (state->opt.prehash) { msg_progress("Hashing...\n"); @@ -1553,7 +1553,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t ret = state_hash_process(state, blockstart, blockmax, &skip_sync); if (ret == -1) { /* LCOV_EXCL_START */ - ++unrecoverable_error; + ++process_error; /* continue, in case also doing the sync if ::skip_sync is not set */ /* LCOV_EXCL_STOP */ } @@ -1619,7 +1619,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t ret = state_sync_process(state, parity_handle, blockstart, blockmax); if (ret == -1) { /* LCOV_EXCL_START */ - ++unrecoverable_error; + ++process_error; /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ } @@ -1635,14 +1635,13 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t 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; + ++process_error; /* continue, as we are already exiting */ /* LCOV_EXCL_STOP */ } } - /* abort if required */ - if (unrecoverable_error != 0) + if (process_error != 0) return -1; return 0; } diff --git a/doc/snapraid_log.1 b/doc/snapraid_log.1 index 8d0150a3..fea6107a 100644 --- a/doc/snapraid_log.1 +++ b/doc/snapraid_log.1 @@ -956,7 +956,7 @@ Also the error tags are possible. .SS Summary Tags These tags provide summary statistics at the end of the command. .TP -.B hash_summary:error_file: +.B hash_summary:error_soft: Logs the total count of file\-related errors that caused a block to be skipped during the hashing phase. These are often due to file changes (missing, size/time change) during the @@ -969,7 +969,7 @@ Total number of file errors (uint). .PD .RE .TP -.B summary:error_file: +.B summary:error_soft: Logs the total count of file\-related errors encountered during the process (e.g., missing files, file attribute changes). .RS 4 @@ -1013,8 +1013,8 @@ one of the following: No issues. The array is fully synchronized and healthy. .HP 4 .I warning -Some files were skipped due to modifications during -execution or permission issues. No hardware risk. +Some files were skipped due to likely intentional +modifications. No hardware risk. .HP 4 .I error Critical failure. Indicates serious issues like I/O failures @@ -1023,7 +1023,8 @@ or filesystem inspection. .PD .RE .SH COMMAND CHECK/FIX TAGS -Tags specific for the \`check\` and \`fix\` commands. +Tags specific for the \`check\` and \`fix\` commands. For \`audit\` mode, +it\'s inteded \`check\` with the \`\-\-audit\-only\` option. Also the error tags are possible. .SS Fixed/Recovered Tags These tags log successful repairs during fix operations. @@ -1184,7 +1185,7 @@ These tags log the final status of files after processing. .TP .B status:unrecoverable:: Indicates that a file has unrecoverable errors and was renamed to -\`.unrecoverable\` (in fix mode) or cannot be recovered (in check mode). +\`.unrecoverable\` (fix) or cannot be recovered (check). .RS 4 .PD 0 .HP 4 @@ -1209,21 +1210,9 @@ The file path relative to disk root (escaped). .PD .RE .TP -.B status:damaged:: -Indicates that a file is damaged (in audit\-only mode, e.g., using \`check\`). -.RS 4 -.PD 0 -.HP 4 -.I -The name of the disk. -.HP 4 -.I -The file path relative to disk root (escaped). -.PD -.RE -.TP .B status:recoverable:: -Logs that a file has errors but could be recovered in fix mode. +Logs that a file has errors but could be recovered with a +\`fix\` (check). .RS 4 .PD 0 .HP 4 @@ -1236,7 +1225,7 @@ The file path relative to disk root (escaped). .RE .TP .B status:correct:: -Indicates that a file passed all checks successfully (verbose mode only). +Indicates that a file passed all checks successfully (verbose). .RS 4 .PD 0 .HP 4 @@ -1250,18 +1239,42 @@ The file path relative to disk root (escaped). .SS Summary Tags These tags provide summary statistics at the end of the command. .TP -.B summary:error: -Logs the total number of errors encountered. +.B summary:error_soft: +Logs the total count of file\-related errors encountered during +the process (e.g., missing files, file attribute changes). .RS 4 .PD 0 .HP 4 -.I -Total number of errors (uint). +.I +The total number of file errors encountered (uint). +.PD +.RE +.TP +.B summary:error_io: +Logs the total count of input/output errors encountered on +data or parity disks. +.RS 4 +.PD 0 +.HP 4 +.I +The total number of I/O errors encountered (uint). +.PD +.RE +.TP +.B summary:error_data: +Logs the total count of \`silent data errors\` (data blocks +not matching their expected hash) encountered during the sync +process. +.RS 4 +.PD 0 +.HP 4 +.I +The total number of silent data errors encountered (uint). .PD .RE .TP .B summary:error_recovered: -Logs the total number of errors successfully recovered (fix mode only). +Logs the total number of errors successfully recovered (fix). .RS 4 .PD 0 .HP 4 @@ -1270,8 +1283,18 @@ Number of recovered errors (uint). .PD .RE .TP +.B summary:error_recoverable: +Logs the total number of errors that can be recovered (check). +.RS 4 +.PD 0 +.HP 4 +.I +Number of recoverable errors (uint). +.PD +.RE +.TP .B summary:error_unrecoverable: -Logs the total number of unrecoverable errors (not in audit\-only mode). +Logs the total number of unrecoverable errors (fix/check). .RS 4 .PD 0 .HP 4 @@ -1287,22 +1310,29 @@ the following: .PD 0 .HP 4 .I ok -Indicates that the operation completed with no errors. +Indicates that the operation completed with no errors (audit). +.HP 4 +.I warning +Some files were different than expected, likely caused +by intentional modification of the files. +No hardware risk (audit). +.HP 4 +.I error +Critical failure. Indicates serious issues like I/O failures +or silent data corruption. Requires immediate hardware +or filesystem inspection (audit). .HP 4 .I recovered Indicates that the operation completed with all -errors successfully recovered (fix mode only). +errors successfully recovered (fix). .HP 4 .I recoverable Indicates that errors were found but are all -recoverable (check mode only). +recoverable (check). .HP 4 .I unrecoverable Indicates that unrecoverable errors were -found. -.HP 4 -.I error -Indicates that errors were found (audit\-only mode). +found (check/fix). .PD .RE .SH COMMAND LIST TAGS @@ -1801,30 +1831,6 @@ The integer exit status returned by the process (int). .PD .RE -.SH STATUS TAGS -These tags log the recovery status of files after a \`check\` or \`fix\` -command. -.TP -.B status:unrecoverable:: -The file is not recoverable. If a \`fix\` command was run, it -was also renamed with the \`.unrecoverable\` extension. -.RS 4 -.PD 0 -.HP 4 -.I -The name of the disk. -.HP 4 -.I -The file path relative to disk root (escaped). -.PD -.RE -.TP -.B status:recovered:: -The file was recovered by a \`fix\` command. -.TP -.B status:recoverable:: -The file is recoverable, and will be recovered by a \`fix\` -command. .SH ERROR TAGS These tags report specific errors that occur on data disks during the commands that access files and parities. diff --git a/doc/snapraid_log.d b/doc/snapraid_log.d index 39e2ed1b..6db1b807 100644 --- a/doc/snapraid_log.d +++ b/doc/snapraid_log.d @@ -636,7 +636,7 @@ Command Sync/Scrub Tags Summary Tags These tags provide summary statistics at the end of the command. - =hash_summary:error_file: + =hash_summary:error_soft: Logs the total count of file-related errors that caused a block to be skipped during the hashing phase. These are often due to file changes (missing, size/time change) during the @@ -644,7 +644,7 @@ Command Sync/Scrub Tags - Total number of file errors (uint). - =summary:error_file: + =summary:error_soft: Logs the total count of file-related errors encountered during the process (e.g., missing files, file attribute changes). @@ -668,14 +668,15 @@ Command Sync/Scrub Tags one of the following: ok - No issues. The array is fully synchronized and healthy. - warning - Some files were skipped due to modifications during - execution or permission issues. No hardware risk. + warning - Some files were skipped due to likely intentional + modifications. No hardware risk. error - Critical failure. Indicates serious issues like I/O failures or silent data corruption. Requires immediate hardware or filesystem inspection. Command Check/Fix Tags - Tags specific for the `check` and `fix` commands. + Tags specific for the `check` and `fix` commands. For `audit` mode, + it's inteded `check` with the `--audit-only` option. Also the error tags are possible. Fixed/Recovered Tags @@ -761,7 +762,7 @@ Command Check/Fix Tags =status:unrecoverable:: Indicates that a file has unrecoverable errors and was renamed to - `.unrecoverable` (in fix mode) or cannot be recovered (in check mode). + `.unrecoverable` (fix) or cannot be recovered (check). - The name of the disk. - The file path relative to disk root (escaped). @@ -772,20 +773,15 @@ Command Check/Fix Tags - The name of the disk. - The file path relative to disk root (escaped). - =status:damaged:: - Indicates that a file is damaged (in audit-only mode, e.g., using `check`). - - - The name of the disk. - - The file path relative to disk root (escaped). - =status:recoverable:: - Logs that a file has errors but could be recovered in fix mode. + Logs that a file has errors but could be recovered with a + `fix` (check). - The name of the disk. - The file path relative to disk root (escaped). =status:correct:: - Indicates that a file passed all checks successfully (verbose mode only). + Indicates that a file passed all checks successfully (verbose). - The name of the disk. - The file path relative to disk root (escaped). @@ -793,33 +789,57 @@ Command Check/Fix Tags Summary Tags These tags provide summary statistics at the end of the command. - =summary:error: - Logs the total number of errors encountered. + =summary:error_soft: + Logs the total count of file-related errors encountered during + the process (e.g., missing files, file attribute changes). + + - The total number of file errors encountered (uint). - - Total number of errors (uint). + =summary:error_io: + Logs the total count of input/output errors encountered on + data or parity disks. + + - The total number of I/O errors encountered (uint). + + =summary:error_data: + Logs the total count of `silent data errors` (data blocks + not matching their expected hash) encountered during the sync + process. + + - The total number of silent data errors encountered (uint). =summary:error_recovered: - Logs the total number of errors successfully recovered (fix mode only). + Logs the total number of errors successfully recovered (fix). - Number of recovered errors (uint). + + =summary:error_recoverable: + Logs the total number of errors that can be recovered (check). + + - Number of recoverable errors (uint). =summary:error_unrecoverable: - Logs the total number of unrecoverable errors (not in audit-only mode). + Logs the total number of unrecoverable errors (fix/check). - Number of unrecoverable errors (uint). =summary:exit: Logs the overall exit status of the command. The `status` is one of the following: - - ok - Indicates that the operation completed with no errors. + + ok - Indicates that the operation completed with no errors (audit). + warning - Some files were different than expected, likely caused + by intentional modification of the files. + No hardware risk (audit). + error - Critical failure. Indicates serious issues like I/O failures + or silent data corruption. Requires immediate hardware + or filesystem inspection (audit). recovered - Indicates that the operation completed with all - errors successfully recovered (fix mode only). + errors successfully recovered (fix). recoverable - Indicates that errors were found but are all - recoverable (check mode only). + recoverable (check). unrecoverable - Indicates that unrecoverable errors were - found. - error - Indicates that errors were found (audit-only mode). + found (check/fix). Command List Tags This section describes the tags output with the `list` command. @@ -1146,24 +1166,6 @@ Device Status Tags - The integer exit status returned by the process (int). -Status Tags - These tags log the recovery status of files after a `check` or `fix` - command. - - =status:unrecoverable:: - The file is not recoverable. If a `fix` command was run, it - was also renamed with the `.unrecoverable` extension. - - - The name of the disk. - - The file path relative to disk root (escaped). - - =status:recovered:: - The file was recovered by a `fix` command. - - =status:recoverable:: - The file is recoverable, and will be recovered by a `fix` - command. - Error Tags These tags report specific errors that occur on data disks during the commands that access files and parities. diff --git a/doc/snapraid_log.txt b/doc/snapraid_log.txt index a1023e2d..19a4ad30 100644 --- a/doc/snapraid_log.txt +++ b/doc/snapraid_log.txt @@ -664,7 +664,7 @@ Also the error tags are possible. ---- 9.0.1 Summary Tags ---- These tags provide summary statistics at the end of the command. - hash_summary:error_file: + hash_summary:error_soft: Logs the total count of file-related errors that caused a block to be skipped during the hashing phase. These are often due to file changes (missing, size/time change) during the @@ -672,7 +672,7 @@ These tags provide summary statistics at the end of the command. - Total number of file errors (uint). - summary:error_file: + summary:error_soft: Logs the total count of file-related errors encountered during the process (e.g., missing files, file attribute changes). @@ -696,8 +696,8 @@ These tags provide summary statistics at the end of the command. one of the following: ok - No issues. The array is fully synchronized and healthy. - warning - Some files were skipped due to modifications during - execution or permission issues. No hardware risk. + warning - Some files were skipped due to likely intentional + modifications. No hardware risk. error - Critical failure. Indicates serious issues like I/O failures or silent data corruption. Requires immediate hardware or filesystem inspection. @@ -706,7 +706,8 @@ These tags provide summary statistics at the end of the command. 10 COMMAND CHECK/FIX TAGS ========================= -Tags specific for the `check` and `fix` commands. +Tags specific for the `check` and `fix` commands. For `audit` mode, +it's inteded `check` with the `--audit-only` option. Also the error tags are possible. ---- 10.0.1 Fixed/Recovered Tags ---- @@ -792,7 +793,7 @@ These tags log the final status of files after processing. status:unrecoverable:: Indicates that a file has unrecoverable errors and was renamed to - `.unrecoverable` (in fix mode) or cannot be recovered (in check mode). + `.unrecoverable` (fix) or cannot be recovered (check). - The name of the disk. - The file path relative to disk root (escaped). @@ -803,20 +804,15 @@ These tags log the final status of files after processing. - The name of the disk. - The file path relative to disk root (escaped). - status:damaged:: - Indicates that a file is damaged (in audit-only mode, e.g., using `check`). - - - The name of the disk. - - The file path relative to disk root (escaped). - status:recoverable:: - Logs that a file has errors but could be recovered in fix mode. + Logs that a file has errors but could be recovered with a + `fix` (check). - The name of the disk. - The file path relative to disk root (escaped). status:correct:: - Indicates that a file passed all checks successfully (verbose mode only). + Indicates that a file passed all checks successfully (verbose). - The name of the disk. - The file path relative to disk root (escaped). @@ -824,18 +820,37 @@ These tags log the final status of files after processing. ---- 10.0.4 Summary Tags ---- These tags provide summary statistics at the end of the command. - summary:error: - Logs the total number of errors encountered. + summary:error_soft: + Logs the total count of file-related errors encountered during + the process (e.g., missing files, file attribute changes). - - Total number of errors (uint). + - The total number of file errors encountered (uint). + + summary:error_io: + Logs the total count of input/output errors encountered on + data or parity disks. + + - The total number of I/O errors encountered (uint). + + summary:error_data: + Logs the total count of `silent data errors` (data blocks + not matching their expected hash) encountered during the sync + process. + + - The total number of silent data errors encountered (uint). summary:error_recovered: - Logs the total number of errors successfully recovered (fix mode only). + Logs the total number of errors successfully recovered (fix). - Number of recovered errors (uint). + summary:error_recoverable: + Logs the total number of errors that can be recovered (check). + + - Number of recoverable errors (uint). + summary:error_unrecoverable: - Logs the total number of unrecoverable errors (not in audit-only mode). + Logs the total number of unrecoverable errors (fix/check). - Number of unrecoverable errors (uint). @@ -843,14 +858,19 @@ These tags provide summary statistics at the end of the command. Logs the overall exit status of the command. The `status` is one of the following: - ok - Indicates that the operation completed with no errors. + ok - Indicates that the operation completed with no errors (audit). + warning - Some files were different than expected, likely caused + by intentional modification of the files. + No hardware risk (audit). + error - Critical failure. Indicates serious issues like I/O failures + or silent data corruption. Requires immediate hardware + or filesystem inspection (audit). recovered - Indicates that the operation completed with all - errors successfully recovered (fix mode only). + errors successfully recovered (fix). recoverable - Indicates that errors were found but are all - recoverable (check mode only). + recoverable (check). unrecoverable - Indicates that unrecoverable errors were - found. - error - Indicates that errors were found (audit-only mode). + found (check/fix). 11 COMMAND LIST TAGS @@ -1196,28 +1216,7 @@ command execution with the `smartctl` command. process (int). -17 STATUS TAGS -============== - -These tags log the recovery status of files after a `check` or `fix` -command. - - status:unrecoverable:: - The file is not recoverable. If a `fix` command was run, it - was also renamed with the `.unrecoverable` extension. - - - The name of the disk. - - The file path relative to disk root (escaped). - - status:recovered:: - The file was recovered by a `fix` command. - - status:recoverable:: - The file is recoverable, and will be recovered by a `fix` - command. - - -18 ERROR TAGS +17 ERROR TAGS ============= These tags report specific errors that occur on data disks during the