From 57b7d0be95a829198503199eabc688492c77b1d5 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Thu, 9 Apr 2015 21:16:06 +0200 Subject: [PATCH] Drop hdparm use replaced by smartctl even for "down" command --- Makefile.am | 2 -- cmdline/device.c | 2 +- cmdline/mingw.c | 84 +++++++++++++++++++++++++++++++++++++++++------- cmdline/unix.c | 40 ++++++++++++++++------- snapraid.1 | 4 +-- snapraid.d | 4 +-- snapraid.txt | 4 +-- 7 files changed, 107 insertions(+), 33 deletions(-) diff --git a/Makefile.am b/Makefile.am index c2f03b8e..f1745904 100644 --- a/Makefile.am +++ b/Makefile.am @@ -819,7 +819,6 @@ distwindows-x86: $(DISTWIN) mkdir tmp cp $(DISTWIN) tmp cp support/smartctl.exe tmp/smartctl.exe - cp support/hdparm.exe tmp/hdparm.exe utod < snapraid.conf.example.windows > tmp/snapraid.conf.example utod < INSTALL.windows > tmp/install.txt utod < README > tmp/readme.txt @@ -835,7 +834,6 @@ distwindows-x64: $(DISTWIN) mkdir tmp cp $(DISTWIN) tmp cp support/smartctl.exe tmp/smartctl.exe - cp support/hdparm.exe tmp/hdparm.exe utod < snapraid.conf.example.windows > tmp/snapraid.conf.example utod < INSTALL.windows > tmp/install.txt utod < README > tmp/readme.txt diff --git a/cmdline/device.c b/cmdline/device.c index bfdc58c6..e37ed842 100644 --- a/cmdline/device.c +++ b/cmdline/device.c @@ -793,7 +793,7 @@ static void state_smart(unsigned n, tommy_list* low) msg_tag("smart:%s:%s:%s:%g\n", devinfo->file, devinfo->name, esc(devinfo->smart_serial), afr); for (j = 0; j < 256; ++j) { if (devinfo->smart[j] != SMART_UNASSIGNED) - msg_tag("attr:%s:%u:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, j, devinfo->smart[j], devinfo->smart[j]); + msg_tag("attr:%s:%u:%" PRIu64 ":0x%" PRIx64 "\n", devinfo->file, j, devinfo->smart[j], devinfo->smart[j]); } if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED) msg_tag("attr:%s:size:%" PRIu64 "\n", devinfo->file, devinfo->smart[SMART_SIZE]); diff --git a/cmdline/mingw.c b/cmdline/mingw.c index 859a0c31..3fd50962 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -2039,12 +2039,14 @@ static int devscan(tommy_list* list) snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" --scan-open -d pd", exedir); - msg_tag("smartctl:scan: smartctl --scan-open -d pd\n"); + msg_tag("smartctl:run:scan: %s\n", u16tou8(cmd)); f = _wpopen(cmd, L"rt"); if (!f) { /* LCOV_EXCL_START */ + pthread_mutex_lock(&io_lock); msg_error("Failed to run '%s' (from popen).\n", u16tou8(cmd)); + pthread_mutex_unlock(&io_lock); return -1; /* LCOV_EXCL_STOP */ } @@ -2059,17 +2061,23 @@ static int devscan(tommy_list* list) ret = pclose(f); if (ret == -1) { /* LCOV_EXCL_START */ + pthread_mutex_lock(&io_lock); msg_error("Failed to run '%s' (from pclose).\n", u16tou8(cmd)); + pthread_mutex_unlock(&io_lock); return -1; /* LCOV_EXCL_STOP */ } if (ret != 0) { /* LCOV_EXCL_START */ + pthread_mutex_lock(&io_lock); msg_error("Failed to run '%s' with return code %xh.\n", u16tou8(cmd), ret); + pthread_mutex_unlock(&io_lock); return -1; /* LCOV_EXCL_STOP */ } + msg_tag("smartctl:ret:scan: 0x%x\n", ret); + return 0; } @@ -2091,21 +2099,23 @@ static int devsmart(uint64_t device, const char* name, const char* custom, uint6 char option[128]; snprintf(option, sizeof(option), custom, file); snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -a %s", exedir, option); - - msg_tag("smartctl:%s: smartctl -a %s\n", name, option); } else { snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -a %s", exedir, file); - - msg_tag("smartctl:%s: smartctl -a %s\n", name, file); } count = 0; retry: + pthread_mutex_lock(&io_lock); + msg_tag("smartctl:run:%s: %s\n", name, u16tou8(cmd)); + pthread_mutex_unlock(&io_lock); + f = _wpopen(cmd, L"rt"); if (!f) { /* LCOV_EXCL_START */ + pthread_mutex_lock(&io_lock); msg_error("Failed to run '%s' (from popen).\n", u16tou8(cmd)); + pthread_mutex_unlock(&io_lock); return -1; /* LCOV_EXCL_STOP */ } @@ -2118,9 +2128,16 @@ retry: } ret = pclose(f); + + pthread_mutex_lock(&io_lock); + msg_tag("smartctl:ret:%s: 0x%x\n", name, ret); + pthread_mutex_unlock(&io_lock); + if (ret == -1) { /* LCOV_EXCL_START */ + pthread_mutex_lock(&io_lock); msg_error("Failed to run '%s' (from pclose).\n", u16tou8(cmd)); + pthread_mutex_unlock(&io_lock); return -1; /* LCOV_EXCL_STOP */ } @@ -2134,7 +2151,7 @@ retry: * stage, returning with error 2, or even with error 0, and with no info at all. * We detect this conditon checking the PowerOnHours, Size and RotationRate attributes. * - * In such conditions we retry using the "sat" type, that often allow to proceed. + * In such conditions we retry using the "sat" type, that often allows to proceed. * * Note that getting error 4 is instead very common, even with full info gathering. */ @@ -2146,8 +2163,6 @@ retry: /* retry using the "sat" type */ snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -a -d sat %s", exedir, file); - msg_tag("smartctl:%s: smartctl -a -d sat %s\n", name, file); - ++count; goto retry; } @@ -2162,25 +2177,70 @@ retry: /** * Spin down a specific device. */ -static int devdown(uint64_t device, const char* name) +static int devdown(uint64_t device, const char* name, const char* custom) { WCHAR cmd[MAX_PATH + 128]; + char file[128]; int ret; + int count; - snwprintf(cmd, sizeof(cmd), L"\"%lshdparm.exe\" -y \\\\.\\PhysicalDrive%" PRIu64 " >nul 2>nul", exedir, device); + snprintf(file, sizeof(file), "/dev/pd%" PRIu64, device); - msg_tag("hdparm:%s: hdparm -y \\\\.\\PhysicalDrive%" PRIu64 " >nul 2>nul\n", name, device); + /* if there is a custom command */ + if (custom[0]) { + char option[128]; + snprintf(option, sizeof(option), custom, file); + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -s standby,now %s >nul 2>nul", exedir, option); + } else { + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -s standby,now %s >nul 2>nul", exedir, file); + } + + count = 0; + +retry: + pthread_mutex_lock(&io_lock); + msg_tag("smartctl:run:%s: %s\n", name, u16tou8(cmd)); + pthread_mutex_unlock(&io_lock); ret = _wsystem(cmd); + + pthread_mutex_lock(&io_lock); + msg_tag("smartctl:ret:%s: 0x%x\n", name, ret); + pthread_mutex_unlock(&io_lock); + if (ret == -1) { /* LCOV_EXCL_START */ + pthread_mutex_lock(&io_lock); msg_error("Failed to run '%s' (from system).\n", u16tou8(cmd)); + pthread_mutex_unlock(&io_lock); return -1; /* LCOV_EXCL_STOP */ } + + /* if first try without custom command */ + if (count == 0 && custom[0] == 0) { + /* + * Handle some common cases in Windows. + * + * Sometimes the "type" autodetection is wrong, and the command fails at identification + * stage, returning with error 2. + * + * In such conditions we retry using the "sat" type, that often allows to proceed. + */ + if (ret == 2) { + /* retry using the "sat" type */ + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -s standby,now -d sat %s >nul 2>nul", exedir, file); + + ++count; + goto retry; + } + } + if (ret != 0) { /* LCOV_EXCL_START */ + pthread_mutex_lock(&io_lock); msg_error("Failed to run '%s' with return code %xh.\n", u16tou8(cmd), ret); + pthread_mutex_unlock(&io_lock); return -1; /* LCOV_EXCL_STOP */ } @@ -2271,7 +2331,7 @@ static void* thread_spindown(void* arg) start = tick_ms(); - if (devdown(devinfo->device, devinfo->name) != 0) { + if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { /* LCOV_EXCL_START */ return (void*)-1; /* LCOV_EXCL_STOP */ diff --git a/cmdline/unix.c b/cmdline/unix.c index cfddd689..586830d2 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -639,12 +639,12 @@ static int devsmart(dev_t device, const char* name, const char* custom, uint64_t snprintf(cmd, sizeof(cmd), "smartctl -a %s", file); } - msg_tag("smartctl:%s: %s\n", name, cmd); + msg_tag("smartctl:run:%s: %s\n", name, cmd); f = popen(cmd, "r"); if (!f) { /* LCOV_EXCL_START */ - msg_error("Failed to run smartctl -a on device '%u:%u' (from popen).\n", major(device), minor(device)); + msg_error("Failed to run '%s' (from popen).\n", cmd); return -1; /* LCOV_EXCL_STOP */ } @@ -657,15 +657,18 @@ static int devsmart(dev_t device, const char* name, const char* custom, uint64_t } ret = pclose(f); + + msg_tag("smartctl:ret:%s 0x%x\n", name, ret); + if (!WIFEXITED(ret)) { /* LCOV_EXCL_START */ - msg_error("Failed to run smartctl -a on device '%u:%u' (not exited).\n", major(device), minor(device)); + msg_error("Failed to run '%s' (not exited).\n", cmd); return -1; /* LCOV_EXCL_STOP */ } if (WEXITSTATUS(ret) == 127) { /* LCOV_EXCL_START */ - msg_error("Failed to run smartctl -a on device '%u:%u' (from sh).\n", major(device), minor(device)); + msg_error("Failed to run '%s' (from sh).\n", cmd); return -1; /* LCOV_EXCL_STOP */ } @@ -680,37 +683,50 @@ static int devsmart(dev_t device, const char* name, const char* custom, uint64_t * Spin down a specific device. */ #if HAVE_LINUX_DEVICE -static int devdown(dev_t device, const char* name) +static int devdown(dev_t device, const char* name, const char* custom) { char cmd[128]; + char file[128]; int ret; - snprintf(cmd, sizeof(cmd), "hdparm -y /dev/block/%u:%u >/dev/null 2>/dev/null", major(device), minor(device)); + snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device)); - msg_tag("hdparm:%s: %s\n", name, cmd); + /* if there is a custom command */ + if (custom[0]) { + char option[128]; + snprintf(option, sizeof(option), custom, file); + snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s >/dev/null 2>/dev/null", option); + } else { + snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s >/dev/null 2>/dev/null", file); + } + + msg_tag("smartctl:run:%s: %s\n", name, cmd); ret = system(cmd); + + msg_tag("smartctl:ret:%s: 0x%x\n", name, ret); + if (ret == -1) { /* LCOV_EXCL_START */ - msg_error("Failed to run hdparm -y on device '%u:%u' (from system).\n", major(device), minor(device)); + msg_error("Failed to run '%s' (from system).\n", cmd); return -1; /* LCOV_EXCL_STOP */ } if (!WIFEXITED(ret)) { /* LCOV_EXCL_START */ - msg_error("Failed to run hdparm -y on device '%u:%u' (not exited).\n", major(device), minor(device)); + msg_error("Failed to run '%s' (not exited).\n", cmd); return -1; /* LCOV_EXCL_STOP */ } if (WEXITSTATUS(ret) == 127) { /* LCOV_EXCL_START */ - msg_error("Failed to run hdparm -y on device '%u:%u' (from sh).\n", major(device), minor(device)); + msg_error("Failed to run '%s' (from sh).\n", cmd); return -1; /* LCOV_EXCL_STOP */ } if (WEXITSTATUS(ret) != 0) { /* LCOV_EXCL_START */ - msg_error("Failed to run hdparm -y on device '%u:%u' with return code %xh.\n", major(device), minor(device), WEXITSTATUS(ret)); + msg_error("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret)); return -1; /* LCOV_EXCL_STOP */ } @@ -803,7 +819,7 @@ static void* thread_spindown(void* arg) start = tick_ms(); - if (devdown(devinfo->device, devinfo->name) != 0) { + if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { /* LCOV_EXCL_START */ return (void*)-1; /* LCOV_EXCL_STOP */ diff --git a/snapraid.1 b/snapraid.1 index b6ccb72d..3e45342a 100644 --- a/snapraid.1 +++ b/snapraid.1 @@ -679,8 +679,8 @@ Nothing is modified. .SS down Spins down all the disks of the array. .PP -This command uses the \[dq]hdparm\[dq] tool, and it\'s equivalent to run -\[dq]hdparm \-y\[dq] or all the devices. +This command uses the \[dq]smartctl\[dq] tool, and it\'s equivalent to run +\[dq]smartctl \-s standby,now\[dq] on all the devices. .PP Nothing is modified. .SS diff diff --git a/snapraid.d b/snapraid.d index eac66e07..ee2c2ba6 100644 --- a/snapraid.d +++ b/snapraid.d @@ -408,8 +408,8 @@ Commands down Spins down all the disks of the array. - This command uses the "hdparm" tool, and it's equivalent to run - "hdparm -y" or all the devices. + This command uses the "smartctl" tool, and it's equivalent to run + "smartctl -s standby,now" on all the devices. Nothing is modified. diff --git a/snapraid.txt b/snapraid.txt index e5d717d0..cf564d11 100644 --- a/snapraid.txt +++ b/snapraid.txt @@ -440,8 +440,8 @@ Nothing is modified. Spins down all the disks of the array. -This command uses the "hdparm" tool, and it's equivalent to run -"hdparm -y" or all the devices. +This command uses the "smartctl" tool, and it's equivalent to run +"smartctl -s standby,now" on all the devices. Nothing is modified.