From 7287b406427df952684258e471d8e9b7cd7c286f Mon Sep 17 00:00:00 2001
From: ballen4705 <ballen4705@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Fri, 2 Apr 2004 05:57:40 +0000
Subject: [PATCH] Better format for Selective self-test log; improved man page
 for smartctl

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@1633 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/ataprint.c    | 103 ++++++++++++++++++++++++++++++----------------
 sm5/ataprint.cpp  | 103 ++++++++++++++++++++++++++++++----------------
 sm5/smartctl.8.in |  90 +++++++++++++++++++++-------------------
 3 files changed, 181 insertions(+), 115 deletions(-)

diff --git a/sm5/ataprint.c b/sm5/ataprint.c
index 5fefddbe8..4ba9dba67 100644
--- a/sm5/ataprint.c
+++ b/sm5/ataprint.c
@@ -35,7 +35,7 @@
 #include "knowndrives.h"
 #include "config.h"
 
-const char *ataprint_c_cvsid="$Id: ataprint.c,v 1.148 2004/03/29 00:26:03 ballen4705 Exp $"
+const char *ataprint_c_cvsid="$Id: ataprint.c,v 1.149 2004/04/02 05:57:40 ballen4705 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
@@ -486,44 +486,44 @@ void ataPrintDriveInfo (struct ata_identify_device *drive){
 }
 
 
