From a1754b558f51f69c7b9cfc126b33220e73d7470f Mon Sep 17 00:00:00 2001 From: chrfranke <chrfranke@4ea69e1a-61f1-4043-bf83-b5c94c648137> Date: Sat, 31 Oct 2009 16:59:55 +0000 Subject: [PATCH] smartctl: Ignore normalized attribute value and threshold if 'raw64' or 'hex64' format is selected. git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@2980 4ea69e1a-61f1-4043-bf83-b5c94c648137 --- smartmontools/CHANGELOG | 3 ++ smartmontools/atacmds.cpp | 62 +++++------------------------- smartmontools/atacmds.h | 8 +--- smartmontools/ataprint.cpp | 79 +++++++++++++++++++++++++++++--------- 4 files changed, 75 insertions(+), 77 deletions(-) diff --git a/smartmontools/CHANGELOG b/smartmontools/CHANGELOG index 11c221a7b..611f3d3f0 100644 --- a/smartmontools/CHANGELOG +++ b/smartmontools/CHANGELOG @@ -43,6 +43,9 @@ NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [CF] smartctl: Ignore normalized attribute value and threshold + if 'raw64' or 'hex24' format is selected. + [CF] knowndrives.cpp updates: - add OCZ-Vertex raw64 attributes - add OCZ-Agility diff --git a/smartmontools/atacmds.cpp b/smartmontools/atacmds.cpp index ff4703dec..ff2e2282a 100644 --- a/smartmontools/atacmds.cpp +++ b/smartmontools/atacmds.cpp @@ -280,15 +280,20 @@ bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs, } ata_attr_raw_format format = format_names[i].format; + // 64-bit formats use the normalized value bytes. + if (format == RAWFMT_RAW64 || format == RAWFMT_HEX64) + flags |= ATTRFLAG_NO_NORMVAL; + if (!id) { // "N,format" -> set format for all entries - for (int j = 0; j < MAX_ATTRIBUTE_NUM; j++) { - if (defs[j].priority >= priority) + for (i = 0; i < MAX_ATTRIBUTE_NUM; i++) { + if (defs[i].priority >= priority) continue; if (attrname[0]) - defs[j].name = attrname; - defs[j].priority = priority; - defs[j].raw_format = format; + defs[i].name = attrname; + defs[i].priority = priority; + defs[i].raw_format = format; + defs[i].flags = flags; } } else if (defs[id].priority <= priority) { @@ -1698,53 +1703,6 @@ int isSupportSelectiveSelfTest(const ata_smart_values * data) return data->offline_data_collection_capability & 0x40; } - - -// Loop over all valid attributes. If they are prefailure attributes -// and are at or below the threshold value, then return the ID of the -// first failing attribute found. Return 0 if all prefailure -// attributes are in bounds. The spec says "Bit 0 -// -Pre-failure/advisory - If the value of this bit equals zero, an -// attribute value less than or equal to its corresponding attribute -// threshold indicates an advisory condition where the usage or age of -// the device has exceeded its intended design life period. If the -// value of this bit equals one, an atribute value less than or equal -// to its corresponding attribute threshold indicates a pre-failure -// condition where imminent loss of data is being predicted." - - -// onlyfailed=0 : are or were any age or prefailure attributes <= threshold -// onlyfailed=1: are any prefailure attributes <= threshold now -int ataCheckSmart(const ata_smart_values * data, - const ata_smart_thresholds_pvt * thresholds, - int onlyfailed) -{ - // loop over all attributes - for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++){ - - // pointers to disk's values and vendor's thresholds - const ata_smart_attribute * disk = data->vendor_attributes+i; - const ata_smart_threshold_entry * thre = thresholds->thres_entries+i; - - // consider only valid attributes - if (disk->id && thre->id){ - int failednow,failedever; - - failednow =disk->current <= thre->threshold; - failedever=disk->worst <= thre->threshold; - - if (!onlyfailed && failedever) - return disk->id; - - if (onlyfailed && failednow && ATTRIBUTE_FLAGS_PREFAILURE(disk->flags)) - return disk->id; - } - } - return 0; -} - - - // This checks the n'th attribute in the attribute list, NOT the // attribute with id==n. If the attribute does not exist, or the // attribute is > threshold, then returns zero. If the attribute is diff --git a/smartmontools/atacmds.h b/smartmontools/atacmds.h index 791c01470..2fea4126c 100644 --- a/smartmontools/atacmds.h +++ b/smartmontools/atacmds.h @@ -656,7 +656,8 @@ enum ata_attr_raw_format // Attribute flags enum { - ATTRFLAG_INCREASING = 0x01 // Value not reset (for reallocated/pending counts) + ATTRFLAG_INCREASING = 0x01, // Value not reset (for reallocated/pending counts) + ATTRFLAG_NO_NORMVAL = 0x02 // Normalized value not valid }; // Vendor attribute display defs for all attribute ids @@ -761,11 +762,6 @@ int ataSmartSupport(const ata_identify_device * drive); // -1: can't tell if SMART is enabled -- try issuing ataDoesSmartWork command to see int ataIsSmartEnabled(const ata_identify_device * drive); -/* Check SMART for Threshold failure */ -// onlyfailed=0 : are or were any age or prefailure attributes <= threshold -// onlyfailed=1: are any prefailure attributes <= threshold now -int ataCheckSmart(const ata_smart_values * data, const ata_smart_thresholds_pvt * thresholds, int onlyfailed); - int ataSmartStatus2(ata_device * device); int isSmartErrorLogCapable(const ata_smart_values * data, const ata_identify_device * identity); diff --git a/smartmontools/ataprint.cpp b/smartmontools/ataprint.cpp index a9511a115..9935206c0 100644 --- a/smartmontools/ataprint.cpp +++ b/smartmontools/ataprint.cpp @@ -773,6 +773,34 @@ static void PrintSmartConveyanceSelfTestPollingTime(const ata_smart_values * dat pout("recommended polling time: \t Not Supported.\n"); } +// Check SMART attribute table for Threshold failure +// onlyfailed=0: are or were any age or prefailure attributes <= threshold +// onlyfailed=1: are any prefailure attributes <= threshold now +static int find_failed_attr(const ata_smart_values * data, + const ata_smart_thresholds_pvt * thresholds, + const ata_vendor_attr_defs & defs, int onlyfailed) +{ + for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { + const ata_smart_attribute * disk = data->vendor_attributes+i; + const ata_smart_threshold_entry * thre = thresholds->thres_entries+i; + + // consider only valid attributes + if (!(disk->id && disk->id == thre->id && thre->threshold + && !(defs[disk->id].flags & ATTRFLAG_NO_NORMVAL) )) + continue; + + bool failednow = (disk->current <= thre->threshold); + bool failedever = (disk->worst <= thre->threshold); + + if (!onlyfailed && failedever) + return disk->id; + + if (onlyfailed && failednow && ATTRIBUTE_FLAGS_PREFAILURE(disk->flags)) + return disk->id; + } + return 0; +} + // onlyfailed=0 : print all attribute values // onlyfailed=1: just ones that are currently failed and have prefailure bit set // onlyfailed=2: ones that are failed, or have failed with or without prefailure bit set @@ -785,22 +813,28 @@ static void PrintSmartAttribWithThres(const ata_smart_values * data, // step through all vendor attributes for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) { - const char *status; const ata_smart_attribute * disk = data->vendor_attributes+i; const ata_smart_threshold_entry * thre = thresholds->thres_entries+i; // consider only valid attributes (allowing some screw-ups in the // thresholds page data to slip by) if (disk->id){ - const char *type, *update; + // Normalized values (current,worth,threshold) valid ? + // (Some SSD disks uses these bytes to store raw value). + bool norm_values_ok = !(defs[disk->id].flags & ATTRFLAG_NO_NORMVAL); // Don't report a failed attribute if its threshold is 0. // ATA-3 (X3T13/2008D Revision 7b) declares 0x00 as the "always passing" // threshold (Later ATA versions declare all thresholds as "obsolete"). // In practice, threshold value 0 is often used for usage attributes or // appears if the thresholds cannot be read. - bool failednow = (thre->threshold > 0 && disk->current <= thre->threshold); - bool failedever = (thre->threshold > 0 && disk->worst <= thre->threshold); + bool failednow, failedever; + if (norm_values_ok && thre->threshold) { + failednow = (disk->current <= thre->threshold); + failedever = (disk->worst <= thre->threshold); + } + else + failednow = failedever = false; // These break out of the loop if we are only printing certain entries... if (onlyfailed==1 && (!ATTRIBUTE_FLAGS_PREFAILURE(disk->flags) || !failednow)) @@ -820,6 +854,7 @@ static void PrintSmartAttribWithThres(const ata_smart_values * data, } // is this Attribute currently failed, or has it ever failed? + const char * status; if (failednow) status="FAILING_NOW"; else if (failedever) @@ -828,22 +863,28 @@ static void PrintSmartAttribWithThres(const ata_smart_values * data, status=" -"; // printing line for each valid attribute - type=ATTRIBUTE_FLAGS_PREFAILURE(disk->flags)?"Pre-fail":"Old_age"; - update=ATTRIBUTE_FLAGS_ONLINE(disk->flags)?"Always":"Offline"; - - pout("%3d %-24s0x%04x %.3d %.3d %.3d %-10s%-9s%-12s%s\n", - disk->id, ata_get_smart_attr_name(disk->id, defs).c_str(), - (int)disk->flags, (int)disk->current, (int)disk->worst, - (int)thre->threshold, type, update, status, - ata_format_attr_raw_value(*disk, defs).c_str()); + std::string attrname = ata_get_smart_attr_name(disk->id, defs); + std::string rawstr = ata_format_attr_raw_value(*disk, defs); + const char * type = ATTRIBUTE_FLAGS_PREFAILURE(disk->flags)?"Pre-fail":"Old_age"; + const char * update = ATTRIBUTE_FLAGS_ONLINE(disk->flags)?"Always":"Offline"; + + if (norm_values_ok) + pout("%3d %-24s0x%04x %.3d %.3d %.3d %-10s%-9s%-12s%s\n", + disk->id, attrname.c_str(), disk->flags, + disk->current, disk->worst, thre->threshold, + type, update, status, rawstr.c_str()); + else + pout("%3d %-24s0x%04x --- --- --- %-10s%-9s%-12s%s\n", + disk->id, attrname.c_str(), disk->flags, + type, update, status, rawstr.c_str()); // Print a warning if there is inconsistency here and // threshold info is not empty. - if (disk->id != thre->id && (thre->id || thre->threshold)) { + if (norm_values_ok && disk->id != thre->id && (thre->id || thre->threshold)) { pout("%3d %-24s<== Data Page | WARNING: PREVIOUS ATTRIBUTE HAS TWO\n", - disk->id, ata_get_smart_attr_name(disk->id, defs).c_str()); + disk->id, attrname.c_str()); pout("%3d %-24s<== Threshold Page | INCONSISTENT IDENTITIES IN THE DATA\n", - thre->id, ata_get_smart_attr_name(thre->id, defs).c_str()); + thre->id, attrname.c_str()); } } } @@ -1948,7 +1989,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) case 0: // The case where the disk health is OK pout("SMART overall-health self-assessment test result: PASSED\n"); - if (ataCheckSmart(&smartval, &smartthres,0)){ + if (find_failed_attr(&smartval, &smartthres, options.attribute_defs, 0)){ if (options.smart_vendor_attrib) pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); else { @@ -1968,7 +2009,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) pout("SMART overall-health self-assessment test result: FAILED!\n" "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); PRINT_OFF(con); - if (ataCheckSmart(&smartval, &smartthres,1)){ + if (find_failed_attr(&smartval, &smartthres, options.attribute_defs, 1)){ returnval|=FAILATTR; if (options.smart_vendor_attrib) pout("See vendor-specific Attribute list for failed Attributes.\n\n"); @@ -1987,7 +2028,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) case -1: default: // The case where something went wrong with HDIO_DRIVE_TASK ioctl() - if (ataCheckSmart(&smartval, &smartthres,1)){ + if (find_failed_attr(&smartval, &smartthres, options.attribute_defs, 1)){ PRINT_ON(con); pout("SMART overall-health self-assessment test result: FAILED!\n" "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); @@ -2004,7 +2045,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } else { pout("SMART overall-health self-assessment test result: PASSED\n"); - if (ataCheckSmart(&smartval, &smartthres,0)){ + if (find_failed_attr(&smartval, &smartthres, options.attribute_defs, 0)){ if (options.smart_vendor_attrib) pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); else { -- GitLab