Ingnore the SMART Command Timeout for Seagate SMR disks

This commit is contained in:
Andrea Mazzoleni 2016-10-13 18:57:14 +02:00
parent faa530e83e
commit a90f8db3c0
7 changed files with 36 additions and 12 deletions

View file

@ -39,6 +39,8 @@ SnapRAID HISTORY
--test-io-advise-direct use direct/unbuffered mode (Linux/Windows)
The new default mode is 'flush' in Linux (before it was 'sequential'),
and 'sequential' in Windows (like before).
* For Seagate SMR (Shingled Magnetic Recording) ignore the SMART
attribute Command_Timeout 188 as not reliable.
* Fixed running in Windows platforms that miss the RtlGenRandom()
function.
* Added the --test-io-cache=1 option to disable the multi-thread IO

View file

@ -464,7 +464,7 @@ static double smart_afr_value(double* tab, unsigned step, uint64_t value)
* we use the maximum rate reported, and we do not sum them,
* because the attributes are not independent.
*/
static double smart_afr(uint64_t* smart)
static double smart_afr(uint64_t* smart, const char* model)
{
double afr = 0;
uint64_t mask32 = 0xffffffffU;
@ -484,7 +484,17 @@ static double smart_afr(uint64_t* smart)
afr = r;
}
if (smart[188] != SMART_UNASSIGNED) {
if (
/**
* Don't check Command_Timeout (188) for Seagate SMR (Shingled
* Magnetic Recording) disks.
*
* It's reported by users to be a not significative test as
* this value increases too often also on sane disks.
*/
strcmp(model, "ST8000AS0002-1NA17Z") != 0
&& smart[188] != SMART_UNASSIGNED
) {
/* with Seagate disks, there are three different 16 bits value reported */
/* the lowest one is the most significant */
double r = smart_afr_value(SMART_188_R, SMART_188_STEP, smart[188] & mask16);
@ -706,7 +716,7 @@ static void state_smart(unsigned n, tommy_list* low)
afr = 0;
printf(" SSD");
} else {
afr = smart_afr(devinfo->smart);
afr = smart_afr(devinfo->smart, devinfo->smart_model);
if (afr == 0) {
/* this happens only if no data */
@ -748,6 +758,10 @@ static void state_smart(unsigned n, tommy_list* low)
log_tag("smart:%s:%s\n", devinfo->file, devinfo->name);
if (devinfo->smart_serial[0])
log_tag("attr:%s:%s:serial:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->smart_serial, esc_buffer));
if (devinfo->smart_vendor[0])
log_tag("attr:%s:%s:vendor:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->smart_vendor, esc_buffer));
if (devinfo->smart_model[0])
log_tag("attr:%s:%s:model:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->smart_model, esc_buffer));
if (afr != 0)
log_tag("attr:%s:%s:afr:%g:%g\n", devinfo->file, devinfo->name, afr, poisson_prob_n_or_more_failures(afr, 1));
if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED)
@ -854,12 +868,16 @@ static int devtest(tommy_list* low, int operation)
if (c == 0) {
entry->smart_serial[0] = 0;
entry->smart_vendor[0] = 0;
entry->smart_model[0] = 0;
entry->file[0] = 0;
entry->name[0] = 0;
entry->smart[SMART_SIZE] = SMART_UNASSIGNED;
entry->smart[SMART_ROTATION_RATE] = 0;
} else {
snprintf(entry->smart_serial, sizeof(entry->smart_serial), "%u", c);
snprintf(entry->smart_serial, sizeof(entry->smart_serial), "S%u", c);
snprintf(entry->smart_vendor, sizeof(entry->smart_vendor), "V%u", c);
snprintf(entry->smart_model, sizeof(entry->smart_model), "M%u", c);
pathcpy(entry->file, sizeof(entry->name), "file");
pathcpy(entry->name, sizeof(entry->name), "name");
entry->smart[SMART_SIZE] = c * TERA;

View file

@ -2172,7 +2172,7 @@ static int devscan(tommy_list* list)
/**
* Get SMART attributes.
*/
static int devsmart(uint64_t device, const char* name, const char* custom, uint64_t* smart, char* serial)
static int devsmart(uint64_t device, const char* name, const char* custom, uint64_t* smart, char* serial, char* vendor, char* model)
{
char conv_buf[CONV_MAX];
WCHAR cmd[MAX_PATH + 128];
@ -2205,7 +2205,7 @@ retry:
/* LCOV_EXCL_STOP */
}
if (smartctl_attribute(f, file, name, smart, serial) != 0) {
if (smartctl_attribute(f, file, name, smart, serial, vendor, model) != 0) {
/* LCOV_EXCL_START */
pclose(f);
return -1;
@ -2434,7 +2434,7 @@ static void* thread_smart(void* arg)
{
devinfo_t* devinfo = arg;
if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial) != 0) {
if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial, devinfo->smart_vendor, devinfo->smart_model) != 0) {
/* LCOV_EXCL_START */
return (void*)-1;
/* LCOV_EXCL_STOP */

View file

@ -460,6 +460,8 @@ struct devinfo_struct {
struct devinfo_struct* parent; /**< Pointer at the parent if any. */
uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */
char smart_serial[SMART_MAX]; /**< SMART serial number. */
char smart_vendor[SMART_MAX]; /**< SMART vendor. */
char smart_model[SMART_MAX]; /**< SMART model. */
#if HAVE_PTHREAD
pthread_t thread;
#endif

View file

@ -1370,7 +1370,7 @@ static int smatch(const char* str, const char* pattern)
return 0;
}
int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial)
int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model)
{
unsigned i;
int inside;
@ -1416,6 +1416,8 @@ int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* sm
smart[SMART_SIZE] += attr[i] - '0';
}
}
} else if (sscanf(s, "Device Model: %63s %63s", vendor, model) == 2) {
} else if (sscanf(s, "Device Model: %63s", model) == 1) {
/* SCSI */
} else if (sscanf(s, "Serial number: %63s", serial) == 1) { /* note "n" of "number" lower case */
} else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT]) == 1) {

View file

@ -389,7 +389,7 @@ void malloc_fail(size_t size);
* Read smartctl attributes from a stream.
* Return 0 on success.
*/
int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial);
int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model);
/**
* Flush smartctl output from a stream.

View file

@ -950,7 +950,7 @@ static int devscan(tommy_list* list)
* Get SMART attributes.
*/
#if HAVE_LINUX_DEVICE
static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial)
static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial, char* vendor, char* model)
{
char cmd[128];
char file[128];
@ -978,7 +978,7 @@ static int devsmart(dev_t device, const char* name, const char* custom, uint64_t
/* LCOV_EXCL_STOP */
}
if (smartctl_attribute(f, file, name, smart, serial) != 0) {
if (smartctl_attribute(f, file, name, smart, serial, vendor, model) != 0) {
/* LCOV_EXCL_START */
pclose(f);
return -1;
@ -1175,7 +1175,7 @@ static void* thread_smart(void* arg)
#if HAVE_LINUX_DEVICE
devinfo_t* devinfo = arg;
if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial) != 0) {
if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial, devinfo->smart_vendor, devinfo->smart_model) != 0) {
/* LCOV_EXCL_START */
return (void*)-1;
/* LCOV_EXCL_STOP */