mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Skip spinup and spindown for non-rotational devices
This commit is contained in:
parent
d7c6a27c6d
commit
d6d1d6d3cd
4 changed files with 112 additions and 8 deletions
2
HISTORY
2
HISTORY
|
|
@ -32,6 +32,8 @@ SnapRAID HISTORY
|
|||
will be slower, this change preserves hash data in the content file
|
||||
to ensure a better fix during disk failures and allows the --import
|
||||
option to remain functional even after an incomplete sync.
|
||||
* Skip spin-up and spin-down operations for non-rotational devices
|
||||
(like SSDs and NVMe drives) on Linux and Windows.
|
||||
* Added --with-smartctl, --with-zfs, --with-zpool, --with-bcachefs
|
||||
configure options to allow pinning the absolute path of each tool at
|
||||
build time. When not specified, the existing runtime discovery
|
||||
|
|
|
|||
|
|
@ -410,7 +410,6 @@ static void devattr_property(HANDLE h, char* serial, char* model, char* inter)
|
|||
#define BusTypeUfs 0x13
|
||||
#define BusTypeNvmeof 0x14
|
||||
|
||||
/* always override interface as more detailed than smartctl */
|
||||
const char* type = 0;
|
||||
switch ((int)desc->BusType) { /* cast to int to avoid warnings about enum unlisted */
|
||||
case BusTypeScsi : type = "SCSI"; break;
|
||||
|
|
@ -435,7 +434,7 @@ static void devattr_property(HANDLE h, char* serial, char* model, char* inter)
|
|||
case BusTypeNvmeof : type = "NVMe"; break;
|
||||
default :
|
||||
}
|
||||
if (inter && type)
|
||||
if (inter && type) /* always override interface as more detailed than smartctl */
|
||||
snprintf(inter, SMART_MAX, "%s", type);
|
||||
|
||||
free(buffer);
|
||||
|
|
@ -483,7 +482,7 @@ static void devattr(uint64_t device, const char* name, const char* wfile, uint64
|
|||
(void)family; /* not available, smartctl uses an internal database to get it */
|
||||
|
||||
/* open the volume */
|
||||
h = CreateFileW(convert(conv_buf, wfile), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, 0);
|
||||
h = CreateFileW(convert(conv_buf, wfile), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
DWORD error = GetLastError();
|
||||
windows_errno(error);
|
||||
|
|
@ -494,12 +493,17 @@ static void devattr(uint64_t device, const char* name, const char* wfile, uint64
|
|||
if (info[INFO_SIZE] == SMART_UNASSIGNED)
|
||||
devattr_size(h, &info[INFO_SIZE]);
|
||||
|
||||
if (*model == 0 || *serial == 0 || *interf == 0)
|
||||
devattr_property(h, serial, model, interf);
|
||||
|
||||
/* set NVMe as not rotational */
|
||||
if (info[INFO_ROTATION_RATE] == SMART_UNASSIGNED && strcasecmp(interf, "nvme") == 0)
|
||||
info[INFO_ROTATION_RATE] = 0;
|
||||
|
||||
/* set SSD as not rotational */
|
||||
if (info[INFO_ROTATION_RATE] == SMART_UNASSIGNED)
|
||||
devattr_rotational(h, &info[INFO_ROTATION_RATE]);
|
||||
|
||||
if (*model == 0 || *serial == 0)
|
||||
devattr_property(h, serial, model, interf);
|
||||
|
||||
if (!CloseHandle(h)) {
|
||||
DWORD error = GetLastError();
|
||||
windows_errno(error);
|
||||
|
|
@ -508,6 +512,54 @@ static void devattr(uint64_t device, const char* name, const char* wfile, uint64
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the device needs power management (it's a rotational one)
|
||||
*/
|
||||
static int devpower(uint64_t device, const char* name, const char* wfile)
|
||||
{
|
||||
HANDLE h;
|
||||
wchar_t conv_buf[CONV_MAX];
|
||||
char file[128];
|
||||
uint64_t rotational;
|
||||
char interf[SMART_MAX];
|
||||
|
||||
rotational = SMART_UNASSIGNED;
|
||||
interf[0] = 0;
|
||||
snprintf(file, sizeof(file), "/dev/pd%" PRIu64, device);
|
||||
|
||||
/* open the volume */
|
||||
h = CreateFileW(convert(conv_buf, wfile), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
DWORD error = GetLastError();
|
||||
windows_errno(error);
|
||||
log_tag("device:%s:%s:error:%lu\n", file, name, error);
|
||||
return 0; /* assume not rotational */
|
||||
}
|
||||
|
||||
/* get the interface */
|
||||
devattr_property(h, 0, 0, interf);
|
||||
|
||||
/* set NVMe as not rotational */
|
||||
if (strcasecmp(interf, "nvme") == 0)
|
||||
rotational = 0;
|
||||
|
||||
/* set SSD as not rotational */
|
||||
if (rotational == SMART_UNASSIGNED)
|
||||
devattr_rotational(h, &rotational);
|
||||
|
||||
if (!CloseHandle(h)) {
|
||||
DWORD error = GetLastError();
|
||||
windows_errno(error);
|
||||
log_tag("device:%s:%s:error:%lu\n", file, name, error);
|
||||
return 0; /* assume not rotational */
|
||||
}
|
||||
|
||||
if (rotational == SMART_UNASSIGNED)
|
||||
return 0; /* assume not rotational */
|
||||
|
||||
return rotational != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get POWER state
|
||||
*/
|
||||
|
|
@ -780,6 +832,10 @@ static void* thread_spinup(void* arg)
|
|||
devinfo_t* devinfo = arg;
|
||||
uint64_t start;
|
||||
|
||||
/* skip not rotational devices */
|
||||
if (devpower(devinfo->device, devinfo->name, devinfo->wfile) == 0)
|
||||
return (void*)-1;
|
||||
|
||||
start = os_tick_ms();
|
||||
|
||||
if (devup(devinfo->device, devinfo->name, devinfo->wfile) != 0) {
|
||||
|
|
@ -816,6 +872,10 @@ static void* thread_spindown(void* arg)
|
|||
devinfo_t* devinfo = arg;
|
||||
uint64_t start;
|
||||
|
||||
/* skip not rotational devices */
|
||||
if (devpower(devinfo->device, devinfo->name, devinfo->wfile) == 0)
|
||||
return (void*)-1;
|
||||
|
||||
start = os_tick_ms();
|
||||
|
||||
if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) {
|
||||
|
|
@ -990,9 +1050,14 @@ int devmap(void)
|
|||
HANDLE h;
|
||||
|
||||
/* open the volume */
|
||||
h = CreateFileW(convert(conv_buf, wfile), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, 0);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
h = CreateFileW(convert(conv_buf, wfile), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
DWORD error = GetLastError();
|
||||
if (error != ERROR_FILE_NOT_FOUND)
|
||||
log_tag("enumeration:/dev/pd%d::error:%lu\n", i, error);
|
||||
continue;
|
||||
}
|
||||
|
||||
char serial[SMART_MAX];
|
||||
serial[0] = 0;
|
||||
devattr_property(h, serial, 0, 0);
|
||||
|
|
|
|||
|
|
@ -2514,6 +2514,7 @@ int smartctl_attribute(OS_FILE* f, const char* file, const char* name, struct sm
|
|||
*/
|
||||
} else if (smatch(s, "NVMe Version:") == 0) {
|
||||
strcpy(inter, "NVMe");
|
||||
info[INFO_ROTATION_RATE] = 0;
|
||||
/* special entries */
|
||||
} else if (snumber(s, "Media and Data Integrity Errors:", &raw) == 1) {
|
||||
smart[SMART_ERROR_MEDIUM].raw = raw;
|
||||
|
|
|
|||
|
|
@ -3218,6 +3218,34 @@ static int devdownifup(dev_t device, const char* name, const char* smartctl, int
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check if the device needs power management (it's a rotational one)
|
||||
*/
|
||||
#if HAVE_LINUX_DEVICE
|
||||
static int devpower(dev_t device)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char buf[512];
|
||||
uint64_t rotational;
|
||||
|
||||
rotational = SMART_UNASSIGNED;
|
||||
|
||||
pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/queue/rotational", major(device), minor(device));
|
||||
if (sysattr(path, buf, sizeof(buf)) == 0) {
|
||||
char* e;
|
||||
uint64_t v;
|
||||
v = strtoul(buf, &e, 10);
|
||||
if (*e == 0)
|
||||
rotational = v;
|
||||
}
|
||||
|
||||
if (rotational == SMART_UNASSIGNED)
|
||||
return 0; /* assume not rotational */
|
||||
|
||||
return rotational != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Spin up a specific device.
|
||||
*/
|
||||
|
|
@ -3329,6 +3357,10 @@ static void* thread_spinup(void* arg)
|
|||
devinfo_t* devinfo = arg;
|
||||
uint64_t start;
|
||||
|
||||
/* skip not rotational devices */
|
||||
if (devpower(devinfo->device) == 0)
|
||||
return (void*)-1;
|
||||
|
||||
start = os_tick_ms();
|
||||
|
||||
if (devup(devinfo->device, devinfo->name) != 0) {
|
||||
|
|
@ -3370,6 +3402,10 @@ static void* thread_spindown(void* arg)
|
|||
devinfo_t* devinfo = arg;
|
||||
uint64_t start;
|
||||
|
||||
/* skip not rotational devices */
|
||||
if (devpower(devinfo->device) == 0)
|
||||
return (void*)-1;
|
||||
|
||||
start = os_tick_ms();
|
||||
|
||||
if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue