Log the normalized, worst and threshold value of SMART attributes

This commit is contained in:
Andrea Mazzoleni 2026-02-16 10:47:43 +01:00
parent ae453435f0
commit 2019aa4bb6
9 changed files with 135 additions and 93 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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. */

View file

@ -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)

View file

@ -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.

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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