mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Report the smartctl fail/prefail conditions
This commit is contained in:
parent
3df837b224
commit
356c36cda0
3 changed files with 67 additions and 21 deletions
|
|
@ -313,12 +313,14 @@ static void state_smart(int verbose, unsigned n, tommy_list* low)
|
|||
unsigned j;
|
||||
size_t device_pad;
|
||||
size_t serial_pad;
|
||||
int have_parent;
|
||||
double array_failure_rate;
|
||||
double p_at_least_one_failure;
|
||||
|
||||
/* compute lengths for padding */
|
||||
device_pad = 0;
|
||||
serial_pad = 0;
|
||||
have_parent = 0;
|
||||
for (i = tommy_list_head(low); i != 0; i = i->next) {
|
||||
size_t len;
|
||||
devinfo_t* devinfo = i->data;
|
||||
|
|
@ -330,19 +332,22 @@ static void state_smart(int verbose, unsigned n, tommy_list* low)
|
|||
len = strlen(devinfo->smart_serial);
|
||||
if (len > serial_pad)
|
||||
serial_pad = len;
|
||||
|
||||
if (devinfo->parent != 0)
|
||||
have_parent = 1;
|
||||
}
|
||||
|
||||
printf("SnapRAID SMART report:\n");
|
||||
printf("\n");
|
||||
printf(" Temp");
|
||||
printf(" Power");
|
||||
printf(" Error");
|
||||
printf(" Error");
|
||||
printf(" FP");
|
||||
printf(" Size");
|
||||
printf("\n");
|
||||
printf(" C°");
|
||||
printf(" C");
|
||||
printf(" OnDays");
|
||||
printf(" Count");
|
||||
printf(" Count");
|
||||
printf(" ");
|
||||
printf(" TB");
|
||||
printf(" "); printl("Serial", serial_pad);
|
||||
|
|
@ -356,6 +361,7 @@ static void state_smart(int verbose, unsigned n, tommy_list* low)
|
|||
for (i = tommy_list_head(low); i != 0; i = i->next) {
|
||||
devinfo_t* devinfo = i->data;
|
||||
double afr;
|
||||
uint64_t flag;
|
||||
|
||||
if (devinfo->smart[194] != SMART_UNASSIGNED)
|
||||
printf("%7" PRIu64, devinfo->smart[194]);
|
||||
|
|
@ -369,18 +375,39 @@ static void state_smart(int verbose, unsigned n, tommy_list* low)
|
|||
else
|
||||
printf(" -");
|
||||
|
||||
if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED)
|
||||
printf("%6" PRIu64, devinfo->smart[SMART_ERROR]);
|
||||
if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED)
|
||||
flag = devinfo->smart[SMART_FLAGS];
|
||||
else
|
||||
printf(" -");
|
||||
flag = 0;
|
||||
if (flag & SMARTCTL_FLAG_FAIL)
|
||||
printf(" FAIL");
|
||||
else if (flag & SMARTCTL_FLAG_PREFAIL)
|
||||
printf(" PREFAIL");
|
||||
else if (flag & SMARTCTL_FLAG_PREFAIL_LOGGED)
|
||||
printf(" PREFAIL");
|
||||
else if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED
|
||||
&& devinfo->smart[SMART_ERROR] != 0)
|
||||
printf("%8" PRIu64, devinfo->smart[SMART_ERROR]);
|
||||
else if (flag & SMARTCTL_FLAG_ERROR)
|
||||
printf(" ERROR");
|
||||
else if (flag & SMARTCTL_FLAG_ERROR_LOGGED)
|
||||
printf(" ERROR");
|
||||
else if (flag & SMARTCTL_FLAG_OPEN)
|
||||
printf(" n/o");
|
||||
else if (flag & SMARTCTL_FLAG_COMMAND)
|
||||
printf(" n/c");
|
||||
else if (devinfo->smart[SMART_ERROR] == 0)
|
||||
printf(" 0");
|
||||
else
|
||||
printf(" -");
|
||||
|
||||
afr = smart_afr(devinfo->smart);
|
||||
|
||||
/* use only afr of disks in the array */
|
||||
if (devinfo->parent != 0)
|
||||
if (devinfo->parent != 0 || !have_parent)
|
||||
array_failure_rate += afr;
|
||||
|
||||
printf("%5.0f%%", poisson_prob_n_or_more_failures(afr, 1) * 100);
|
||||
printf("%4.0f%%", poisson_prob_n_or_more_failures(afr, 1) * 100);
|
||||
|
||||
if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED)
|
||||
printf(" %2.1f", devinfo->smart[SMART_SIZE] / 1E12);
|
||||
|
|
@ -403,7 +430,10 @@ static void state_smart(int verbose, unsigned n, tommy_list* low)
|
|||
if (*devinfo->name)
|
||||
printf("%s", devinfo->name);
|
||||
else
|
||||
printf("- (not in stats)");
|
||||
printf("-");
|
||||
|
||||
if (devinfo->parent == 0 && have_parent)
|
||||
printf(" (not in stats)");
|
||||
|
||||
printf("\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -315,13 +315,25 @@ int randomize(void* ptr, size_t size);
|
|||
/**
|
||||
* SMART attributes.
|
||||
*/
|
||||
#define SMART_COUNT (256+2)
|
||||
#define SMART_COUNT (256+3)
|
||||
|
||||
/**
|
||||
* Additional info attributes.
|
||||
*/
|
||||
#define SMART_ERROR 256 /**< ATA Error count. */
|
||||
#define SMART_SIZE 257 /**< Size in bytes. */
|
||||
#define SMART_FLAGS 258 /**< Flags returned by smartctl. */
|
||||
|
||||
/**
|
||||
* Flags returned by smartctl.
|
||||
*/
|
||||
#define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open failed. */
|
||||
#define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or other ATA command to the disk failed. */
|
||||
#define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */
|
||||
#define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */
|
||||
#define SMARTCTL_FLAG_PREFAIL_LOGGED (1 << 5) /**< SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. */
|
||||
#define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */
|
||||
#define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */
|
||||
|
||||
/**
|
||||
* SMART max attribute length.
|
||||
|
|
|
|||
|
|
@ -637,7 +637,7 @@ static int devsmart(dev_t device, uint64_t* smart, char* serial)
|
|||
f = popen(cmd, "r");
|
||||
if (!f) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Failed to run smartctrl -a on device '%u:%u' (from open).\n", major(device), minor(device));
|
||||
fprintf(stderr, "Failed to run smartctl -a on device '%u:%u' (from popen).\n", major(device), minor(device));
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
|
@ -647,7 +647,7 @@ static int devsmart(dev_t device, uint64_t* smart, char* serial)
|
|||
char buf[256];
|
||||
char attr[64];
|
||||
unsigned id;
|
||||
unsigned long long raw;
|
||||
uint64_t raw;
|
||||
char* s;
|
||||
|
||||
s = fgets(buf, sizeof(buf), f);
|
||||
|
|
@ -665,7 +665,7 @@ static int devsmart(dev_t device, uint64_t* smart, char* serial)
|
|||
inside = 1;
|
||||
} else if (strncmp(s, "No Errors Logged", 16) == 0) {
|
||||
smart[SMART_ERROR] = 0;
|
||||
} else if (sscanf(s, "ATA Error Count: %llu", &raw) == 1) {
|
||||
} else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) {
|
||||
smart[SMART_ERROR] = raw;
|
||||
} else if (sscanf(s, "Serial Number: %63s", serial) == 1) {
|
||||
} else if (sscanf(s, "User Capacity: %63s", attr) == 1) {
|
||||
|
|
@ -677,9 +677,9 @@ static int devsmart(dev_t device, uint64_t* smart, char* serial)
|
|||
}
|
||||
}
|
||||
} else if (inside) {
|
||||
if (sscanf(s, "%u %*s %*s %*u %*u %*u %*s %*s %*s %llu", &id, &raw) != 2) {
|
||||
if (sscanf(s, "%u %*s %*s %*u %*u %*u %*s %*s %*s %" SCNu64, &id, &raw) != 2) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Invalid smartctrl line '%s'.\n", buf);
|
||||
fprintf(stderr, "Invalid smartctl line '%s'.\n", buf);
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
|
@ -698,23 +698,27 @@ static int devsmart(dev_t device, uint64_t* smart, char* serial)
|
|||
ret = pclose(f);
|
||||
if (!WIFEXITED(ret)) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Failed to run smartctrl -a on device '%u:%u' (not exited).\n", major(device), minor(device));
|
||||
fprintf(stderr, "Failed to run smartctl -a on device '%u:%u' (not exited).\n", major(device), minor(device));
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
if (WEXITSTATUS(ret) == 127) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Failed to run smartctrl -a on device '%u:%u' (from sh).\n", major(device), minor(device));
|
||||
fprintf(stderr, "Failed to run smartctl -a on device '%u:%u' (from sh).\n", major(device), minor(device));
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
if (WEXITSTATUS(ret) != 0) {
|
||||
/* check only first bit, as other bits are used to report other conditions */
|
||||
if ((WEXITSTATUS(ret) & 1) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Failed to run smartctrl -a on device '%u:%u' with return code %d.\n", major(device), minor(device), WEXITSTATUS(ret));
|
||||
fprintf(stderr, "Failed to run smartctl -a on device '%u:%u' with return code %xh.\n", major(device), minor(device), WEXITSTATUS(ret));
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* store the return smartctl return value */
|
||||
smart[SMART_FLAGS] = WEXITSTATUS(ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -750,7 +754,7 @@ static int devdown(dev_t device)
|
|||
}
|
||||
if (WEXITSTATUS(ret) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "Failed to run hdparm -y on device '%u:%u' with return code %u.\n", major(device), minor(device), WEXITSTATUS(ret));
|
||||
fprintf(stderr, "Failed to run hdparm -y on device '%u:%u' with return code %xh.\n", major(device), minor(device), WEXITSTATUS(ret));
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
|
@ -861,7 +865,7 @@ static void* thread_spindown(void* arg)
|
|||
}
|
||||
|
||||
/**
|
||||
* Thread for spinning down.
|
||||
* Thread for getting smart info.
|
||||
*/
|
||||
static void* thread_smart(void* arg)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue