From 5ce5706cc7bd40af14ec978e3cc406bb59f5739a Mon Sep 17 00:00:00 2001 From: chrfranke <chrfranke@4ea69e1a-61f1-4043-bf83-b5c94c648137> Date: Sun, 5 Jul 2009 17:16:44 +0000 Subject: [PATCH] smartctl: Add '-l xerror,error' and '-l xselftest,selftest'. git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@2819 4ea69e1a-61f1-4043-bf83-b5c94c648137 --- sm5/CHANGELOG | 5 ++++- sm5/ataprint.cpp | 36 +++++++++++++++++++++++++++++------- sm5/ataprint.h | 4 +++- sm5/smartctl.8.in | 18 ++++++++++++++---- sm5/smartctl.cpp | 40 +++++++++++++++++++++++++++++----------- 5 files changed, 79 insertions(+), 24 deletions(-) diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 3659535c0..6f71441d7 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.815 2009/07/04 23:24:37 manfred99 Exp $ +$Id: CHANGELOG,v 1.816 2009/07/05 17:16:38 chrfranke Exp $ The most recent version of this file is: http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup @@ -41,6 +41,9 @@ NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [CF] smartctl: Add '-l xerror,error' and '-l xselftest,selftest' to print + the old logs if the extended logs are not supported. + [MS] knowndrives.cpp updates: - Western Digital AV-GP series - Transcend Solid-State Drive and Transcend Solid-State Drive V series diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp index d2e0a0e9a..12363f375 100644 --- a/sm5/ataprint.cpp +++ b/sm5/ataprint.cpp @@ -44,7 +44,7 @@ #include "utility.h" #include "knowndrives.h" -const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.212 2009/06/20 17:58:33 chrfranke Exp $" +const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.213 2009/07/05 17:16:38 chrfranke Exp $" ATACMDNAMES_H_CVSID ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // for passing global control variables @@ -2151,10 +2151,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // Print SMART Extendend Comprehensive Error Log + bool do_smart_error_log = options.smart_error_log; if (options.smart_ext_error_log) { + bool ok = false; unsigned nsectors = GetNumLogSectors(gplogdir, 0x03, true); if (!nsectors) - pout("SMART Extended Comprehensive Error Log (GP Log 0x03) does not exist\n"); + pout("SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n"); else if (nsectors >= 256) pout("SMART Extended Comprehensive Error Log size %u not supported\n", nsectors); else { @@ -2162,13 +2164,22 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) ata_smart_exterrlog * log_03 = (ata_smart_exterrlog *)log_03_buf.data(); if (!ataReadExtErrorLog(device, log_03, nsectors)) failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - else + else { PrintSmartExtErrorLog(log_03, nsectors, options.smart_ext_error_log); + ok = true; + } + } + + if (!ok) { + if (options.retry_error_log) + do_smart_error_log = true; + else if (!do_smart_error_log) + pout("Try '-l [xerror,]error' to read traditional SMART Error Log\n"); } } // Print SMART error log - if (options.smart_error_log) { + if (do_smart_error_log) { if (!isSmartErrorLogCapable(&smartval, &drive)){ pout("Warning: device does not support Error Logging\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); @@ -2186,10 +2197,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // Print SMART Extendend Self-test Log + bool do_smart_selftest_log = options.smart_selftest_log; if (options.smart_ext_selftest_log) { + bool ok = false; unsigned nsectors = GetNumLogSectors(gplogdir, 0x07, true); if (!nsectors) - pout("SMART Extended Self-test Log (GP Log 0x07) does not exist\n"); + pout("SMART Extended Self-test Log (GP Log 0x07) not supported\n"); else if (nsectors >= 256) pout("SMART Extended Self-test Log size %u not supported\n", nsectors); else { @@ -2197,13 +2210,22 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) ata_smart_extselftestlog * log_07 = (ata_smart_extselftestlog *)log_07_buf.data(); if (!ataReadExtSelfTestLog(device, log_07, nsectors)) failuretest(OPTIONAL_CMD, returnval|=FAILSMART); - else + else { PrintSmartExtSelfTestLog(log_07, nsectors, options.smart_ext_selftest_log); + ok = true; + } + } + + if (!ok) { + if (options.retry_selftest_log) + do_smart_selftest_log = true; + else if (!do_smart_selftest_log) + pout("Try '-l [xselftest,]selftest' to read traditional SMART Self Test Log\n"); } } // Print SMART self-test log - if (options.smart_selftest_log) { + if (do_smart_selftest_log) { if (!isSmartTestLogCapable(&smartval, &drive)){ pout("Warning: device does not support Self Test Logging\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); diff --git a/sm5/ataprint.h b/sm5/ataprint.h index d672fadfe..404cb398f 100644 --- a/sm5/ataprint.h +++ b/sm5/ataprint.h @@ -26,7 +26,7 @@ #ifndef ATAPRINT_H_ #define ATAPRINT_H_ -#define ATAPRINT_H_CVSID "$Id: ataprint.h,v 1.41 2009/06/20 17:58:33 chrfranke Exp $\n" +#define ATAPRINT_H_CVSID "$Id: ataprint.h,v 1.42 2009/07/05 17:16:38 chrfranke Exp $\n" #include <vector> @@ -58,6 +58,7 @@ struct ata_print_options bool gp_logdir, smart_logdir; unsigned smart_ext_error_log; unsigned smart_ext_selftest_log; + bool retry_error_log, retry_selftest_log; std::vector<ata_log_request> log_requests; @@ -99,6 +100,7 @@ struct ata_print_options gp_logdir(false), smart_logdir(false), smart_ext_error_log(0), smart_ext_selftest_log(0), + retry_error_log(false), retry_selftest_log(false), sct_temp_sts(false), sct_temp_hist(false), sataphy(false), sataphy_reset(false), smart_disable(false), smart_enable(false), diff --git a/sm5/smartctl.8.in b/sm5/smartctl.8.in index 3c2f74088..984f8b31e 100644 --- a/sm5/smartctl.8.in +++ b/sm5/smartctl.8.in @@ -1,7 +1,7 @@ .ig Copyright (C) 2002-9 Bruce Allen <smartmontools-support@lists.sourceforge.net> - $Id: smartctl.8.in,v 1.131 2009/06/29 19:56:19 chrfranke Exp $ + $Id: smartctl.8.in,v 1.132 2009/07/05 17:16:38 chrfranke Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -833,7 +833,7 @@ receives a command which is not implemented or is not valid. \- [SCSI] prints the error counter log pages for reads, write and verifies. The verify row is only output if it has an element other than zero. -.I xerror[,NUM] +.I xerror[,NUM][,error] \- [ATA only] [NEW EXPERIMENTAL SMARTCTL FEATURE] prints the Extended Comprehensive SMART error log (General Purpose Log address 0x03). Unlike the Summary SMART error log (see \'\-l error\' above), @@ -846,6 +846,13 @@ are 2 (Samsung), 5 (Seagate) or 6 (WD). If the optional parameter NUM is specified, only the NUM most recent log entries are printed. Otherwise, all entries are printed. +If ',error' is appended and the Extended Comprehensive SMART error +log is not supported, the Summary SMART self-test log is printed. + +Please note that some recent (e.g. Samsung) drives report errors only +in the Comprehensive SMART error log. The Summary SMART error log can +be read but is always empty. + .I selftest \- [ATA] prints the SMART self\-test log. The disk maintains a self\-test log showing the results of the self tests, which can be run using the @@ -882,7 +889,7 @@ Additional Sense Code Qualifier (ASQ) are also printed. The self tests can be run using the \'\-t\' option described below (using the ATA test terminology). -.I xselftest[,NUM] +.I xselftest[,NUM][,selftest] \- [ATA only] [NEW EXPERIMENTAL SMARTCTL FEATURE] prints the Extended SMART self\-test log (General Purpose Log address 0x07). Unlike the SMART self\-test log (see \'\-l selftest\' above), it supports 48-bit LBA @@ -893,6 +900,9 @@ values are 1 (Seagate) or 2 (Samsung). If the optional parameter NUM is specified, only the NUM most recent log entries are printed. Otherwise, all entries are printed. +If ',selftest' is appended and the Extended SMART self-test log is not +supported, the old SMART self-test log is printed. + .I selective \- [ATA only] Please see the \'\-t select\' option below for a description of selective self\-tests. The selective self\-test log @@ -1743,7 +1753,7 @@ these documents may be found in the References section of the .SH CVS ID OF THIS PAGE: -$Id: smartctl.8.in,v 1.131 2009/06/29 19:56:19 chrfranke Exp $ +$Id: smartctl.8.in,v 1.132 2009/07/05 17:16:38 chrfranke Exp $ .\" Local Variables: .\" mode: nroff .\" End: diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp index 0d40dec20..62952c057 100644 --- a/sm5/smartctl.cpp +++ b/sm5/smartctl.cpp @@ -63,7 +63,7 @@ extern const char *os_solaris_ata_s_cvsid; extern const char *cciss_c_cvsid; #endif extern const char *atacmdnames_c_cvsid, *atacmds_c_cvsid, *ataprint_c_cvsid, *knowndrives_c_cvsid, *os_XXXX_c_cvsid, *scsicmds_c_cvsid, *scsiprint_c_cvsid, *utility_c_cvsid; -const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.200 2009/06/21 02:39:32 dpgilbert Exp $" +const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.201 2009/07/05 17:16:44 chrfranke Exp $" ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // This is a block containing all the "control variables". We declare @@ -168,9 +168,9 @@ void Usage (void){ " -l TYPE, --log=TYPE\n" " Show device log. TYPE: error, selftest, selective, directory[,g|s],\n" " background, sasphy[,reset], sataphy[,reset],\n" -" scttemp[sts,hist],gplog,N[,RANGE],\n" -" smartlog,N[,RANGE],\n" -" xerror[,N], xselftest[,N]\n\n" +" scttemp[sts,hist],\n" +" gplog,N[,RANGE], smartlog,N[,RANGE],\n" +" xerror[,N][,error], xselftest[,N][,selftest]\n\n" " -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n" " Set display OPTION for vendor Attribute N (see man page)\n\n" " -F TYPE, --firmwarebug=TYPE (ATA)\n" @@ -226,7 +226,7 @@ static const char *getvalidarglist(char opt) case 'l': return "error, selftest, selective, directory[,g|s], background, scttemp[sts|hist], " "sasphy[,reset], sataphy[,reset], gplog,N[,RANGE], smartlog,N[,RANGE], " - "xerror[,N], xselftest[,N]"; + "xerror[,N][,error], xselftest[,N][,selftest]"; case 'P': return "use, ignore, show, showall"; case 't': @@ -483,17 +483,35 @@ const char * parse_options(int argc, char** argv, } else if (!strcmp(optarg,"scttemphist")) { ataopts.sct_temp_hist = true; - } else if ( !strncmp(optarg,"xerror" , sizeof("xerror" )-1) - || !strncmp(optarg,"xselftest", sizeof("xselftest")-1)) { + } else if (!strncmp(optarg, "xerror", sizeof("xerror")-1)) { int n1 = -1, n2 = -1, len = strlen(optarg); unsigned val = ~0U; - sscanf(optarg, "%*[a-z]%n,%u%n", &n1, &val, &n2); - if (!((n1 == len || n2 == len) && val > 0)) - badarg = true; - else if (optarg[1] == 'e') + sscanf(optarg, "xerror%n,error%n", &n1, &n2); + if (!(n1 == len || n2 == len)) { + n1 = n2 = -1; + sscanf(optarg, "xerror,%u%n,error%n", &val, &n1, &n2); + } + if ((n1 == len || n2 == len) && val > 0) { ataopts.smart_ext_error_log = val; + ataopts.retry_error_log = (n2 == len); + } else + badarg = true; + + } else if (!strncmp(optarg, "xselftest", sizeof("xselftest")-1)) { + int n1 = -1, n2 = -1, len = strlen(optarg); + unsigned val = ~0U; + sscanf(optarg, "xselftest%n,selftest%n", &n1, &n2); + if (!(n1 == len || n2 == len)) { + n1 = n2 = -1; + sscanf(optarg, "xselftest,%u%n,selftest%n", &val, &n1, &n2); + } + if ((n1 == len || n2 == len) && val > 0) { ataopts.smart_ext_selftest_log = val; + ataopts.retry_selftest_log = (n2 == len); + } + else + badarg = true; } else if ( !strncmp(optarg, "gplog," , sizeof("gplog," )-1) || !strncmp(optarg, "smartlog,", sizeof("smartlog,")-1)) { -- GitLab