From 276b06f0a69e42888f70eb616191e31ff6f4d0c1 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Tue, 13 Jan 2026 23:45:31 +0100 Subject: [PATCH] Extend the log error tags to differentiate between io/silent to generic errors --- cmdline/scrub.c | 36 +++++++++++++------- cmdline/sync.c | 58 ++++++++++++++++++++++---------- doc/snapraid_log.1 | 79 +++++++++++++++++++++++++++++++------------- doc/snapraid_log.d | 71 +++++++++++++++++++++++++-------------- doc/snapraid_log.txt | 46 +++++++++++++++++--------- makeuncrustify.sh | 2 +- 6 files changed, 199 insertions(+), 93 deletions(-) diff --git a/cmdline/scrub.c b/cmdline/scrub.c index 4c9362a8..09239511 100644 --- a/cmdline/scrub.c +++ b/cmdline/scrub.c @@ -143,7 +143,7 @@ static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_ta /* 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_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); @@ -165,7 +165,7 @@ static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_ta if (ret == -1) { if (errno == EIO) { /* LCOV_EXCL_START */ - log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + 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("Stopping at block %u\n", blockcur); @@ -197,7 +197,8 @@ 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) { 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_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); task->state = TASK_STATE_IOERROR_CONTINUE; return; @@ -228,7 +229,8 @@ static void scrub_parity_reader(struct snapraid_worker* worker, struct snapraid_ ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error); if (ret == -1) { if (errno == EIO) { - log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno)); + 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); task->state = TASK_STATE_IOERROR_CONTINUE; return; @@ -482,13 +484,13 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); - log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); - /* 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 bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); ++error; error_on_this_block = 1; } else { + log_tag("error_data:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); log_error("Data error in file '%s' at position '%u', diff bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE * 8); ++silent_error; silent_error_on_this_block = 1; @@ -575,14 +577,14 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par if (buffer_recov[l] && memcmp(buffer[diskmax + l], buffer_recov[l], state->block_size) != 0) { unsigned diff = memdiff(buffer[diskmax + l], buffer_recov[l], state->block_size); - log_tag("parity_error:%u:%s: Data error, diff bits %u/%u\n", blockcur, lev_config_name(l), diff, state->block_size * 8); - /* 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 bits %u/%u\n", blockcur, lev_config_name(l), diff, state->block_size * 8); ++error; error_on_this_block = 1; } else { - log_fatal("Data error in parity '%s' at position '%u', diff bits %u/%u\n", lev_config_name(l), blockcur, diff, state->block_size * 8); + log_tag("parity_error_data:%u:%s: Data error, diff bits %u/%u\n", blockcur, lev_config_name(l), diff, state->block_size * 8); + log_error("Data error in parity '%s' at position '%u', diff bits %u/%u\n", lev_config_name(l), blockcur, diff, state->block_size * 8); ++silent_error; silent_error_on_this_block = 1; } @@ -701,6 +703,8 @@ end: log_tag("summary:error_data:%u\n", silent_error); if (error + silent_error + io_error == 0) log_tag("summary:exit:ok\n"); + else if (silent_error + io_error == 0) + log_tag("summary:exit:alert\n"); else log_tag("summary:exit:error\n"); log_flush(); @@ -715,9 +719,17 @@ bail: ret = handle_close(&handle[j]); if (ret == -1) { /* LCOV_EXCL_START */ - log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); - log_fatal("DANGER! Unexpected close error in a data disk.\n"); - ++error; + 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 */ /* LCOV_EXCL_STOP */ } diff --git a/cmdline/sync.c b/cmdline/sync.c index 214af597..ba780a91 100644 --- a/cmdline/sync.c +++ b/cmdline/sync.c @@ -139,7 +139,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta /* 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", i, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + 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); @@ -161,7 +161,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta if (ret == -1) { if (errno == EIO) { /* LCOV_EXCL_START */ - log_tag("error:%u:%s:%s: Open EIO error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + 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); @@ -207,13 +207,15 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta || STAT_NSEC(&handle[j].st) != file->mtime_nsec || handle[j].st.st_ino != file->inode ) { - log_tag("error:%u:%s:%s: Unexpected attribute change\n", i, disk->name, esc_tag(file->sub, esc_buffer)); if (handle[j].st.st_size != file->size) { + log_tag("error:%u:%s:%s: Unexpected size change\n", i, disk->name, esc_tag(file->sub, esc_buffer)); log_error("Unexpected size change at file '%s' from %" PRIu64 " to %" PRIu64 ".\n", handle[j].path, file->size, (uint64_t)handle[j].st.st_size); } else if (handle[j].st.st_mtime != file->mtime_sec || STAT_NSEC(&handle[j].st) != file->mtime_nsec) { + log_tag("error:%u:%s:%s: Unexpected time change\n", i, disk->name, esc_tag(file->sub, esc_buffer)); log_error("Unexpected time change at file '%s' from %" PRIu64 ".%d to %" PRIu64 ".%d.\n", handle[j].path, file->mtime_sec, file->mtime_nsec, (uint64_t)handle[j].st.st_mtime, STAT_NSEC(&handle[j].st)); } else { + 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"); @@ -228,7 +230,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta if (read_size == -1) { /* LCOV_EXCL_START */ if (errno == EIO) { - log_tag("error:%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_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); @@ -265,7 +267,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta if (block_state == BLOCK_STATE_REP) { /* compare the hash */ if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { - log_tag("error:%u:%s:%s: Unexpected data change\n", i, disk->name, esc_tag(file->sub, esc_buffer)); + log_tag("error_data:%u:%s:%s: Unexpected data change\n", i, disk->name, esc_tag(file->sub, esc_buffer)); log_error("Data change at file '%s' at position '%u'\n", handle[j].path, file_pos); log_error("WARNING! Unexpected data modification of a file without parity!\n"); @@ -321,7 +323,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta /* 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", blockmax, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + 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); @@ -376,10 +378,20 @@ bail: struct snapraid_disk* disk = handle[j].disk; ret = handle_close(&handle[j]); if (ret == -1) { - 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"); - ++error; + /* LCOV_EXCL_START */ + 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 */ + /* LCOV_EXCL_STOP */ } } @@ -517,7 +529,7 @@ static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_tas /* 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_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); @@ -539,7 +551,7 @@ static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_tas if (ret == -1) { if (errno == EIO) { /* LCOV_EXCL_START */ - log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + 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); @@ -606,7 +618,8 @@ static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_tas if (task->read_size == -1) { /* LCOV_EXCL_START */ 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_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 open 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; @@ -642,7 +655,7 @@ static void sync_parity_writer(struct snapraid_worker* worker, struct snapraid_t if (ret == -1) { /* LCOV_EXCL_START */ if (errno == EIO) { - log_tag("parity_error:%u:%s: Write EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno)); + 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; @@ -974,7 +987,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari continue; } else { /* otherwise it's a BLK with silent error */ unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); - log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); + log_tag("error_data:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); log_error("Data error in file '%s' at position '%u', diff bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE * 8); /* save the failed block for the fix */ @@ -1077,7 +1090,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari if (ret == -1) { /* LCOV_EXCL_START */ if (errno == EIO) { - log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(l), strerror(errno)); + log_tag("parity_error_io:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(l), strerror(errno)); 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)); @@ -1411,6 +1424,8 @@ end: log_tag("summary:error_data:%u\n", silent_error); if (error + silent_error + io_error == 0) log_tag("summary:exit:ok\n"); + else if (silent_error + io_error == 0) + log_tag("summary:exit:alert\n"); else log_tag("summary:exit:error\n"); log_flush(); @@ -1425,8 +1440,17 @@ bail: ret = handle_close(&handle[j]); if (ret == -1) { /* LCOV_EXCL_START */ - log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); - log_fatal("DANGER! Unexpected close error in a data disk.\n"); + 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 */ diff --git a/doc/snapraid_log.1 b/doc/snapraid_log.1 index 418226ae..4a2f2afd 100644 --- a/doc/snapraid_log.1 +++ b/doc/snapraid_log.1 @@ -309,25 +309,32 @@ is assumed to be correct. These tags provide a final count of all detected changes. .TP .B summary:equal: -Total number of equal (unchanged) files/links/firs found (uint). +Total number of files/dirs/links whose metadata and data match +the current parity (uint). .TP .B summary:added: -Total number of new files/links/dirs found (uint). +Total number of new brand new files/dirs/links that have no +relationship to existing parity (uint). .TP .B summary:removed: -Total number of removed files/links/dirs found (uint). +Total number of files/dirs/links that existed in the last sync +but are now missing (uint). .TP .B summary:updated: -Total number of updated files/links found (uint). +Total number of existing files where the timestamp or size has +changed (uint). .TP .B summary:moved: -Total number of moved files found (uint). +Total number of files relocated to a new path but retaining +the same inode (uint). .TP .B summary:copied: -Total number of copied files found (uint). +Total number of new files created by copying an existing +protected file to a new path (uint). .TP .B summary:restored: -Total number of restored files found (uint). +Total number of new files matching a parity entry by +name/time/size but with a new inode (uint). .TP .B summary:exit:equal A zero\-argument tag indicating that no differences were found. @@ -846,8 +853,8 @@ Unix timestamp of the scrub/sync. Number of blocks processed at this timestamp. .HP 4 .I -\[dq]scrubbed\[dq] (for blocks verified to be correct) or -\[dq]new\[dq] (for synced blocks that haven\'t been scrubbed yet). +\`scrubbed\` (for blocks verified to be correct) or +\`new\` (for synced blocks that haven\'t been scrubbed yet). .PD .RE .TP @@ -929,7 +936,7 @@ The total number of I/O errors encountered (uint). .RE .TP .B summary:error_data: -Logs the total count of \[dq]silent data errors\[dq] (data blocks +Logs the total count of \`silent data errors\` (data blocks not matching their expected hash) encountered during the sync process. .RS 4 @@ -947,10 +954,16 @@ one of the following: .PD 0 .HP 4 .I ok -No errors were found. +No issues. The array is fully synchronized and healthy. +.HP 4 +.I alert +Incomplete. Some files were skipped due to modifications +during execution or permission issues. No hardware risk. .HP 4 .I error -If any errors were found (file, I/O, or data errors). +Critical failure. Indicates serious issues like I/O failures +or silent data corruption. Requires immediate hardware +or filesystem inspection. .PD .RE .SH COMMAND CHECK/FIX TAGS @@ -989,7 +1002,7 @@ recomputed and written. The block position being processed (uint). .HP 4 .I -The name of the parity level (e.g., \[dq]parity\[dq], \[dq]2\-parity\[dq]). +The name of the parity level (e.g., \`parity\`, \`2\-parity\`). .HP 4 .I A descriptive message indicating the nature of the fix @@ -1217,22 +1230,22 @@ the following: .RS 4 .PD 0 .HP 4 -.I \`ok\` +.I ok Indicates that the operation completed with no errors. .HP 4 -.I \`recovered\` +.I recovered Indicates that the operation completed with all errors successfully recovered (fix mode only). .HP 4 -.I \`recoverable\` +.I recoverable Indicates that errors were found but are all recoverable (check mode only). .HP 4 -.I \`unrecoverable\` +.I unrecoverable Indicates that unrecoverable errors were found. .HP 4 -.I \`error\` +.I error Indicates that errors were found (audit\-only mode). .PD .RE @@ -1555,9 +1568,9 @@ rotational speed in RPM. .B attr::[/]:flags:: Logs the SMART status flags from the \`smartctl\` utility. Per the smartctl manpage, these flags are bit\-mapped -to indicate specific issues like \[dq]Command line did not parse\[dq], -\[dq]Device could not be opened\[dq], or \[dq]SMART status check -returned \'DISK FAILING\'\[dq]. +to indicate specific issues like \`Command line did not parse\`, +\`Device could not be opened\`, or \`SMART status check +returned \'DISK FAILING\'\`. .RS 4 .PD 0 .HP 4 @@ -1687,12 +1700,22 @@ process. These tags report specific errors that occur on data disks during the commands that access files and parities. .TP -.B error:::: +.B error[_io|_data]:::: Logs file access errors (open, read, file changed) during the data disk read operation for parity calculation or verification. .RS 4 .PD 0 .HP 4 +.I _io +Indicates a physical Input/Output error. +The disk was unable to read or write a specific block, +typically signaling a failing sector or cable issue. +.HP 4 +.I _data +Indicates the data was read successfully but failed +the checksum/hash verification. This signals \`silent\` +corruption or an unsuccessful parity match. +.HP 4 .I The zero\-based index of the block where the error occurred (uint). .HP 4 @@ -1710,11 +1733,21 @@ error (e.g., \`Open/Read/Write EIO error\`, \`Open/Read/Write error\`, .PD .RE .TP -.B parity_error::: +.B parity_error[_io|_data]::: Logs errors during parity disk read or write operations. .RS 4 .PD 0 .HP 4 +.I _io +Indicates a physical Input/Output error. +The disk was unable to read or write a specific block, +typically signaling a failing sector or cable issue. +.HP 4 +.I _data +Indicates the data was read successfully but failed +the checksum/hash verification. This signals \`silent\` +corruption or an unsuccessful parity match. +.HP 4 .I The zero\-based index of the block where the error occurred (uint). .HP 4 diff --git a/doc/snapraid_log.d b/doc/snapraid_log.d index cae1638a..af37f6ba 100644 --- a/doc/snapraid_log.d +++ b/doc/snapraid_log.d @@ -226,25 +226,32 @@ Scan Tags These tags provide a final count of all detected changes. =summary:equal: - Total number of equal (unchanged) files/links/firs found (uint). + Total number of files/dirs/links whose metadata and data match + the current parity (uint). =summary:added: - Total number of new files/links/dirs found (uint). + Total number of new brand new files/dirs/links that have no + relationship to existing parity (uint). =summary:removed: - Total number of removed files/links/dirs found (uint). + Total number of files/dirs/links that existed in the last sync + but are now missing (uint). =summary:updated: - Total number of updated files/links found (uint). + Total number of existing files where the timestamp or size has + changed (uint). =summary:moved: - Total number of moved files found (uint). + Total number of files relocated to a new path but retaining + the same inode (uint). =summary:copied: - Total number of copied files found (uint). + Total number of new files created by copying an existing + protected file to a new path (uint). =summary:restored: - Total number of restored files found (uint). + Total number of new files matching a parity entry by + name/time/size but with a new inode (uint). =summary:exit:equal A zero-argument tag indicating that no differences were found. @@ -568,8 +575,8 @@ Command Status Tags