From e99f43c8cabcf18c87f6dc13dc413841dacbe237 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Mon, 19 Jan 2026 14:33:55 +0100 Subject: [PATCH] Log both protocol and medium errors --- cmdline/device.c | 26 ++++++++++++++++---------- cmdline/portable.h | 20 ++++++++++++++++++-- cmdline/support.c | 12 ++++++++++-- doc/snapraid_log.1 | 23 +++++++++++++++++++++-- doc/snapraid_log.d | 18 ++++++++++++++++-- doc/snapraid_log.txt | 18 ++++++++++++++++-- 6 files changed, 97 insertions(+), 20 deletions(-) diff --git a/cmdline/device.c b/cmdline/device.c index 2cac8651..88adb418 100644 --- a/cmdline/device.c +++ b/cmdline/device.c @@ -565,8 +565,10 @@ static void state_smart_log(devinfo_t* devinfo, double afr) unsigned j; log_tag("smart:%s:%s\n", devinfo->file, devinfo->name); - if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED) - log_tag("attr:%s:%s:error:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR]); + if (devinfo->smart[SMART_ERROR_PROTOCOL] != SMART_UNASSIGNED) + log_tag("attr:%s:%s:error_protocol:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR_PROTOCOL]); + if (devinfo->smart[SMART_ERROR_MEDIUM] != SMART_UNASSIGNED) + log_tag("attr:%s:%s:error_medium:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR_MEDIUM]); if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED) log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS], devinfo->smart[SMART_FLAGS]); @@ -655,25 +657,28 @@ static void state_smart(struct snapraid_state* state, unsigned n, tommy_list* lo else printf(" -"); + uint64_t error_count = 0; + if (devinfo->smart[SMART_ERROR_PROTOCOL] != SMART_UNASSIGNED && devinfo->smart[SMART_ERROR_PROTOCOL] != 0) + error_count += devinfo->smart[SMART_ERROR_PROTOCOL]; + if (devinfo->smart[SMART_ERROR_MEDIUM] != SMART_UNASSIGNED && devinfo->smart[SMART_ERROR_MEDIUM] != 0) + error_count += devinfo->smart[SMART_ERROR_MEDIUM]; if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED) flag = devinfo->smart[SMART_FLAGS]; else flag = 0; + if (flag & SMARTCTL_FLAG_FAIL) printf(" FAIL"); else if (flag & SMARTCTL_FLAG_PREFAIL) printf(" PREFAIL"); else if (flag & SMARTCTL_FLAG_PREFAIL_LOGGED) printf(" logfail"); - else if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED - && devinfo->smart[SMART_ERROR] != 0) - printf("%8" PRIu64, devinfo->smart[SMART_ERROR]); - else if (flag & SMARTCTL_FLAG_ERROR) + else if (error_count != 0) { + printf("%8" PRIu64, error_count); + } else if (flag & SMARTCTL_FLAG_ERROR) printf(" logerr"); else if (flag & SMARTCTL_FLAG_ERROR_LOGGED) printf(" selferr"); - else if (devinfo->smart[SMART_ERROR] == 0) - printf(" 0"); else printf(" -"); @@ -910,12 +915,13 @@ int devtest(tommy_list* high, tommy_list* low, int operation) pathcpy(entry->name, sizeof(entry->name), devinfo->name); entry->info[INFO_SIZE] = count * TERA; entry->info[INFO_ROTATION_RATE] = 7200; - entry->smart[SMART_ERROR] = 0; + entry->smart[SMART_ERROR_MEDIUM] = 0; + entry->smart[SMART_ERROR_PROTOCOL] = 0; entry->smart[SMART_FLAGS] = SMART_UNASSIGNED; entry->smart[SMART_TEMPERATURE_CELSIUS] = 27; switch (count) { - case 3 : entry->smart[SMART_ERROR] = 1; break; + case 3 : entry->smart[SMART_ERROR_PROTOCOL] = 1; break; case 4 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_UNSUPPORTED; break; case 5 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_COMMAND; break; case 6 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_OPEN; break; diff --git a/cmdline/portable.h b/cmdline/portable.h index 2b142d3b..b34ca639 100644 --- a/cmdline/portable.h +++ b/cmdline/portable.h @@ -433,12 +433,28 @@ int randomize(void* ptr, size_t size); #define SMART_TEMPERATURE_CELSIUS 194 #define SMART_FLAGS 256 /**< Flags returned by smartctl. */ -#define SMART_ERROR 257 /**< ATA Error count. */ + +/* + * Counts command, transport, or controller-level errors reported by the device. + * These reflect failed I/O operations not directly caused by media defects + * (for example interface, firmware, or power-related errors). + * This counter is cumulative and never resets to zero, even if the underlying + * error condition is resolved. + */ +#define SMART_ERROR_PROTOCOL 257 + +/* + * Counts media-level errors where data could not be reliably read or written. + * These indicate actual storage surface or flash failures and may imply data loss. + * This counter is cumulative and never resets to zero, even if the underlying + * error condition is resolved. + */ +#define SMART_ERROR_MEDIUM 258 /** * SMART attributes count. */ -#define SMART_COUNT 258 +#define SMART_COUNT 259 /** * Info attributes. diff --git a/cmdline/support.c b/cmdline/support.c index 4704a537..433d30ac 100644 --- a/cmdline/support.c +++ b/cmdline/support.c @@ -1779,9 +1779,17 @@ int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* sm } else if (smatch(s, "ID#") == 0) { inside = 1; } else if (smatch(s, "No Errors Logged") == 0) { - smart[SMART_ERROR] = 0; + smart[SMART_ERROR_PROTOCOL] = 0; } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { - smart[SMART_ERROR] = raw; + smart[SMART_ERROR_PROTOCOL] = raw; + } else if (sscanf(s, "Media and Data Integrity Errors: %" SCNu64, &raw) == 1) { + smart[SMART_ERROR_MEDIUM] = raw; + } else if (sscanf(s, "Error Information Log Entries: %" SCNu64, &raw) == 1) { + smart[SMART_ERROR_PROTOCOL] = raw; + } else if (sscanf(s, "Medium error count: %" SCNu64, &raw) == 1) { + smart[SMART_ERROR_MEDIUM] = raw; + } else if (sscanf(s, "Non-medium error count: %" SCNu64, &raw) == 1) { + smart[SMART_ERROR_PROTOCOL] = raw; } else if (inside) { if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) { /* LCOV_EXCL_START */ diff --git a/doc/snapraid_log.1 b/doc/snapraid_log.1 index 78e4025e..e14b5657 100644 --- a/doc/snapraid_log.1 +++ b/doc/snapraid_log.1 @@ -1611,8 +1611,27 @@ The disk size in bytes (uint). .PD .RE .TP -.B attr::[/]:error: -Logs the total error count. +.B attr::[/]:error_protocol: +Counts command, transport, or controller\-level errors reported +by the device. These reflect failed I/O operations not directly +caused by media defects (for example interface, firmware, or +power\-related errors). +This counter is cumulative and never resets to zero, even if +the underlying error condition is resolved. +.RS 4 +.PD 0 +.HP 4 +.I +The total error count (uint). +.PD +.RE +.TP +.B attr::[/]:error_medium: +Counts media\-level errors where data could not be reliably +read or written. These indicate actual storage surface or +flash failures and may imply data loss. +This counter is cumulative and never resets to zero, even if +the underlying error condition is resolved. .RS 4 .PD 0 .HP 4 diff --git a/doc/snapraid_log.d b/doc/snapraid_log.d index f13ff78e..9375c0e9 100644 --- a/doc/snapraid_log.d +++ b/doc/snapraid_log.d @@ -1018,8 +1018,22 @@ Command Smart And Probe Tags - The disk size in bytes (uint). - =attr::[/]:error: - Logs the total error count. + =attr::[/]:error_protocol: + Counts command, transport, or controller-level errors reported + by the device. These reflect failed I/O operations not directly + caused by media defects (for example interface, firmware, or + power-related errors). + This counter is cumulative and never resets to zero, even if + the underlying error condition is resolved. + + - The total error count (uint). + + =attr::[/]:error_medium: + Counts media-level errors where data could not be reliably + read or written. These indicate actual storage surface or + flash failures and may imply data loss. + This counter is cumulative and never resets to zero, even if + the underlying error condition is resolved. - The total error count (uint). diff --git a/doc/snapraid_log.txt b/doc/snapraid_log.txt index 8e04c6d3..523b5a02 100644 --- a/doc/snapraid_log.txt +++ b/doc/snapraid_log.txt @@ -1064,8 +1064,22 @@ Tags logging specific disk identification and attribute values. - The disk size in bytes (uint). - attr::[/]:error: - Logs the total error count. + attr::[/]:error_protocol: + Counts command, transport, or controller-level errors reported + by the device. These reflect failed I/O operations not directly + caused by media defects (for example interface, firmware, or + power-related errors). + This counter is cumulative and never resets to zero, even if + the underlying error condition is resolved. + + - The total error count (uint). + + attr::[/]:error_medium: + Counts media-level errors where data could not be reliably + read or written. These indicate actual storage surface or + flash failures and may imply data loss. + This counter is cumulative and never resets to zero, even if + the underlying error condition is resolved. - The total error count (uint).