-/*  prints verbose value Off-line data collection status byte */
-void PrintSmartOfflineStatus(struct ata_smart_values *data){
-  char *message=NULL;
-
-  // the final 7 bits
-  unsigned char stat=data->offline_data_collection_status & 0x7f;
+const char *OfflineDataCollectionStatus(unsigned char status_byte){
+  unsigned char stat=status_byte & 0x7f;
   
-  pout("Offline data collection status:  (0x%02x)\t",
-       (int)data->offline_data_collection_status);
-    
   switch(stat){
   case 0x00:
-    message="never started";
-    break;
+    return "was never started";
   case 0x02:
-    message="completed without error";
-    break;
+    return "was completed without error";
+  case 0x03:
+    if (status_byte == 0x03)
+      return "is in progress";
+    else
+      return "is in a Reserved state";
   case 0x04:
-    message="suspended by an interrupting command from host";
-    break;
+    return "was suspended by an interrupting command from host";
   case 0x05:
-    message="aborted by an interrupting command from host";
-    break;
+    return "was aborted by an interrupting command from host";
   case 0x06:
-    message="aborted by the device with a fatal error";
-    break;
+    return "was aborted by the device with a fatal error";
   default:
     if (stat >= 0x40)
-      pout("Vendor Specific.\n");
+      return "is in a Vendor Specific state\n";
     else
-      pout("Reserved.\n");
+      return "is in a Reserved state\n";
   }
+}
+  
+  
+  /*  prints verbose value Off-line data collection status byte */
+  void PrintSmartOfflineStatus(struct ata_smart_values *data){
   
-  if (message)
-    // Off-line data collection status byte is not a reserved
-    // or vendor specific value
-    pout("Offline data collection activity was\n"
-         "\t\t\t\t\t%s.\n", message);
+  pout("Offline data collection status:  (0x%02x)\t",
+       (int)data->offline_data_collection_status);
+    
+  // Off-line data collection status byte is not a reserved
+  // or vendor specific value
+  pout("Offline data collection activity\n"
+       "\t\t\t\t\t%s.\n", OfflineDataCollectionStatus(data->offline_data_collection_status));
   
   // Report on Automatic Data Collection Status.  Only IBM documents
   // this bit.  See SFF 8035i Revision 2 for details.
@@ -1018,8 +1018,10 @@ int ataPrintSmartErrorlog(struct ata_smart_errorlog *data){
 }
 
 void ataPrintSelectiveSelfTestLog(struct ata_selective_self_test_log *log, struct ata_smart_values *sv) {
-  int i;
+  int i,field1,field2;
   char *msg;
+  char tmp[64];
+  uint64_t maxl=0,maxr=0;
   uint64_t current=log->currentlba;
   uint64_t currentend=current+65535;
 
@@ -1053,23 +1055,52 @@ void ataPrintSelectiveSelfTestLog(struct ata_selective_self_test_log *log, struc
     break;
   }
 
-  // print the five test spans
-  pout("Span         STARTING_LBA           ENDING_LBA   CURRENT_TEST_STATUS\n");
+  // find the number of columns needed for printing
+  for (i=0; i<5; i++) {
+    uint64_t start=log->span[i].start;
+    uint64_t end  =log->span[i].end; 
+
+    if (start>maxl)
+      maxl=start;
+    if (end > maxr)
+      maxr=end;
+  }
+  if (current>maxl)
+    maxl=current;
+  if (currentend>maxr)
+    maxr=currentend;
+  
+  // we need at least 7 characters wide fields to accomodate the
+  // labels
+  if ((field1=snprintf(tmp,64, "%"PRIu64, maxl))<7)
+    field1=7;
+  if ((field2=snprintf(tmp,64, "%"PRIu64, maxr))<7)
+    field2=7;
+
+  // now print the five test spans
+  pout(" SPAN  %*s  %*s  CURRENT_TEST_STATUS\n", field1, "MIN_LBA", field2, "MAX_LBA");
+
   for (i=0; i<5; i++) {
     uint64_t start=log->span[i].start;
     uint64_t end=log->span[i].end;
     
     if ((i+1)==(int)log->currentspan)
       // this span is currently under test
-      pout("   %d %20"PRIu64" %20"PRIu64"   %s (%"PRIu64"-%"PRIu64")\n",
-	   i+1, start, end, msg, current, currentend);
+      pout("    %d  %*"PRIu64"  %*"PRIu64"  %s [%01d0%% left] (%"PRIu64"-%"PRIu64")\n",
+	   i+1, field1, start, field2, end, msg,
+	   (int)(sv->self_test_exec_status & 0x7), current, currentend);
     else
       // this span is not currently under test
-      pout("   %d %20"PRIu64" %20"PRIu64"   Not_testing\n", i+1, start, end);
+      pout("    %d  %*"PRIu64"  %*"PRIu64"  Not_testing\n",
+	   i+1, field1, start, field2, end);
   }  
   
-  if ((log->flags & SELECTIVE_FLAG_DOSCAN) && (log->flags & SELECTIVE_FLAG_ACTIVE) && log->currentspan>5)
-    pout("%4d %20"PRIu64" %20"PRIu64"   Read_scanning\n", (int)log->currentspan, current, currentend);
+  // if we are currently read-scanning, print LBAs and the status of
+  // the read scan
+  if (log->currentspan>5)
+    pout("%5d  %*"PRIu64"  %*"PRIu64"  Read_scanning %s\n",
+	 (int)log->currentspan, field1, current, field2, currentend,
+	 OfflineDataCollectionStatus(sv->offline_data_collection_status));
   
   /* Print selective self-test flags.  Possible flag combinations are
      (numbering bits from 0-15):
@@ -1094,7 +1125,7 @@ void ataPrintSelectiveSelfTestLog(struct ata_selective_self_test_log *log, struc
   }
   else
     pout("  After scanning selected spans, do NOT read-scan remainder of disk.\n");
-
+  
   // print pending time
   pout("If Selective self-test is pending on power-up, resume after %d minute delay.\n",
        (int)log->pendingtime);
diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp
index 656237010..09a4d440a 100644
--- a/sm5/ataprint.cpp
+++ b/sm5/ataprint.cpp
@@ -35,7 +35,7 @@
 #include "knowndrives.h"
 #include "config.h"
 
-const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.148 2004/03/29 00:26:03 ballen4705 Exp $"
+const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.149 2004/04/02 05:57:40 ballen4705 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
@@ -486,44 +486,44 @@ void ataPrintDriveInfo (struct ata_identify_device *drive){
 }
 
 
-/*  prints verbose value Off-line data collection status byte */
-void PrintSmartOfflineStatus(struct ata_smart_values *data){
-  char *message=NULL;
-
-  // the final 7 bits
-  unsigned char stat=data->offline_data_collection_status & 0x7f;
+const char *OfflineDataCollectionStatus(unsigned char status_byte){
+  unsigned char stat=status_byte & 0x7f;
   
-  pout("Offline data collection status:  (0x%02x)\t",
-       (int)data->offline_data_collection_status);
-    
   switch(stat){
   case 0x00:
-    message="never started";
-    break;
+    return "was never started";
   case 0x02:
-    message="completed without error";
-    break;
+    return "was completed without error";
+  case 0x03:
+    if (status_byte == 0x03)
+      return "is in progress";
+    else
+      return "is in a Reserved state";
   case 0x04:
-    message="suspended by an interrupting command from host";
-    break;
+    return "was suspended by an interrupting command from host";
   case 0x05:
-    message="aborted by an interrupting command from host";
-    break;
+    return "was aborted by an interrupting command from host";
   case 0x06:
-    message="aborted by the device with a fatal error";
-    break;
+    return "was aborted by the device with a fatal error";
   default:
     if (stat >= 0x40)
-      pout("Vendor Specific.\n");
+      return "is in a Vendor Specific state\n";
     else
-      pout("Reserved.\n");
+      return "is in a Reserved state\n";
   }
+}
+  
+  
+  /*  prints verbose value Off-line data collection status byte */
+  void PrintSmartOfflineStatus(struct ata_smart_values *data){
   
-  if (message)
-    // Off-line data collection status byte is not a reserved
-    // or vendor specific value
-    pout("Offline data collection activity was\n"
-         "\t\t\t\t\t%s.\n", message);
+  pout("Offline data collection status:  (0x%02x)\t",
+       (int)data->offline_data_collection_status);
+    
+  // Off-line data collection status byte is not a reserved
+  // or vendor specific value
+  pout("Offline data collection activity\n"
+       "\t\t\t\t\t%s.\n", OfflineDataCollectionStatus(data->offline_data_collection_status));
   
   // Report on Automatic Data Collection Status.  Only IBM documents
   // this bit.  See SFF 8035i Revision 2 for details.
@@ -1018,8 +1018,10 @@ int ataPrintSmartErrorlog(struct ata_smart_errorlog *data){
 }
 
 void ataPrintSelectiveSelfTestLog(struct ata_selective_self_test_log *log, struct ata_smart_values *sv) {
-  int i;
+  int i,field1,field2;
   char *msg;
+  char tmp[64];
+  uint64_t maxl=0,maxr=0;
   uint64_t current=log->currentlba;
   uint64_t currentend=current+65535;
 
@@ -1053,23 +1055,52 @@ void ataPrintSelectiveSelfTestLog(struct ata_selective_self_test_log *log, struc
     break;
   }
 
-  // print the five test spans
-  pout("Span         STARTING_LBA           ENDING_LBA   CURRENT_TEST_STATUS\n");
+  // find the number of columns needed for printing
+  for (i=0; i<5; i++) {
+    uint64_t start=log->span[i].start;
+    uint64_t end  =log->span[i].end; 
+
+    if (start>maxl)
+      maxl=start;
+    if (end > maxr)
+      maxr=end;
+  }
+  if (current>maxl)
+    maxl=current;
+  if (currentend>maxr)
+    maxr=currentend;
+  
+  // we need at least 7 characters wide fields to accomodate the
+  // labels
+  if ((field1=snprintf(tmp,64, "%"PRIu64, maxl))<7)
+    field1=7;
+  if ((field2=snprintf(tmp,64, "%"PRIu64, maxr))<7)
+    field2=7;
+
+  // now print the five test spans
+  pout(" SPAN  %*s  %*s  CURRENT_TEST_STATUS\n", field1, "MIN_LBA", field2, "MAX_LBA");
+
   for (i=0; i<5; i++) {
     uint64_t start=log->span[i].start;
     uint64_t end=log->span[i].end;
     
     if ((i+1)==(int)log->currentspan)
       // this span is currently under test
-      pout("   %d %20"PRIu64" %20"PRIu64"   %s (%"PRIu64"-%"PRIu64")\n",
-	   i+1, start, end, msg, current, currentend);
+      pout("    %d  %*"PRIu64"  %*"PRIu64"  %s [%01d0%% left] (%"PRIu64"-%"PRIu64")\n",
+	   i+1, field1, start, field2, end, msg,
+	   (int)(sv->self_test_exec_status & 0x7), current, currentend);
     else
       // this span is not currently under test
-      pout("   %d %20"PRIu64" %20"PRIu64"   Not_testing\n", i+1, start, end);
+      pout("    %d  %*"PRIu64"  %*"PRIu64"  Not_testing\n",
+	   i+1, field1, start, field2, end);
   }  
   
-  if ((log->flags & SELECTIVE_FLAG_DOSCAN) && (log->flags & SELECTIVE_FLAG_ACTIVE) && log->currentspan>5)
-    pout("%4d %20"PRIu64" %20"PRIu64"   Read_scanning\n", (int)log->currentspan, current, currentend);
+  // if we are currently read-scanning, print LBAs and the status of
+  // the read scan
+  if (log->currentspan>5)
+    pout("%5d  %*"PRIu64"  %*"PRIu64"  Read_scanning %s\n",
+	 (int)log->currentspan, field1, current, field2, currentend,
+	 OfflineDataCollectionStatus(sv->offline_data_collection_status));
   
   /* Print selective self-test flags.  Possible flag combinations are
      (numbering bits from 0-15):
@@ -1094,7 +1125,7 @@ void ataPrintSelectiveSelfTestLog(struct ata_selective_self_test_log *log, struc
   }
   else
     pout("  After scanning selected spans, do NOT read-scan remainder of disk.\n");
-
+  
   // print pending time
   pout("If Selective self-test is pending on power-up, resume after %d minute delay.\n",
        (int)log->pendingtime);
diff --git a/sm5/smartctl.8.in b/sm5/smartctl.8.in
index 76a2624db..5ee7f350b 100644
--- a/sm5/smartctl.8.in
+++ b/sm5/smartctl.8.in
@@ -1,7 +1,7 @@
 .ig
  Copyright (C) 2002-4 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
- $Id: smartctl.8.in,v 1.40 2004/03/25 15:39:25 ballen4705 Exp $
+ $Id: smartctl.8.in,v 1.41 2004/04/02 05:57:40 ballen4705 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
@@ -517,54 +517,55 @@ some common types of errors, the Error Register (ER) and Status
 Register (SR) values are decoded and printed as text. The meanings of these
 are:
 .nf
-   \fBABRT\fP:  Aborted
-   \fBAMNF\fP:  Address Mark Not Found
-   \fBCCTO\fP:  Command Completion Timed Out
-   \fBEOM\fP:   End Of Media
-   \fBICRC\fP:  Interface CRC error
-   \fBIDNF\fP:  Id Not Found
+   \fBABRT\fP:  Command \fBAB\fPo\fBRT\fPed
+   \fBAMNF\fP:  \fBA\fPddress \fBM\fPark \fBN\fPot \fBF\fPound
+   \fBCCTO\fP:  \fBC\fPommand \fBC\fPompletion \fBT\fPimed \fBO\fPut
+   \fBEOM\fP:   \fBE\fPnd \fBO\fPf \fBM\fPedia
+   \fBICRC\fP:  \fBI\fPnterface \fBC\fPyclic \fBR\fPedundancy \fBC\fPode (CRC) error
+   \fBIDNF\fP:  \fBID\fPentity \fBN\fPot \fBF\fPound
    \fBILI\fP:   (packet command-set specific)
-   \fBMC\fP:    Media Changed
-   \fBMCR\fP:   Media Change Request
-   \fBNM\fP:    No Media
-   \fBobs\fP:   Obsolete
-   \fBTK0NF\fP: Track 0 Not Found
-   \fBUNC\fP:   Uncorrectable
-   \fBWP\fP:    Write Protected
+   \fBMC\fP:    \fBM\fPedia \fBC\fPhanged
+   \fBMCR\fP:   \fBM\fPedia \fBC\fPhange \fBR\fPequest
+   \fBNM\fP:    \fBN\fPo \fBM\fPedia
+   \fBobs\fP:   \fBobs\fPolete
+   \fBTK0NF\fP: \fBT\fPrac\fBK 0 N\fPot \fBF\fPound
+   \fBUNC\fP:   \fBUNC\fPorrectable Error in Data
+   \fBWP\fP:    Media is \fBW\fPrite \fBP\fProtected
 .fi
 In addition, up to the last five commands that preceded the error are
-listed, along with a timestamp measured in seconds from the start of
-the corresponding power cycle.  [Note: this time stamp wraps after
-2^32 milliseconds, or 49 days 17 hours 2 minutes and 47.296 seconds.]
-The key ATA disk registers are also recorded in the log.  The final
-column of the error log is a text-string description of the ATA
-command defined by the Command Register (CR) and Feature Register (FR)
-values.  Commands that are obsolete in the most current (ATA-7) spec
-are listed like this: \fBREAD LONG (w/ retry) [OBS-4]\fP, indicating
-that the command became obsolete with or in the ATA-4 specification.
-Similarly, the notation \fB[RET-\fP\fIN\fP\fB]\fP is used to indicate
-that a command was retired in the ATA-\fIN\fP specification.  Some 
-commands are not defined in any version of the ATA specification but
-are in common use nonetheless; these are marked \fB[NS]\fP, meaning
-non-standard.
-
-
-The ATA Specification (ATA-5 Revision 1c, Section 8.41.6.8.2 to be
-precise) says:
-\fB"Error log structures shall include UNC errors, IDNF
-errors for which the address requested was valid, servo errors, write
-fault errors, etc.  Error log data structures shall not include errors
+listed, along with a timestamp measured from the start of the
+corresponding power cycle. This is displayed in the form
+Dd+HH:MM:SS.msec where D is the number of days, HH is hours, MM is
+minutes, SS is seconds and msec is milliseconds.  [Note: this time
+stamp wraps after 2^32 milliseconds, or 49 days 17 hours 2 minutes and
+47.296 seconds.]  The key ATA disk registers are also recorded in the
+log.  The final column of the error log is a text-string description
+of the ATA command defined by the Command Register (CR) and Feature
+Register (FR) values.  Commands that are obsolete in the most current
+(ATA-7) spec are listed like this: \fBREAD LONG (w/ retry) [OBS-4]\fP,
+indicating that the command became obsolete with or in the ATA-4
+specification.  Similarly, the notation \fB[RET-\fP\fIN\fP\fB]\fP is
+used to indicate that a command was retired in the ATA-\fIN\fP
+specification.  Some commands are not defined in any version of the
+ATA specification but are in common use nonetheless; these are marked
+\fB[NS]\fP, meaning non-standard.
+
+The ATA Specification (ATA-5 Revision 1c, Section 8.41.6.8.2) says:
+\fB"Error log structures shall include UNC errors, IDNF errors for
+which the address requested was valid, servo errors, write fault
+errors, etc.  Error log data structures shall not include errors
 attributed to the receipt of faulty commands such as command codes not
 implemented by the device or requests with invalid parameters or
-invalid addresses."\fP
-The definitions of these terms are:
-.fi
-\fBUNC\fP (\fBUNC\fPorrectable): data is uncorrectable.
-.fi
-
+invalid addresses."\fP The definitions of these terms are:
+.br
+\fBUNC\fP (\fBUNC\fPorrectable): data is uncorrectable.  This refers
+to data which as been read from the disk, but for which the Error
+Checking and Correction (ECC) codes are inconsistent.  In effect, this
+means that the data can not be read.
+.br
 \fBIDNF\fP (\fBID N\fPot \fBF\fPound): user-accessible address could
 not be found. For READ LOG type commands, \fBIDNF\fP can also indicate
-that a device data log structure checksum was incorrect.  
+that a device data log structure checksum was incorrect.
 
 If the command that caused the error was a READ or WRITE command, then
 the Logical Block Address (LBA) at which the error occured will be
@@ -1131,4 +1132,7 @@ these documents may be found in the References section of the
 
 .SH
 CVS ID OF THIS PAGE:
-$Id: smartctl.8.in,v 1.40 2004/03/25 15:39:25 ballen4705 Exp $
+$Id: smartctl.8.in,v 1.41 2004/04/02 05:57:40 ballen4705 Exp $
+.\" Local Variables:	         
+.\" mode: nroff         
+.\" End:
-- 
GitLab