diff --git a/cmdline/device.c b/cmdline/device.c index 8d2289d2..bfdc58c6 100644 --- a/cmdline/device.c +++ b/cmdline/device.c @@ -946,6 +946,7 @@ void state_device(struct snapraid_state* state, int operation) entry->device = disk->device; pathcpy(entry->name, sizeof(entry->name), disk->name); pathcpy(entry->mount, sizeof(entry->mount), disk->dir); + pathcpy(entry->smartctl, sizeof(entry->smartctl), disk->smartctl); tommy_list_insert_tail(&high, &entry->node, entry); } @@ -959,6 +960,7 @@ void state_device(struct snapraid_state* state, int operation) entry->device = state->parity[j].device; pathcpy(entry->name, sizeof(entry->name), lev_config_name(j)); pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].path); + pathcpy(entry->smartctl, sizeof(entry->smartctl), state->parity[j].smartctl); pathcut(entry->mount); /* remove the parity file */ tommy_list_insert_tail(&high, &entry->node, entry); diff --git a/cmdline/elem.c b/cmdline/elem.c index 103ae645..b8c04575 100644 --- a/cmdline/elem.c +++ b/cmdline/elem.c @@ -675,6 +675,7 @@ struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev /* ensure that the dir terminate with "/" if it isn't empty */ pathslash(disk->dir, sizeof(disk->dir)); + disk->smartctl[0] = 0; disk->device = dev; disk->tick = 0; disk->total_blocks = 0; diff --git a/cmdline/elem.h b/cmdline/elem.h index 89c8e9b2..5df2adff 100644 --- a/cmdline/elem.h +++ b/cmdline/elem.h @@ -309,6 +309,7 @@ struct snapraid_deleted { struct snapraid_disk { char name[PATH_MAX]; /**< Name of the disk. */ char dir[PATH_MAX]; /**< Mount point of the disk. It always terminates with /. */ + char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */ uint64_t device; /**< Device identifier. */ uint64_t tick; /**< Usage time of the disk. */ @@ -387,6 +388,7 @@ struct snapraid_map { struct snapraid_parity { char path[PATH_MAX]; /**< Path of the parity file. */ char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */ + char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */ uint64_t device; /**< Device identifier of the parity. */ block_off_t total_blocks; /**< Number of total blocks. */ block_off_t free_blocks; /**< Number of free blocks at the last sync. */ diff --git a/cmdline/mingw.c b/cmdline/mingw.c index 4ab238da..859a0c31 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -1901,7 +1901,7 @@ static int devresolve(const char* mount, char* file, size_t file_size, char* wfi /** * Read a device tree filling the specified list of disk_t entries. */ -static int devtree(const char* name, const char* wfile, devinfo_t* parent, tommy_list* list) +static int devtree(const char* name, const char* custom, const char* wfile, devinfo_t* parent, tommy_list* list) { HANDLE h; unsigned char vde_buffer[sizeof(VOLUME_DISK_EXTENTS)]; @@ -1949,6 +1949,7 @@ static int devtree(const char* name, const char* wfile, devinfo_t* parent, tommy devinfo = calloc_nofail(1, sizeof(devinfo_t)); pathcpy(devinfo->name, sizeof(devinfo->name), name); + pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom); devinfo->device = vde->Extents[i].DiskNumber; pathprint(devinfo->file, sizeof(devinfo->file), "/dev/pd%" PRIu64, devinfo->device); pathprint(devinfo->wfile, sizeof(devinfo->wfile), "\\\\.\\PhysicalDrive%" PRIu64, devinfo->device); @@ -2038,6 +2039,8 @@ 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"); + f = _wpopen(cmd, L"rt"); if (!f) { /* LCOV_EXCL_START */ @@ -2073,17 +2076,32 @@ static int devscan(tommy_list* list) /** * Gets SMART attributes. */ -static int devsmart(uint64_t device, uint64_t* smart, char* serial) +static int devsmart(uint64_t device, const char* name, const char* custom, uint64_t* smart, char* serial) { WCHAR cmd[MAX_PATH + 128]; + char file[128]; FILE* f; int ret; - int retry; + int count; - snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -a /dev/pd%" PRIu64, exedir, device); + snprintf(file, sizeof(file), "/dev/pd%" PRIu64, device); - retry = 0; -loop: + /* 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\" -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: f = _wpopen(cmd, L"rt"); if (!f) { /* LCOV_EXCL_START */ @@ -2107,7 +2125,8 @@ loop: /* LCOV_EXCL_STOP */ } - if (retry == 0) { + /* if first try without custom command */ + if (count == 0 && custom[0] == 0) { /* * Handle some common cases in Windows. * @@ -2125,9 +2144,12 @@ loop: && smart[SMART_ROTATION_RATE] == SMART_UNASSIGNED ) { /* retry using the "sat" type */ - snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -a /dev/pd%" PRIu64 " -d sat", exedir, device); - ++retry; - goto loop; + 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; } } @@ -2140,13 +2162,15 @@ loop: /** * Spin down a specific device. */ -static int devdown(uint64_t device) +static int devdown(uint64_t device, const char* name) { WCHAR cmd[MAX_PATH + 128]; int ret; snwprintf(cmd, sizeof(cmd), L"\"%lshdparm.exe\" -y \\\\.\\PhysicalDrive%" PRIu64 " >nul 2>nul", exedir, device); + msg_tag("hdparm:%s: hdparm -y \\\\.\\PhysicalDrive%" PRIu64 " >nul 2>nul\n", name, device); + ret = _wsystem(cmd); if (ret == -1) { /* LCOV_EXCL_START */ @@ -2247,7 +2271,7 @@ static void* thread_spindown(void* arg) start = tick_ms(); - if (devdown(devinfo->device) != 0) { + if (devdown(devinfo->device, devinfo->name) != 0) { /* LCOV_EXCL_START */ return (void*)-1; /* LCOV_EXCL_STOP */ @@ -2267,7 +2291,7 @@ static void* thread_smart(void* arg) { devinfo_t* devinfo = arg; - if (devsmart(devinfo->device, devinfo->smart, devinfo->smart_serial) != 0) { + if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial) != 0) { /* LCOV_EXCL_START */ return (void*)-1; /* LCOV_EXCL_STOP */ @@ -2336,7 +2360,7 @@ int devquery(tommy_list* high, tommy_list* low, int operation) } /* expand the tree of devices */ - if (devtree(devinfo->name, devinfo->wfile, devinfo, low) != 0) { + if (devtree(devinfo->name, devinfo->smartctl, devinfo->wfile, devinfo, low) != 0) { /* LCOV_EXCL_START */ msg_error("Failed to expand device '%s'.\n", devinfo->file); return -1; diff --git a/cmdline/portable.h b/cmdline/portable.h index a3b647c6..a7ca6237 100644 --- a/cmdline/portable.h +++ b/cmdline/portable.h @@ -388,6 +388,7 @@ struct devinfo_struct { uint64_t device; /**< Device ID. */ char name[PATH_MAX]; /**< Name of the disk. */ char mount[PATH_MAX]; /**< Mount point or other contained directory. */ + char smartctl[PATH_MAX]; /**< Options for smartctl. */ char file[PATH_MAX]; /**< File device. */ #ifdef _WIN32 char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */ diff --git a/cmdline/state.c b/cmdline/state.c index 1ac67385..0fe75636 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -55,6 +55,48 @@ const char* lev_config_name(unsigned l) return 0; } +static int lev_config_scan(const char* s, unsigned* level, unsigned* mode) +{ + if (strcmp(s, "parity") == 0 || strcmp(s, "1-parity") == 0) { + *level = 0; + return 0; + } + + if (strcmp(s, "q-parity") == 0 || strcmp(s, "2-parity") == 0) { + *level = 1; + return 0; + } + + if (strcmp(s, "r-parity") == 0 || strcmp(s, "3-parity") == 0) { + *level = 2; + return 0; + } + + if (strcmp(s, "4-parity") == 0) { + *level = 3; + return 0; + } + + if (strcmp(s, "5-parity") == 0) { + *level = 4; + return 0; + } + + if (strcmp(s, "6-parity") == 0) { + *level = 5; + return 0; + } + + if (strcmp(s, "z-parity") == 0) { + *level = 2; + if (mode) + *mode = RAID_MODE_VANDERMONDE; + return 0; + } + + return -1; +} + const char* lev_raid_name(unsigned mode, unsigned n) { switch (n) { @@ -415,6 +457,7 @@ void state_config(struct snapraid_state* state, const char* path, const char* co char buffer[PATH_MAX]; int ret; int c; + unsigned level; /* skip initial spaces */ sgetspace(f); @@ -462,41 +505,9 @@ void state_config(struct snapraid_state* state, const char* path, const char* co /* LCOV_EXCL_STOP */ } state->block_size *= 1024; - } else if (strcmp(tag, "parity") == 0 - || strcmp(tag, "q-parity") == 0 - || strcmp(tag, "r-parity") == 0 - || strcmp(tag, "1-parity") == 0 - || strcmp(tag, "2-parity") == 0 - || strcmp(tag, "3-parity") == 0 - || strcmp(tag, "4-parity") == 0 - || strcmp(tag, "5-parity") == 0 - || strcmp(tag, "6-parity") == 0 - || strcmp(tag, "z-parity") == 0 - ) { + } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) { char device[PATH_MAX]; char* slash; - unsigned level; - - switch (tag[0]) { - case 'p' : level = 0; break; - case 'q' : level = 1; break; - case 'r' : level = 2; break; - case '1' : level = 0; break; - case '2' : level = 1; break; - case '3' : level = 2; break; - case '4' : level = 3; break; - case '5' : level = 4; break; - case '6' : level = 5; break; - case 'z' : - level = 2; - state->raid_mode = RAID_MODE_VANDERMONDE; - break; - default : - /* LCOV_EXCL_START */ - msg_error("Invalid '%s' specification in '%s' at line %u\n", tag, path, line); - exit(EXIT_FAILURE); - /* LCOV_EXCL_STOP */ - } if (*state->parity[level].path) { /* LCOV_EXCL_START */ @@ -745,6 +756,74 @@ void state_config(struct snapraid_state* state, const char* path, const char* co disk = disk_alloc(buffer, dir, dev); tommy_list_insert_tail(&state->disklist, &disk->node, disk); + } else if (strcmp(tag, "smartctl") == 0) { + char custom[PATH_MAX]; + + ret = sgettok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + msg_error("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + msg_error("Empty 'smartctl' name specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + sgetspace(f); + + ret = sgetlasttok(f, custom, sizeof(custom)); + if (ret < 0) { + /* LCOV_EXCL_START */ + msg_error("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*custom) { + /* LCOV_EXCL_START */ + msg_error("Empty 'smartctl' option specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* search for parity */ + if (lev_config_scan(buffer, &level, 0) == 0) { + if (state->parity[level].smartctl[0] != 0) { + /* LCOV_EXCL_START */ + msg_error("Duplicate parity smartctl '%s' at line %u\n", buffer, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom); + } else { + /* search the disk */ + struct snapraid_disk* disk; + for (i = state->disklist; i != 0; i = i->next) { + disk = i->data; + if (strcmp(disk->name, buffer) == 0) + break; + } + if (!i) { + /* LCOV_EXCL_START */ + msg_error("Missing disk smartctl '%s' at line %u\n", buffer, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (disk->smartctl[0] != 0) { + /* LCOV_EXCL_START */ + msg_error("Duplicate disk name '%s' at line %u\n", buffer, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + pathcpy(disk->smartctl, sizeof(disk->smartctl), custom); + } } else if (strcmp(tag, "nohidden") == 0) { state->filter_hidden = 1; } else if (strcmp(tag, "exclude") == 0) { diff --git a/cmdline/support.h b/cmdline/support.h index 8ed9bda3..c50c096e 100644 --- a/cmdline/support.h +++ b/cmdline/support.h @@ -47,7 +47,7 @@ void msg_warning(const char* format, ...) __attribute__((format(attribute_printf * * Messages are in tag format, like "tag:entry:...". * - * These messages neves go on the screen, but only in the log file if specified. + * These messages never go on the screen, but only in the log file if specified. * * Note that this function, allows not \n terminated strings. * diff --git a/cmdline/unix.c b/cmdline/unix.c index 9a66213b..cfddd689 100644 --- a/cmdline/unix.c +++ b/cmdline/unix.c @@ -456,7 +456,7 @@ static int devresolve(dev_t device, char* path, size_t path_size) * Read a device tree filling the specified list of disk_t entries. */ #if HAVE_LINUX_DEVICE -static int devtree(const char* name, dev_t device, devinfo_t* parent, tommy_list* list) +static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list) { char path[PATH_MAX]; DIR* d; @@ -482,7 +482,7 @@ static int devtree(const char* name, dev_t device, devinfo_t* parent, tommy_list /* LCOV_EXCL_STOP */ } - if (devtree(name, device, parent, list) != 0) { + if (devtree(name, custom, device, parent, list) != 0) { /* LCOV_EXCL_START */ closedir(d); return -1; @@ -526,6 +526,7 @@ static int devtree(const char* name, dev_t device, devinfo_t* parent, tommy_list devinfo->device = device; pathcpy(devinfo->name, sizeof(devinfo->name), name); + pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom); pathcpy(devinfo->file, sizeof(devinfo->file), path); devinfo->parent = parent; @@ -620,13 +621,25 @@ static int devscan(tommy_list* list) /** * Gets SMART attributes. */ -static int devsmart(dev_t device, uint64_t* smart, char* serial) +static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial) { char cmd[128]; + char file[128]; FILE* f; int ret; - snprintf(cmd, sizeof(cmd), "smartctl -a /dev/block/%u:%u", major(device), minor(device)); + snprintf(file, sizeof(file), "/dev/block/%u:%u", major(device), minor(device)); + + /* if there is a custom command */ + if (custom[0]) { + char option[128]; + snprintf(option, sizeof(option), custom, file); + snprintf(cmd, sizeof(cmd), "smartctl -a %s", option); + } else { + snprintf(cmd, sizeof(cmd), "smartctl -a %s", file); + } + + msg_tag("smartctl:%s: %s\n", name, cmd); f = popen(cmd, "r"); if (!f) { @@ -667,13 +680,15 @@ static int devsmart(dev_t device, uint64_t* smart, char* serial) * Spin down a specific device. */ #if HAVE_LINUX_DEVICE -static int devdown(dev_t device) +static int devdown(dev_t device, const char* name) { char cmd[128]; int ret; snprintf(cmd, sizeof(cmd), "hdparm -y /dev/block/%u:%u >/dev/null 2>/dev/null", major(device), minor(device)); + msg_tag("hdparm:%s: %s\n", name, cmd); + ret = system(cmd); if (ret == -1) { /* LCOV_EXCL_START */ @@ -788,7 +803,7 @@ static void* thread_spindown(void* arg) start = tick_ms(); - if (devdown(devinfo->device) != 0) { + if (devdown(devinfo->device, devinfo->name) != 0) { /* LCOV_EXCL_START */ return (void*)-1; /* LCOV_EXCL_STOP */ @@ -810,7 +825,7 @@ static void* thread_smart(void* arg) { devinfo_t* devinfo = arg; - if (devsmart(devinfo->device, devinfo->smart, devinfo->smart_serial) != 0) { + if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial) != 0) { /* LCOV_EXCL_START */ return (void*)-1; /* LCOV_EXCL_STOP */ @@ -904,7 +919,7 @@ int devquery(tommy_list* high, tommy_list* low, int operation) } /* expand the tree of devices */ - if (devtree(devinfo->name, devinfo->device, devinfo, low) != 0) { + if (devtree(devinfo->name, devinfo->smartctl, devinfo->device, devinfo, low) != 0) { /* LCOV_EXCL_START */ msg_error("Failed to expand device '%u:%u'.\n", major(devinfo->device), minor(devinfo->device)); return -1; diff --git a/snapraid.1 b/snapraid.1 index be8e40e0..b6ccb72d 100644 --- a/snapraid.1 +++ b/snapraid.1 @@ -667,6 +667,10 @@ or less parity. This command uses the \[dq]smartctl\[dq] tool, and it\'s equivalent to run \[dq]smartctl \-a\[dq] on all the devices. .PP +If your devices are not autodetected correctly, you can configure +a custom command using the \[dq]smartctl\[dq] option in the configuration +file. +.PP Nothing is modified. .SS up Spins up all the disks of the array. @@ -1260,6 +1264,30 @@ disk name as specified in the \[dq]disk\[dq] option, and finally adding the file dir and name. .PP This option is only required for Windows. +.SS smartctl DISK/PARITY OPTIONS... +Defines a custom smartctl command to obtain the SMART attributes +for each disk. This may be required for RAID controllers and for +some USB disk that cannot be autodetected. +.PP +DISK is the same disk name specified in the \[dq]disk\[dq] option. +PARITY is one of the parity name as \[dq]parity,[1,2,3,4,5,6,z]\-parity\[dq]. +.PP +In the specified OPTIONS, the \[dq]%s\[dq] string is replaced by the +device name. Note that in case of RAID controllers the device is likely +fixed, and you don\'t have to use \[dq]%s\[dq]. +.PP +Refers at the smartmontools documentation about the possible options: +.PP +.RS 4 +https://www.smartmontools.org/wiki/Supported_RAID\-Controllers +.PD 0 +.PP +.PD +https://www.smartmontools.org/wiki/Supported_USB\-Devices +.PD 0 +.PP +.PD +.RE .SS Examples An example of a typical configuration for Unix is: .PP @@ -1296,6 +1324,18 @@ exclude /tmp/ .PD 0 .PP .PD +smartctl d1 \-d sat %s +.PD 0 +.PP +.PD +smartctl d2 \-d usbjmicron %s +.PD 0 +.PP +.PD +smartctl parity \-d areca,1/1 /dev/sg0 +.PD 0 +.PP +.PD .RE .PP An example of a typical configuration for Windows is: @@ -1337,6 +1377,18 @@ exclude \\System Volume Information .PD 0 .PP .PD +smartctl d1 \-d sat %s +.PD 0 +.PP +.PD +smartctl d2 \-d usbjmicron %s +.PD 0 +.PP +.PD +smartctl parity \-d areca,1/1 /dev/arcmsr0 +.PD 0 +.PP +.PD .RE .SH PATTERN Patterns are used to select a subset of files to exclude or include in diff --git a/snapraid.conf.example b/snapraid.conf.example index 0e63a865..48f66ec3 100644 --- a/snapraid.conf.example +++ b/snapraid.conf.example @@ -70,3 +70,15 @@ exclude /lost+found/ # Format: "pool DIR" #pool /pool +# Defines a custom smartctl command to obtain the SMART attributes +# for each disk. This may be required for RAID controllers and for +# some USB disk that cannot be autodetected. +# In the specified options, the "%s" string is replaced by the device name. +# Refers at the smartmontools documentation about the possible options: +# RAID -> https://www.smartmontools.org/wiki/Supported_RAID-Controllers +# USB -> https://www.smartmontools.org/wiki/Supported_USB-Devices +#smartctl d1 -d sat %s +#smartctl d2 -d usbjmicron %s +#smartctl parity -d areca,1/1 /dev/sg0 +#smartctl 2-parity -d areca,2/1 /dev/sg0 + diff --git a/snapraid.conf.example.windows b/snapraid.conf.example.windows index f77da725..4739cc75 100644 --- a/snapraid.conf.example.windows +++ b/snapraid.conf.example.windows @@ -85,3 +85,15 @@ exclude \Windows\ # Format: "share UNC_DIR" #share \\server +# Defines a custom smartctl command to obtain the SMART attributes +# for each disk. This may be required for RAID controllers and for +# some USB disk that cannot be autodetected. +# In the specified options, the "%s" string is replaced by the device name. +# Refers at the smartmontools documentation about the possible options: +# RAID -> https://www.smartmontools.org/wiki/Supported_RAID-Controllers +# USB -> https://www.smartmontools.org/wiki/Supported_USB-Devices +#smartctl d1 -d sat %s +#smartctl d2 -d usbjmicron %s +#smartctl parity -d areca,1/1 /dev/arcmsr0 +#smartctl 2-parity -d areca,2/1 /dev/arcmsr0 + diff --git a/snapraid.d b/snapraid.d index ae1c6727..eac66e07 100644 --- a/snapraid.d +++ b/snapraid.d @@ -394,6 +394,10 @@ Commands This command uses the "smartctl" tool, and it's equivalent to run "smartctl -a" on all the devices. + If your devices are not autodetected correctly, you can configure + a custom command using the "smartctl" option in the configuration + file. + Nothing is modified. up @@ -1001,6 +1005,23 @@ Configuration This option is only required for Windows. + smartctl DISK/PARITY OPTIONS... + Defines a custom smartctl command to obtain the SMART attributes + for each disk. This may be required for RAID controllers and for + some USB disk that cannot be autodetected. + + DISK is the same disk name specified in the "disk" option. + PARITY is one of the parity name as "parity,[1,2,3,4,5,6,z]-parity". + + In the specified OPTIONS, the "%s" string is replaced by the + device name. Note that in case of RAID controllers the device is likely + fixed, and you don't have to use "%s". + + Refers at the smartmontools documentation about the possible options: + + :https://www.smartmontools.org/wiki/Supported_RAID-Controllers + :https://www.smartmontools.org/wiki/Supported_USB-Devices + Examples An example of a typical configuration for Unix is: @@ -1012,6 +1033,9 @@ Configuration :disk d3 /mnt/disk3/ :exclude /lost+found/ :exclude /tmp/ + :smartctl d1 -d sat %s + :smartctl d2 -d usbjmicron %s + :smartctl parity -d areca,1/1 /dev/sg0 An example of a typical configuration for Windows is: @@ -1024,6 +1048,9 @@ Configuration :exclude Thumbs.db :exclude \$RECYCLE.BIN :exclude \System Volume Information + :smartctl d1 -d sat %s + :smartctl d2 -d usbjmicron %s + :smartctl parity -d areca,1/1 /dev/arcmsr0 Pattern Patterns are used to select a subset of files to exclude or include in diff --git a/snapraid.txt b/snapraid.txt index dda4b6cc..e5d717d0 100644 --- a/snapraid.txt +++ b/snapraid.txt @@ -422,6 +422,10 @@ or less parity. This command uses the "smartctl" tool, and it's equivalent to run "smartctl -a" on all the devices. +If your devices are not autodetected correctly, you can configure +a custom command using the "smartctl" option in the configuration +file. + Nothing is modified. 5.3 up @@ -1085,7 +1089,26 @@ file dir and name. This option is only required for Windows. -7.12 Examples +7.12 smartctl DISK/PARITY OPTIONS... +------------------------------------ + +Defines a custom smartctl command to obtain the SMART attributes +for each disk. This may be required for RAID controllers and for +some USB disk that cannot be autodetected. + +DISK is the same disk name specified in the "disk" option. +PARITY is one of the parity name as "parity,[1,2,3,4,5,6,z]-parity". + +In the specified OPTIONS, the "%s" string is replaced by the +device name. Note that in case of RAID controllers the device is likely +fixed, and you don't have to use "%s". + +Refers at the smartmontools documentation about the possible options: + + https://www.smartmontools.org/wiki/Supported_RAID-Controllers + https://www.smartmontools.org/wiki/Supported_USB-Devices + +7.13 Examples ------------- An example of a typical configuration for Unix is: @@ -1098,6 +1121,9 @@ An example of a typical configuration for Unix is: disk d3 /mnt/disk3/ exclude /lost+found/ exclude /tmp/ + smartctl d1 -d sat %s + smartctl d2 -d usbjmicron %s + smartctl parity -d areca,1/1 /dev/sg0 An example of a typical configuration for Windows is: @@ -1110,6 +1136,9 @@ An example of a typical configuration for Windows is: exclude Thumbs.db exclude \$RECYCLE.BIN exclude \System Volume Information + smartctl d1 -d sat %s + smartctl d2 -d usbjmicron %s + smartctl parity -d areca,1/1 /dev/arcmsr0 8 PATTERN diff --git a/test/test-par6.conf b/test/test-par6.conf index 4d6616bc..c92e1dbd 100644 --- a/test/test-par6.conf +++ b/test/test-par6.conf @@ -20,4 +20,6 @@ disk disk5 bench/disk5/ disk disk6 bench/disk6/ include *.hidden exclude *.unrecoverable +smartctl disk1 %s +smartctl parity /dev/sda