Use -l xerror,error and -l xselftest,selftest by default.

Implemented parsing of xerror, xselftest sections.
This commit is contained in:
Alexander Shaduri
2017-08-29 13:26:25 +00:00
parent b2b97f2c9a
commit 9ca87eb296
6 changed files with 28 additions and 20 deletions
+1 -4
View File
@@ -23,6 +23,7 @@ TODO:
Don't rely on smartctl return code (2), parse the output instead.
This will allow us to show the Info page.
Need usage cases.
Areca detection
@@ -69,10 +70,6 @@ Testing:
Pre-failure: P, old age: -.
Maybe get rid of Type and Updated columns and print only decoded flags?
use -l xerror,error -l xselftest,selftest by default (the output is similar).
Maybe increase default number of entries (50?).
Change this text: "Note: Usually only the last five errors are stored."
Add a tab for -l devstat - it shows interesting statistics.
Some of this stuff is better than attributes, maybe show them before attributes.
Also needs the warnings and descriptions.
+19 -10
View File
@@ -645,12 +645,14 @@ bool SmartctlParser::parse_section_data(const std::string& body)
} else if (app_pcre_match("/SMART Attributes Data Structure/mi", sub)) {
status = parse_section_data_subsection_attributes(sub) || status;
} else if (app_pcre_match("/SMART Error Log Version/mi", sub)
} else if (app_pcre_match("/SMART Error Log Version/mi", sub) // -l error
|| app_pcre_match("/SMART Extended Comprehensive Error Log Version/mi", sub) // -l xerror
|| app_pcre_match("/Warning: device does not support Error Logging/mi", sub)
|| app_pcre_match("/SMART Error Log not supported/mi", sub)) {
status = parse_section_data_subsection_error_log(sub) || status;
} else if (app_pcre_match("/SMART Self-test log/mi", sub)
} else if (app_pcre_match("/SMART Self-test log/mi", sub) // -l selftest
|| app_pcre_match("/SMART Extended Self-test Log Version/mi", sub) // -l error xselftest
|| app_pcre_match("/Warning: device does not support Self Test Logging/mi", sub)
|| app_pcre_match("/SMART Self-test Log not supported/mi", sub)) {
status = parse_section_data_subsection_selftest_log(sub) || status;
@@ -1350,7 +1352,9 @@ bool SmartctlParser::parse_section_data_subsection_error_log(const std::string&
// Error log version
{
pcrecpp::RE re = app_pcre_re("/^(SMART Error Log Version):[ \\t]*(.*)$/mi");
// SMART Error Log Version: 1
// SMART Extended Comprehensive Error Log Version: 1 (1 sectors)
pcrecpp::RE re = app_pcre_re("/^(SMART (Extended Comprehensive )?Error Log Version): ([0-9]+).*?$/mi");
std::string name, value;
if (re.PartialMatch(sub, &name, &value)) {
@@ -1384,7 +1388,7 @@ bool SmartctlParser::parse_section_data_subsection_error_log(const std::string&
}
}
// Error log enty count
// Error log entry count
{
// note: these represent the same information
pcrecpp::RE re1 = app_pcre_re("/^ATA Error Count:[ \\t]*([0-9]+)/mi");
@@ -1413,14 +1417,17 @@ bool SmartctlParser::parse_section_data_subsection_error_log(const std::string&
// individual errors
{
// split by blocks
pcrecpp::RE re_block = app_pcre_re("/^((Error[ \\t]*([0-9]+))[ \\t]*occurred at disk power-on lifetime:[ \\t]*([0-9]+) hours.*(?:\\n(?: |\\n ).*)*)/mi");
// "Error 1 [0] occurred at disk power-on lifetime: 1 hours (0 days + 1 hours)"
// "Error 25 occurred at disk power-on lifetime: 14799 hours"
pcrecpp::RE re_block = app_pcre_re("/^((Error[ \\t]*([0-9]+))[ \\t]*(?:\\[[0-9]+\\][ \\t])?occurred at disk power-on lifetime:[ \\t]*([0-9]+) hours(?:[^\\n]*)?.*(?:\\n(?: |\\n ).*)*)/mi");
// " When the command that caused the error occurred, the device was active or idle."
// Note: For "in an unknown state" - remove first two words.
pcrecpp::RE re_state = app_pcre_re("/occurred, the device was[ \\t]*(?: in)?(?: an?)?[ \\t]+([^.\\n]*)\\.?/mi");
// " 84 51 2c 71 cd 3f e6 Error: ICRC, ABRT 44 sectors at LBA = 0x063fcd71 = 104844657"
// " 40 51 00 f5 41 61 e0 Error: UNC at LBA = 0x006141f5 = 6373877"
pcrecpp::RE re_type = app_pcre_re("/[ \\t]+Error:[ \\t]*([ ,a-z]+)[ \\t]+((?:[0-9]+|at )[ \\t]*.*)$/mi");
// " 02 -- 51 00 00 00 00 00 00 00 00 00 00 Error: TK0NF"
pcrecpp::RE re_type = app_pcre_re("/[ \\t]+Error:[ \\t]*([ ,a-z0-9]+)(?:[ \\t]+((?:[0-9]+|at )[ \\t]*.*))?$/mi");
std::string block, name, value_num, value_time;
pcrecpp::StringPiece input(sub); // position tracker
@@ -1504,7 +1511,7 @@ bool SmartctlParser::parse_section_data_subsection_selftest_log(const std::strin
// The whole subsection
{
StorageProperty p(pt);
p.set_name("SMART Self-test log", "selftest_log");
p.set_name("SMART Self-Test Log", "selftest_log");
p.reported_value = sub;
p.value_type = StorageProperty::value_type_string;
p.value_string = p.reported_value;
@@ -1529,13 +1536,15 @@ bool SmartctlParser::parse_section_data_subsection_selftest_log(const std::strin
// Self-test log version
{
// newer smartctl (since smartctl 5.1-16)
// SMART Self-test log structure revision number 1
// SMART Extended Self-test Log Version: 1 (1 sectors)
pcrecpp::RE re1 = app_pcre_re("/(SMART Self-test log structure[^\\n0-9]*)([^ \\n]+)[ \\t]*$/mi");
// older smartctl
pcrecpp::RE re1_ex = app_pcre_re("/(SMART Extended Self-test Log Version: ([0-9]+).*$/mi");
// older smartctl (pre 5.1-16)
pcrecpp::RE re2 = app_pcre_re("/(SMART Self-test log, version number[^\\n0-9]*)([^ \\n]+)[ \\t]*$/mi");
std::string name, value;
if (re1.PartialMatch(sub, &name, &value) || re2.PartialMatch(sub, &name, &value)) {
if (re1.PartialMatch(sub, &name, &value) || re1_ex.PartialMatch(sub, &name, &value) || re2.PartialMatch(sub, &name, &value)) {
hz::string_trim(value);
StorageProperty p(pt);
+2 -2
View File
@@ -324,10 +324,10 @@ std::string StorageDevice::fetch_data_and_parse(hz::intrusive_ptr<CmdexSync> sma
if (this->get_type_argument() == "scsi") { // not sure about correctness... FIXME probably fails with RAID/scsi
// This doesn't do much yet, but just in case...
// SCSI equivalent of -a --get=all:
error_msg = execute_device_smartctl("--health --info --get=all --attributes --log=error --log=selftest", smartctl_ex, output);
error_msg = execute_device_smartctl("--health --info --get=all --attributes --log=xerror,50,error --log=xselftest,50,selftest", smartctl_ex, output);
} else {
// ATA equivalent of -a --get=all:
error_msg = execute_device_smartctl("--health --info --get=all --capabilities --attributes --log=error --log=selftest --log=selective",
error_msg = execute_device_smartctl("--health --info --get=all --capabilities --attributes --log=xerror,50,error --log=xselftest,50,selftest --log=selective",
smartctl_ex, output, true); // set type to invalid if needed
}
// See notes above (in fetch_basic_data_and_parse()).
+2 -2
View File
@@ -339,8 +339,8 @@ class StorageProperty {
subsection_health, ///< Overall-health (-H, --health)
subsection_capabilities, ///< General SMART Values, aka Capabilities (-c, --capabilities)
subsection_attributes, ///< Attributes (-A, --attributes). These need decoding.
subsection_error_log, ///< Error Log (-l error)
subsection_selftest_log, ///< Self-test log (-l selftest)
subsection_error_log, ///< Error Log (--log=error)
subsection_selftest_log, ///< Self-test log (--log=selftest)
subsection_selective_selftest_log ///< Selective self-test log and settings
};
+1 -1
View File
@@ -849,7 +849,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
} else if (iter->value_type != StorageProperty::value_type_error_block) {
label_strings.push_back(PropertyLabel(iter->readable_name + ": " + iter->format_value(), &(*iter)));
if (iter->generic_name == "error_count")
label_strings.back().label += " (Note: Usually only the last five errors are stored.)";
label_strings.back().label += " (Note: The number of entries may be limited to the newest ones)";
} else {
std::string type_details = iter->value_error_block.type_more_info;
+3 -1
View File
@@ -197,6 +197,7 @@
<object class="GtkBox" id="attributes_label_vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">3</property>
<child>
<placeholder/>
@@ -380,6 +381,7 @@
<object class="GtkBox" id="error_log_label_vbox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">3</property>
<child>
<placeholder/>
@@ -938,8 +940,8 @@ Selective self-test log is also presented here.</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Re-read all the information</property>
<property name="use_stock">True</property>
<accelerator key="R" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="F5" signal="clicked"/>
<accelerator key="R" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
</object>
<packing>
<property name="expand">True</property>