Report the smartctl fail/prefail conditions

This commit is contained in:
Andrea Mazzoleni 2015-01-24 17:55:59 +01:00
parent 3df837b224
commit 356c36cda0
3 changed files with 67 additions and 21 deletions

View file

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

View file

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

View file

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