mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
Log the normalized, worst and threshold value of SMART attributes
This commit is contained in:
parent
ae453435f0
commit
2019aa4bb6
9 changed files with 135 additions and 93 deletions
105
cmdline/device.c
105
cmdline/device.c
|
|
@ -408,26 +408,26 @@ 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, const char* model)
|
||||
static double smart_afr(struct smart_struct* smart, const char* model)
|
||||
{
|
||||
double afr = 0;
|
||||
uint64_t mask32 = 0xffffffffU;
|
||||
uint64_t mask16 = 0xffffU;
|
||||
|
||||
/* do not estimate for not rotational */
|
||||
if (smart[INFO_ROTATION_RATE] == 0)
|
||||
if (smart[INFO_ROTATION_RATE].raw == 0)
|
||||
return 0;
|
||||
|
||||
if (smart[5] != SMART_UNASSIGNED) {
|
||||
double r = smart_afr_value(SMART_5_R, SMART_5_STEP, smart[5] & mask32);
|
||||
if (smart[5].raw != SMART_UNASSIGNED) {
|
||||
double r = smart_afr_value(SMART_5_R, SMART_5_STEP, smart[5].raw & mask32);
|
||||
if (afr < r)
|
||||
afr = r;
|
||||
}
|
||||
|
||||
if (smart[187] != SMART_UNASSIGNED) {
|
||||
if (smart[187].raw != SMART_UNASSIGNED) {
|
||||
/* with some disks, only the lower 16 bits are significant */
|
||||
/* See: http://web.archive.org/web/20130507072056/http://media.kingston.com/support/downloads/MKP_306_SMART_attribute.pdf */
|
||||
double r = smart_afr_value(SMART_187_R, SMART_187_STEP, smart[187] & mask16);
|
||||
double r = smart_afr_value(SMART_187_R, SMART_187_STEP, smart[187].raw & mask16);
|
||||
if (afr < r)
|
||||
afr = r;
|
||||
}
|
||||
|
|
@ -440,23 +440,23 @@ static double smart_afr(uint64_t* smart, const char* model)
|
|||
* and IronWolf disks to be a not significant test as
|
||||
* this value increases too often also on sane disks.
|
||||
*/
|
||||
strncmp(model, "ST", 2) != 0 && smart[188] != SMART_UNASSIGNED
|
||||
strncmp(model, "ST", 2) != 0 && smart[188].raw != 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);
|
||||
double r = smart_afr_value(SMART_188_R, SMART_188_STEP, smart[188].raw & mask16);
|
||||
if (afr < r)
|
||||
afr = r;
|
||||
}
|
||||
|
||||
if (smart[197] != SMART_UNASSIGNED) {
|
||||
double r = smart_afr_value(SMART_197_R, SMART_197_STEP, smart[197] & mask32);
|
||||
if (smart[197].raw != SMART_UNASSIGNED) {
|
||||
double r = smart_afr_value(SMART_197_R, SMART_197_STEP, smart[197].raw & mask32);
|
||||
if (afr < r)
|
||||
afr = r;
|
||||
}
|
||||
|
||||
if (smart[198] != SMART_UNASSIGNED) {
|
||||
double r = smart_afr_value(SMART_198_R, SMART_198_STEP, smart[198] & mask32);
|
||||
if (smart[198].raw != SMART_UNASSIGNED) {
|
||||
double r = smart_afr_value(SMART_198_R, SMART_198_STEP, smart[198].raw & mask32);
|
||||
if (afr < r)
|
||||
afr = r;
|
||||
}
|
||||
|
|
@ -544,21 +544,22 @@ static void state_smart_log(devinfo_t* devinfo, double afr)
|
|||
unsigned j;
|
||||
|
||||
log_tag("smart:%s:%s\n", devinfo->file, devinfo->name);
|
||||
if (devinfo->smart[SMART_ERROR_PROTOCOL] != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:error_protocol:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR_PROTOCOL]);
|
||||
if (devinfo->smart[SMART_ERROR_MEDIUM] != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:error_medium:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR_MEDIUM]);
|
||||
if (devinfo->smart[SMART_WEAR_LEVEL] != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:wear_level:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_WEAR_LEVEL]);
|
||||
if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS], devinfo->smart[SMART_FLAGS]);
|
||||
if (devinfo->smart[SMART_ERROR_PROTOCOL].raw != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:error_protocol:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR_PROTOCOL].raw);
|
||||
if (devinfo->smart[SMART_ERROR_MEDIUM].raw != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:error_medium:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR_MEDIUM].raw);
|
||||
if (devinfo->smart[SMART_WEAR_LEVEL].raw != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:wear_level:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_WEAR_LEVEL].raw);
|
||||
if (devinfo->smart[SMART_FLAGS].raw != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS].raw, devinfo->smart[SMART_FLAGS].raw);
|
||||
|
||||
if (afr != 0)
|
||||
log_tag("attr:%s:%s:afr:%g:%g\n", devinfo->file, devinfo->name, afr, poisson_prob_at_least_one_failure(afr));
|
||||
|
||||
for (j = 0; j < 256; ++j)
|
||||
if (devinfo->smart[j] != SMART_UNASSIGNED)
|
||||
log_tag("attr:%s:%s:%u:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, j, devinfo->smart[j], devinfo->smart[j]);
|
||||
if (devinfo->smart[j].raw != SMART_UNASSIGNED) {
|
||||
log_tag("attr:%s:%s:%u:%" PRIu64 ":%" PRIx64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%s\n", devinfo->file, devinfo->name, j, devinfo->smart[j].raw, devinfo->smart[j].raw, devinfo->smart[j].norm, devinfo->smart[j].worst, devinfo->smart[j].thresh, devinfo->smart[j].name);
|
||||
}
|
||||
|
||||
int temp = smart_temp(devinfo);
|
||||
if (temp >= 0)
|
||||
|
|
@ -627,8 +628,8 @@ static void state_smart(struct snapraid_state* state, unsigned n, tommy_list* lo
|
|||
|
||||
/* clear attributes to ignore */
|
||||
for (j = 0; j < SMART_IGNORE_MAX; ++j) {
|
||||
devinfo->smart[state->smartignore[j]] = SMART_UNASSIGNED;
|
||||
devinfo->smart[devinfo->smartignore[j]] = SMART_UNASSIGNED;
|
||||
devinfo->smart[state->smartignore[j]].raw = SMART_UNASSIGNED;
|
||||
devinfo->smart[devinfo->smartignore[j]].raw = SMART_UNASSIGNED;
|
||||
}
|
||||
|
||||
int temp = smart_temp(devinfo);
|
||||
|
|
@ -637,18 +638,18 @@ static void state_smart(struct snapraid_state* state, unsigned n, tommy_list* lo
|
|||
else
|
||||
printf(" -");
|
||||
|
||||
if (devinfo->smart[SMART_POWER_ON_HOURS] != SMART_UNASSIGNED)
|
||||
printf("%7" PRIu64, (devinfo->smart[SMART_POWER_ON_HOURS] & mask32) / 24);
|
||||
if (devinfo->smart[SMART_POWER_ON_HOURS].raw != SMART_UNASSIGNED)
|
||||
printf("%7" PRIu64, (devinfo->smart[SMART_POWER_ON_HOURS].raw & mask32) / 24);
|
||||
else
|
||||
printf(" -");
|
||||
|
||||
uint64_t error_count = 0;
|
||||
if (devinfo->smart[SMART_ERROR_PROTOCOL] != SMART_UNASSIGNED && devinfo->smart[SMART_ERROR_PROTOCOL] != 0)
|
||||
error_count += devinfo->smart[SMART_ERROR_PROTOCOL];
|
||||
if (devinfo->smart[SMART_ERROR_MEDIUM] != SMART_UNASSIGNED && devinfo->smart[SMART_ERROR_MEDIUM] != 0)
|
||||
error_count += devinfo->smart[SMART_ERROR_MEDIUM];
|
||||
if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED)
|
||||
flag = devinfo->smart[SMART_FLAGS];
|
||||
if (devinfo->smart[SMART_ERROR_PROTOCOL].raw != SMART_UNASSIGNED && devinfo->smart[SMART_ERROR_PROTOCOL].raw != 0)
|
||||
error_count += devinfo->smart[SMART_ERROR_PROTOCOL].raw;
|
||||
if (devinfo->smart[SMART_ERROR_MEDIUM].raw != SMART_UNASSIGNED && devinfo->smart[SMART_ERROR_MEDIUM].raw != 0)
|
||||
error_count += devinfo->smart[SMART_ERROR_MEDIUM].raw;
|
||||
if (devinfo->smart[SMART_FLAGS].raw != SMART_UNASSIGNED)
|
||||
flag = devinfo->smart[SMART_FLAGS].raw;
|
||||
else
|
||||
flag = 0;
|
||||
|
||||
|
|
@ -697,8 +698,8 @@ static void state_smart(struct snapraid_state* state, unsigned n, tommy_list* lo
|
|||
}
|
||||
}
|
||||
|
||||
if (devinfo->smart[SMART_WEAR_LEVEL] != SMART_UNASSIGNED) {
|
||||
printf(" %3" PRIu64 "%%", devinfo->smart[SMART_WEAR_LEVEL]);
|
||||
if (devinfo->smart[SMART_WEAR_LEVEL].raw != SMART_UNASSIGNED) {
|
||||
printf(" %3" PRIu64 "%%", devinfo->smart[SMART_WEAR_LEVEL].raw);
|
||||
} else {
|
||||
printf(" -");
|
||||
}
|
||||
|
|
@ -910,10 +911,14 @@ int devtest(tommy_list* high, tommy_list* low, int operation)
|
|||
|
||||
for (j = 0; j < 256; ++j) {
|
||||
switch (count) {
|
||||
case 0 : entry->smart[j] = 0; break;
|
||||
case 1 : entry->smart[j] = SMART_UNASSIGNED; break;
|
||||
case 0 :
|
||||
entry->smart[j].raw = 0;
|
||||
break;
|
||||
case 1 :
|
||||
entry->smart[j].raw = SMART_UNASSIGNED;
|
||||
break;
|
||||
default :
|
||||
entry->smart[j] = 0;
|
||||
entry->smart[j].raw = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -926,21 +931,21 @@ int devtest(tommy_list* high, tommy_list* low, int operation)
|
|||
pathcpy(entry->name, sizeof(entry->name), devinfo->name);
|
||||
entry->info[INFO_SIZE] = count * TERA;
|
||||
entry->info[INFO_ROTATION_RATE] = 7200;
|
||||
entry->smart[SMART_ERROR_MEDIUM] = 0;
|
||||
entry->smart[SMART_ERROR_PROTOCOL] = 0;
|
||||
entry->smart[SMART_FLAGS] = SMART_UNASSIGNED;
|
||||
entry->smart[SMART_TEMPERATURE_CELSIUS] = 27;
|
||||
entry->smart[SMART_ERROR_MEDIUM].raw = 0;
|
||||
entry->smart[SMART_ERROR_PROTOCOL].raw = 0;
|
||||
entry->smart[SMART_FLAGS].raw = SMART_UNASSIGNED;
|
||||
entry->smart[SMART_TEMPERATURE_CELSIUS].raw = 27;
|
||||
|
||||
switch (count) {
|
||||
case 3 : entry->smart[SMART_ERROR_PROTOCOL] = 1; break;
|
||||
case 4 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_UNSUPPORTED; break;
|
||||
case 5 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_COMMAND; break;
|
||||
case 6 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_OPEN; break;
|
||||
case 7 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_FAIL; break;
|
||||
case 8 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL; break;
|
||||
case 9 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL_LOGGED; break;
|
||||
case 10 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR_LOGGED; break;
|
||||
case 11 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_SELFERROR_LOGGED; break;
|
||||
case 3 : entry->smart[SMART_ERROR_PROTOCOL].raw = 1; break;
|
||||
case 4 : entry->smart[SMART_FLAGS].raw = SMARTCTL_FLAG_UNSUPPORTED; break;
|
||||
case 5 : entry->smart[SMART_FLAGS].raw = SMARTCTL_FLAG_COMMAND; break;
|
||||
case 6 : entry->smart[SMART_FLAGS].raw = SMARTCTL_FLAG_OPEN; break;
|
||||
case 7 : entry->smart[SMART_FLAGS].raw = SMARTCTL_FLAG_FAIL; break;
|
||||
case 8 : entry->smart[SMART_FLAGS].raw = SMARTCTL_FLAG_PREFAIL; break;
|
||||
case 9 : entry->smart[SMART_FLAGS].raw = SMARTCTL_FLAG_PREFAIL_LOGGED; break;
|
||||
case 10 : entry->smart[SMART_FLAGS].raw = SMARTCTL_FLAG_ERROR_LOGGED; break;
|
||||
case 11 : entry->smart[SMART_FLAGS].raw = SMARTCTL_FLAG_SELFERROR_LOGGED; break;
|
||||
}
|
||||
|
||||
entry->power = POWER_ACTIVE;
|
||||
|
|
|
|||
|
|
@ -2506,7 +2506,7 @@ static int devscan(tommy_list* list)
|
|||
/**
|
||||
* Get SMART attributes.
|
||||
*/
|
||||
static int devsmart(uint64_t device, const char* name, const char* smartctl, uint64_t* smart, uint64_t* info, char* serial, char* family, char* model, char* inter)
|
||||
static int devsmart(uint64_t device, const char* name, const char* smartctl, struct smart_struct* smart, uint64_t* info, char* serial, char* family, char* model, char* inter)
|
||||
{
|
||||
char conv_buf[CONV_MAX];
|
||||
WCHAR cmd[MAX_PATH + 128];
|
||||
|
|
@ -2574,7 +2574,7 @@ retry:
|
|||
* Note that getting error 4 is instead very common, even with full info gathering.
|
||||
*/
|
||||
if ((ret == 0 || ret == 2)
|
||||
&& smart[9] == SMART_UNASSIGNED
|
||||
&& smart[SMART_POWER_ON_HOURS].raw == SMART_UNASSIGNED
|
||||
&& info[INFO_SIZE] == SMART_UNASSIGNED
|
||||
&& info[INFO_ROTATION_RATE] == SMART_UNASSIGNED
|
||||
) {
|
||||
|
|
@ -2587,7 +2587,7 @@ retry:
|
|||
}
|
||||
|
||||
/* store the smartctl return value */
|
||||
smart[SMART_FLAGS] = ret;
|
||||
smart[SMART_FLAGS].raw = ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2738,7 +2738,7 @@ static void devattr(uint64_t device, const char* name, const char* wfile, uint64
|
|||
/**
|
||||
* Get POWER state
|
||||
*/
|
||||
static int devprobe(uint64_t device, const char* name, const char* smartctl, int* power, uint64_t* smart, uint64_t* info, char* serial, char* family, char* model, char* interf)
|
||||
static int devprobe(uint64_t device, const char* name, const char* smartctl, int* power, struct smart_struct* smart, uint64_t* info, char* serial, char* family, char* model, char* interf)
|
||||
{
|
||||
char conv_buf[CONV_MAX];
|
||||
WCHAR cmd[MAX_PATH + 128];
|
||||
|
|
@ -2819,7 +2819,7 @@ retry:
|
|||
*power = POWER_ACTIVE;
|
||||
|
||||
/* store the return smartctl return value */
|
||||
smart[SMART_FLAGS] = WEXITSTATUS(ret);
|
||||
smart[SMART_FLAGS].raw = WEXITSTATUS(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -422,6 +422,7 @@ int randomize(void* ptr, size_t size);
|
|||
* Standard SMART attributes.
|
||||
*/
|
||||
#define SMART_REALLOCATED_SECTOR_COUNT 5
|
||||
#define SMART_POWER_ON_HOURS 9
|
||||
#define SMART_UNCORRECTABLE_ERROR_CNT 187
|
||||
#define SMART_COMMAND_TIMEOUT 188
|
||||
#define SMART_CURRENT_PENDING_SECTOR 197
|
||||
|
|
@ -509,6 +510,14 @@ int randomize(void* ptr, size_t size);
|
|||
#define POWER_ACTIVE 1
|
||||
#define POWER_UNKNOWN -1
|
||||
|
||||
struct smart_struct {
|
||||
char name[128]; /**< SMART attribute name. */
|
||||
uint64_t raw; /**< SMART attributes raw. */
|
||||
uint64_t norm; /**< SMART attributes normalized. */
|
||||
uint64_t worst; /**< SMART attributes worst. */
|
||||
uint64_t thresh; /**< SMART attributes threshold. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Device info entry.
|
||||
*/
|
||||
|
|
@ -524,7 +533,7 @@ struct devinfo_struct {
|
|||
#endif
|
||||
struct devinfo_struct* parent; /**< Pointer at the parent if any. */
|
||||
struct devinfo_struct* split; /**< Pointer at first split if any. */
|
||||
uint64_t smart[SMART_COUNT]; /**< SMART attributes. */
|
||||
struct smart_struct smart[SMART_COUNT]; /**< All smart values. */
|
||||
uint64_t info[INFO_COUNT]; /**< Info attributes. */
|
||||
uint64_t access_stat; /**< Access stat info. */
|
||||
char serial[SMART_MAX]; /**< Serial number. */
|
||||
|
|
|
|||
|
|
@ -1702,11 +1702,11 @@ 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, uint64_t* info, char* serial, char* family, char* model, char* inter)
|
||||
int smartctl_attribute(FILE* f, const char* file, const char* name, struct smart_struct* smart, uint64_t* info, char* serial, char* family, char* model, char* inter)
|
||||
{
|
||||
unsigned i;
|
||||
int inside;
|
||||
uint64_t dummy_smart[SMART_COUNT];
|
||||
struct smart_struct dummy_smart[SMART_COUNT];
|
||||
uint64_t dummy_info[INFO_COUNT];
|
||||
char dummy_serial[SMART_MAX];
|
||||
char dummy_family[SMART_MAX];
|
||||
|
|
@ -1732,8 +1732,9 @@ int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* sm
|
|||
*family = 0;
|
||||
*model = 0;
|
||||
*inter = 0;
|
||||
memset(smart, 0, sizeof(struct smart_struct) * SMART_COUNT);
|
||||
for (i = 0; i < SMART_COUNT; ++i)
|
||||
smart[i] = SMART_UNASSIGNED;
|
||||
smart[i].raw = SMART_UNASSIGNED;
|
||||
for (i = 0; i < INFO_COUNT; ++i)
|
||||
info[i] = SMART_UNASSIGNED;
|
||||
|
||||
|
|
@ -1743,7 +1744,9 @@ int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* sm
|
|||
char buf[256];
|
||||
unsigned id;
|
||||
uint64_t raw;
|
||||
uint64_t normalized;
|
||||
uint64_t norm;
|
||||
uint64_t worst;
|
||||
uint64_t thresh;
|
||||
char* s;
|
||||
|
||||
s = fgets(buf, sizeof(buf), f);
|
||||
|
|
@ -1810,16 +1813,16 @@ int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* sm
|
|||
strcpy(inter, "PCIe");
|
||||
else
|
||||
strcpy(inter, "SCSI");
|
||||
} else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT]) == 1) {
|
||||
} else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS]) == 1) {
|
||||
} else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS]) == 1) {
|
||||
} else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT]) == 1) {
|
||||
} else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT]) == 1) {
|
||||
} else if (sscanf(s, " number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS]) == 1) { /* note "n" of "number" lower case */
|
||||
} else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT].raw) == 1) {
|
||||
} else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS].raw) == 1) {
|
||||
} else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].raw) == 1) {
|
||||
} else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT].raw) == 1) {
|
||||
} else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT].raw) == 1) {
|
||||
} else if (sscanf(s, " number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS].raw) == 1) { /* note "n" of "number" lower case */
|
||||
} else if (sscanf(s, "Non-medium error count: %" SCNu64, &raw) == 1) {
|
||||
smart[SMART_ERROR_PROTOCOL] = raw;
|
||||
smart[SMART_ERROR_PROTOCOL].raw = raw;
|
||||
} else if (sscanf(s, "Medium error count: %" SCNu64, &raw) == 1) {
|
||||
smart[SMART_ERROR_MEDIUM] = raw;
|
||||
smart[SMART_ERROR_MEDIUM].raw = raw;
|
||||
/* ATA */
|
||||
} else if (smatch(s, "ATA Version is:") == 0) {
|
||||
strcpy(inter, "ATA");
|
||||
|
|
@ -1830,24 +1833,25 @@ int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* sm
|
|||
} else if (smatch(s, "Transport Type: Parallel") == 0) {
|
||||
strcpy(inter, "PATA");
|
||||
} else if (smatch(s, "No Errors Logged") == 0) {
|
||||
smart[SMART_ERROR_PROTOCOL] = 0;
|
||||
smart[SMART_ERROR_PROTOCOL].raw = 0;
|
||||
} else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) {
|
||||
smart[SMART_ERROR_PROTOCOL] = raw;
|
||||
smart[SMART_ERROR_PROTOCOL].raw = raw;
|
||||
/* NVME */
|
||||
} else if (smatch(s, "NVMe Version:") == 0) {
|
||||
strcpy(inter, "NVMe");
|
||||
} else if (sscanf(s, "Media and Data Integrity Errors: %" SCNu64, &raw) == 1) {
|
||||
smart[SMART_ERROR_MEDIUM] = raw;
|
||||
smart[SMART_ERROR_MEDIUM].raw = raw;
|
||||
} else if (sscanf(s, "Error Information Log Entries: %" SCNu64, &raw) == 1) {
|
||||
smart[SMART_ERROR_PROTOCOL] = raw;
|
||||
smart[SMART_ERROR_PROTOCOL].raw = raw;
|
||||
} else if (sscanf(s, "Percentage Used: %" SCNu64 "%%", &raw) == 1) { /* NVME */
|
||||
if (raw <= 100)
|
||||
smart[SMART_WEAR_LEVEL] = raw;
|
||||
smart[SMART_WEAR_LEVEL].raw = raw;
|
||||
/* Attributes */
|
||||
} else if (smatch(s, "ID#") == 0) {
|
||||
inside = 1;
|
||||
} else if (inside) {
|
||||
if (sscanf(s, "%u %*s %*s %" SCNu64 " %*s %*s %*s %*s %*s %" SCNu64, &id, &normalized, &raw) != 3) {
|
||||
char id_name[128] = { 0 };
|
||||
if (sscanf(s, "%u %127s %*s %" SCNu64 " %" SCNu64 " %" SCNu64 " %*s %*s %*s %" SCNu64, &id, id_name, &norm, &worst, &thresh, &raw) != 6) {
|
||||
log_fatal(EEXTERNAL, "Invalid smartctl line '%s'.\n", s);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1859,7 +1863,11 @@ int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* sm
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
smart[id] = raw;
|
||||
smart[id].raw = raw;
|
||||
smart[id].norm = norm;
|
||||
smart[id].worst = worst;
|
||||
smart[id].thresh = thresh;
|
||||
pathcpy(smart[id].name, sizeof(smart[id].name), id_name);
|
||||
|
||||
/*
|
||||
* Map normalized health percentage to our unified wear level for SSDs
|
||||
|
|
@ -1867,12 +1875,12 @@ int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* sm
|
|||
* 231: SSD_Life_Left (Kingston/WD)
|
||||
* 233: Media_Wearout_Indicator (Intel)
|
||||
*/
|
||||
if (normalized <= 100) {
|
||||
if (norm <= 100) {
|
||||
switch (id) {
|
||||
case 177 :
|
||||
case 233 :
|
||||
case 231 :
|
||||
smart[SMART_WEAR_LEVEL] = 100 - normalized;
|
||||
smart[SMART_WEAR_LEVEL].raw = 100 - norm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1904,9 +1912,9 @@ int smartctl_flush(FILE* f, const char* file, const char* name)
|
|||
|
||||
int smart_temp(devinfo_t* devinfo)
|
||||
{
|
||||
uint64_t t = devinfo->smart[SMART_TEMPERATURE_CELSIUS] & 0xFFFF;
|
||||
uint64_t t = devinfo->smart[SMART_TEMPERATURE_CELSIUS].raw & 0xFFFF;
|
||||
if (t == SMART_UNASSIGNED)
|
||||
t = devinfo->smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS] & 0xFFFF;
|
||||
t = devinfo->smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS].raw & 0xFFFF;
|
||||
|
||||
/* validate temperature */
|
||||
if (t == SMART_UNASSIGNED)
|
||||
|
|
|
|||
|
|
@ -453,7 +453,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, uint64_t* info, char* serial, char* family, char* model, char* interf);
|
||||
int smartctl_attribute(FILE* f, const char* file, const char* name, struct smart_struct* smart, uint64_t* info, char* serial, char* family, char* model, char* interf);
|
||||
|
||||
/**
|
||||
* Flush smartctl output from a stream.
|
||||
|
|
|
|||
|
|
@ -1479,7 +1479,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* smartctl, uint64_t* smart, uint64_t* info, char* serial, char* family, char* model, char* interface)
|
||||
static int devsmart(dev_t device, const char* name, const char* smartctl, struct smart_struct* smart, uint64_t* info, char* serial, char* family, char* model, char* interface)
|
||||
{
|
||||
char cmd[PATH_MAX + 64];
|
||||
char file[PATH_MAX];
|
||||
|
|
@ -1550,7 +1550,7 @@ static int devsmart(dev_t device, const char* name, const char* smartctl, uint64
|
|||
}
|
||||
|
||||
/* store the return smartctl return value */
|
||||
smart[SMART_FLAGS] = WEXITSTATUS(ret);
|
||||
smart[SMART_FLAGS].raw = WEXITSTATUS(ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1717,7 +1717,7 @@ static void devattr(dev_t device, uint64_t* info, char* serial, char* family, ch
|
|||
* Get POWER state.
|
||||
*/
|
||||
#if HAVE_LINUX_DEVICE
|
||||
static int devprobe(dev_t device, const char* name, const char* smartctl, int* power, uint64_t* smart, uint64_t* info, char* serial, char* family, char* model, char* interface)
|
||||
static int devprobe(dev_t device, const char* name, const char* smartctl, int* power, struct smart_struct* smart, uint64_t* info, char* serial, char* family, char* model, char* interface)
|
||||
{
|
||||
char cmd[PATH_MAX + 64];
|
||||
char file[PATH_MAX];
|
||||
|
|
@ -1795,7 +1795,7 @@ static int devprobe(dev_t device, const char* name, const char* smartctl, int* p
|
|||
*power = POWER_ACTIVE;
|
||||
|
||||
/* store the return smartctl return value */
|
||||
smart[SMART_FLAGS] = WEXITSTATUS(ret);
|
||||
smart[SMART_FLAGS].raw = WEXITSTATUS(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1794,7 +1794,7 @@ The raw flags value (uint, hexadecimal).
|
|||
.PD
|
||||
.RE
|
||||
.TP
|
||||
.B attr:<device_file>:<disk_name>[/<split_index>]:<id>:<value_decimal>:<value_hex>
|
||||
.B attr:<device_file>:<disk_name>[/<split_index>]:<id>:<raw_decimal>:<raw_hex>:<norm>:<worst>:<thresh>:<name>
|
||||
Logs the raw value of any assigned SMART attribute.
|
||||
.RS 4
|
||||
.PD 0
|
||||
|
|
@ -1802,11 +1802,23 @@ Logs the raw value of any assigned SMART attribute.
|
|||
.I <id>
|
||||
The SMART attribute ID (uint).
|
||||
.HP 4
|
||||
.I <value_decimal>
|
||||
.I <raw_decimal>
|
||||
The raw attribute value (uint, decimal).
|
||||
.HP 4
|
||||
.I <value_hex>
|
||||
.I <raw_hex>
|
||||
The raw attribute value (uint, hexadecimal).
|
||||
.HP 4
|
||||
.I <norm>
|
||||
The normalized value (uint).
|
||||
.HP 4
|
||||
.I <worst>
|
||||
The worst value (uint).
|
||||
.HP 4
|
||||
.I <thresh>
|
||||
The threshold value (uint).
|
||||
.HP 4
|
||||
.I <name>
|
||||
Name of the attribute.
|
||||
.PD
|
||||
.RE
|
||||
.TP
|
||||
|
|
|
|||
|
|
@ -1121,12 +1121,16 @@ Command Smart And Probe Tags
|
|||
<flags_decimal> - The raw flags value (uint, decimal).
|
||||
<flags_hex> - The raw flags value (uint, hexadecimal).
|
||||
|
||||
=attr:<device_file>:<disk_name>[/<split_index>]:<id>:<value_decimal>:<value_hex>
|
||||
=attr:<device_file>:<disk_name>[/<split_index>]:<id>:<raw_decimal>:<raw_hex>:<norm>:<worst>:<thresh>:<name>
|
||||
Logs the raw value of any assigned SMART attribute.
|
||||
|
||||
<id> - The SMART attribute ID (uint).
|
||||
<value_decimal> - The raw attribute value (uint, decimal).
|
||||
<value_hex> - The raw attribute value (uint, hexadecimal).
|
||||
<raw_decimal> - The raw attribute value (uint, decimal).
|
||||
<raw_hex> - The raw attribute value (uint, hexadecimal).
|
||||
<norm> - The normalized value (uint).
|
||||
<worst> - The worst value (uint).
|
||||
<thresh> - The threshold value (uint).
|
||||
<name> - Name of the attribute.
|
||||
|
||||
=attr:<device_file>:<disk_name>[/<split_index>]:power:active
|
||||
Logs that the device was confirmed to be in an active power
|
||||
|
|
|
|||
|
|
@ -1167,12 +1167,16 @@ Tags logging specific disk identification and attribute values.
|
|||
<flags_decimal> - The raw flags value (uint, decimal).
|
||||
<flags_hex> - The raw flags value (uint, hexadecimal).
|
||||
|
||||
attr:<device_file>:<disk_name>[/<split_index>]:<id>:<value_decimal>:<value_hex>
|
||||
attr:<device_file>:<disk_name>[/<split_index>]:<id>:<raw_decimal>:<raw_hex>:<norm>:<worst>:<thresh>:<name>
|
||||
Logs the raw value of any assigned SMART attribute.
|
||||
|
||||
<id> - The SMART attribute ID (uint).
|
||||
<value_decimal> - The raw attribute value (uint, decimal).
|
||||
<value_hex> - The raw attribute value (uint, hexadecimal).
|
||||
<raw_decimal> - The raw attribute value (uint, decimal).
|
||||
<raw_hex> - The raw attribute value (uint, hexadecimal).
|
||||
<norm> - The normalized value (uint).
|
||||
<worst> - The worst value (uint).
|
||||
<thresh> - The threshold value (uint).
|
||||
<name> - Name of the attribute.
|
||||
|
||||
attr:<device_file>:<disk_name>[/<split_index>]:power:active
|
||||
Logs that the device was confirmed to be in an active power
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue