From fca525e5c67bbfc97e08ae81c15599005ded901c Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Thu, 25 Dec 2025 21:03:46 +0100 Subject: [PATCH] Get SMART attributes also in probe, but only if the disk is already spinning --- cmdline/unix.c | 40 +++++++++++++++++++++++++--------------- doc/snapraid_log.1 | 8 ++++++-- doc/snapraid_log.d | 8 ++++++-- doc/snapraid_log.txt | 10 +++++++--- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/cmdline/unix.c b/cmdline/unix.c index 59934598..a5517b96 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -1533,7 +1533,7 @@ static void devattr(dev_t device, uint64_t* info, char* serial, char* vendor, ch * Get POWER state. */ #if HAVE_LINUX_DEVICE -static int devprobe(dev_t device, const char* name, const char* smartctl, int* power, uint64_t* info, char* serial, char* vendor, char* model) +static int devprobe(dev_t device, const char* name, const char* smartctl, int* power, uint64_t* smart, uint64_t* info, char* serial, char* vendor, char* model) { char cmd[PATH_MAX + 64]; char file[PATH_MAX]; @@ -1560,9 +1560,9 @@ static int devprobe(dev_t device, const char* name, const char* smartctl, int* p if (smartctl[0]) { char option[PATH_MAX]; snprintf(option, sizeof(option), smartctl, file); - snprintf(cmd, sizeof(cmd), "%s -n standby,3 -i %s", x, option); + snprintf(cmd, sizeof(cmd), "%s -n standby,3 -a %s", x, option); } else { - snprintf(cmd, sizeof(cmd), "%s -n standby,3 -i %s", x, file); + snprintf(cmd, sizeof(cmd), "%s -n standby,3 -a %s", x, file); } log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); @@ -1576,7 +1576,7 @@ static int devprobe(dev_t device, const char* name, const char* smartctl, int* p /* LCOV_EXCL_STOP */ } - if (smartctl_attribute(f, file, name, 0, info, serial, vendor, model) != 0) { + if (smartctl_attribute(f, file, name, smart, info, serial, vendor, model) != 0) { /* LCOV_EXCL_START */ pclose(f); log_tag("device:%s:%s:shell\n", file, name); @@ -1603,18 +1603,15 @@ static int devprobe(dev_t device, const char* name, const char* smartctl, int* p /* LCOV_EXCL_STOP */ } - if (WEXITSTATUS(ret) == 0) { - log_tag("attr:%s:%s:power:active\n", file, name); - *power = POWER_ACTIVE; - } else if (WEXITSTATUS(ret) == 3) { + if (WEXITSTATUS(ret) == 3) { log_tag("attr:%s:%s:power:standby\n", file, name); *power = POWER_STANDBY; } else { - /* LCOV_EXCL_START */ - log_tag("device:%s:%s:exit:%d\n", file, name, WEXITSTATUS(ret)); - log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret)); - return -1; - /* LCOV_EXCL_STOP */ + log_tag("attr:%s:%s:power:active\n", file, name); + *power = POWER_ACTIVE; + + /* store the return smartctl return value */ + smart[SMART_FLAGS] = WEXITSTATUS(ret); } return 0; @@ -1716,7 +1713,7 @@ static int devdownifup(dev_t device, const char* name, const char* smartctl, int { *power = POWER_UNKNOWN; - if (devprobe(device, name, smartctl, power, 0, 0, 0, 0) != 0) + if (devprobe(device, name, smartctl, power, 0, 0, 0, 0, 0) != 0) return -1; if (*power == POWER_ACTIVE) @@ -1888,6 +1885,19 @@ static void* thread_smart(void* arg) /* LCOV_EXCL_STOP */ } + /* + * Retrieve some attributes directly from the system. + * + * smartctl intentionally skips queries on devices in standby mode + * to prevent accidentally spinning them up. + */ + devattr(devinfo->device, devinfo->info, devinfo->serial, devinfo->family, devinfo->model); + + /* + * Retrieve access stat for the device + */ + devstat(devinfo->device, &devinfo->access_stat); + return 0; #else (void)arg; @@ -1903,7 +1913,7 @@ static void* thread_probe(void* arg) #if HAVE_LINUX_DEVICE devinfo_t* devinfo = arg; - if (devprobe(devinfo->device, devinfo->name, devinfo->smartctl, &devinfo->power, devinfo->info, devinfo->serial, devinfo->family, devinfo->model) != 0) { + if (devprobe(devinfo->device, devinfo->name, devinfo->smartctl, &devinfo->power, devinfo->smart, devinfo->info, devinfo->serial, devinfo->family, devinfo->model) != 0) { /* LCOV_EXCL_START */ return (void*)-1; /* LCOV_EXCL_STOP */ diff --git a/doc/snapraid_log.1 b/doc/snapraid_log.1 index 10f9e013..c2786f95 100644 --- a/doc/snapraid_log.1 +++ b/doc/snapraid_log.1 @@ -1435,8 +1435,12 @@ Logs the final exit status indicating that the current hash algorithm is already the \`best hash\` for the platform, and thus a rehash is not required. This causes the program to exit with a fatal error. -.SH COMMAND SMART TAGS -This section describes the tags output with the \`smart\` command. +.SH COMMAND SMART AND PROBE TAGS +This section describes the tags output by the \`smart\` and \`probe\` +commands. The main difference between the two is that \`probe\` doesn\'t +spin up the disk, so it won\'t be able to get all attributes if the +disk is spun down. The \`smart\` command, instead, will always get all +attributes, but with the risk of spinning up all disks. .PP Note that a \`\` may be associated with more \`\`, in case the logical disk uses more physical disks. In such a case, diff --git a/doc/snapraid_log.d b/doc/snapraid_log.d index 0821cbaa..93253cc4 100644 --- a/doc/snapraid_log.d +++ b/doc/snapraid_log.d @@ -917,8 +917,12 @@ Command Rehash Tags a rehash is not required. This causes the program to exit with a fatal error. -Command Smart Tags - This section describes the tags output with the `smart` command. +Command Smart And Probe Tags + This section describes the tags output by the `smart` and `probe` + commands. The main difference between the two is that `probe` doesn't + spin up the disk, so it won't be able to get all attributes if the + disk is spun down. The `smart` command, instead, will always get all + attributes, but with the risk of spinning up all disks. Note that a `` may be associated with more ``, in case the logical disk uses more physical disks. In such a case, diff --git a/doc/snapraid_log.txt b/doc/snapraid_log.txt index e5f320a1..fff76194 100644 --- a/doc/snapraid_log.txt +++ b/doc/snapraid_log.txt @@ -957,10 +957,14 @@ These tags provide a final summary of the rehash scheduling process. a fatal error. -14 COMMAND SMART TAGS -===================== +14 COMMAND SMART AND PROBE TAGS +=============================== -This section describes the tags output with the `smart` command. +This section describes the tags output by the `smart` and `probe` +commands. The main difference between the two is that `probe` doesn't +spin up the disk, so it won't be able to get all attributes if the +disk is spun down. The `smart` command, instead, will always get all +attributes, but with the risk of spinning up all disks. Note that a `` may be associated with more ``, in case the logical disk uses more physical disks. In such a case,