From d8f4c591d6cec4b9ff4be0d914f58dca8eef5d70 Mon Sep 17 00:00:00 2001
From: ballen4705 <ballen4705@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Fri, 22 Nov 2002 13:30:56 +0000
Subject: [PATCH] smartd: added smartd.conf Directives -T and -s.  The -T
 Directive enables/disables Automatic Offline Testing.  The -s Directive
 enables/disables Attribute Autosave. Documentation and example configuration
 file updated to agree.

Some revision of documentation to clarify the different between offline
testing and self-testing.


git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@310 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/CHANGELOG     |  7 +++++-
 sm5/TODO          |  6 +----
 sm5/atacmds.c     | 22 +++++++++++++---
 sm5/atacmds.cpp   | 22 +++++++++++++---
 sm5/smartctl.8    | 64 ++++++++++++++++++++++++++++++++++-------------
 sm5/smartd.8      | 40 +++++++++++++++++++++++------
 sm5/smartd.c      | 53 ++++++++++++++++++++++++++++++++++-----
 sm5/smartd.conf   |  2 ++
 sm5/smartd.conf.5 | 40 +++++++++++++++++++++++------
 sm5/smartd.cpp    | 53 ++++++++++++++++++++++++++++++++++-----
 sm5/smartd.h      |  6 ++++-
 11 files changed, 256 insertions(+), 59 deletions(-)

diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index da3b8fe80..31e72c48d 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.53 2002/11/21 17:45:59 ballen4705 Exp $
+$Id: CHANGELOG,v 1.54 2002/11/22 13:30:54 ballen4705 Exp $
 
 Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
@@ -25,6 +25,11 @@ NOTES FOR FUTURE RELEASES: see TODO file.
 
 CURRENT RELEASE (see VERSION file in this directory):
 
+  Allen: smartd: added smartd.conf Directives -T and -s.  The -T Directive
+  enables/disables Automatic Offline Testing.  The -s Directive
+  enables/disables Attribute Autosave. Documentation and
+  example configuration file updated to agree.
+
   Allen: smartd: user can make smartd check the disks at any time
   (ie, interrupt sleep) by sending signal SIGUSR1 to smartd.  This
   can be done for example with:
diff --git a/sm5/TODO b/sm5/TODO
index 3979c30fc..538a9dc17 100644
--- a/sm5/TODO
+++ b/sm5/TODO
@@ -4,7 +4,7 @@ Home page of code is: http://smartmontools.sourceforge.net
 
 Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
-$Id: TODO,v 1.25 2002/11/21 18:14:29 knan Exp $
+$Id: TODO,v 1.26 2002/11/22 13:30:55 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
@@ -57,10 +57,6 @@ exists? If something doesn't exit then don't try to open it?  This
 should probably be the default option if there is no configuration
 file.
 
-Add following config file directives:
-  -f                    enable autosave of attributes
-  -o                    enable automatic offline testing
-
 Use daemon (3) function instead of do-it-yourself daemon_init().  But,
 does it close all open file descriptors?  Must read glibc code to see:
 documentation unclear. [Some discussion indicates that this is
diff --git a/sm5/atacmds.c b/sm5/atacmds.c
index 76f5770a3..f71be7009 100644
--- a/sm5/atacmds.c
+++ b/sm5/atacmds.c
@@ -29,7 +29,7 @@
 #include <stdlib.h>
 #include "atacmds.h"
 
-const char *CVSid1="$Id: atacmds.c,v 1.40 2002/11/14 05:42:49 ballen4705 Exp $" CVSID1;
+const char *CVSid1="$Id: atacmds.c,v 1.41 2002/11/22 13:30:55 ballen4705 Exp $" CVSID1;
 
 // These Drive Identity tables are taken from hdparm 5.2, and are also
 // given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
@@ -448,7 +448,16 @@ int ataDisableAutoSave(int device){
   return 0;
 }
 
-// Note that in the ATA-5 standard this command is marked "OBSOLETE"
+// Note that in the ATA-5 standard the Enable/Disable AutoOffline
+// command is marked "OBSOLETE".  Curiously, I could not find it
+// documented in ANY of the ATA specifications.  In other words, it's
+// been obsolete forever. However some vendors (eg, IBM) seem to be
+// using this command anyway.  For example see the IBM Travelstar
+// 40GNX hard disk drive specifications page 164 Revision 1.1 22 Apr
+// 2002.  This gives a detailed description of the command, although
+// the drive claims to comply with the ATA/ATAPI-5 Revision 3
+// standard!  The latter document makes no mention of this command at
+// all, other than to say that it is "obsolete".
 int ataEnableAutoOffline (int device ){	
   
   /* timer hard coded to 4 hours */
@@ -461,7 +470,8 @@ int ataEnableAutoOffline (int device ){
   return 0;
 }
 
-// Another Obsolete Command!
+// Another Obsolete Command.  See comments directly above, associated
+// with the corresponding Enable command.
 int ataDisableAutoOffline (int device ){	
   unsigned char parms[4] = {WIN_SMART, 0, SMART_AUTO_OFFLINE, 0};
   
@@ -618,6 +628,12 @@ int isSmartErrorLogCapable ( struct ata_smart_values *data){
 int isSupportExecuteOfflineImmediate ( struct ata_smart_values *data){
    return data->offline_data_collection_capability & 0x01;
 }
+
+// Note in the ATA-5 standard, the following bit is listed as "Vendor
+// Specific".  So it may not be reliable. The only use of this that I
+// have found is in IBM drives, where it is well-documented.  See for
+// example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX
+// hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.
 int isSupportAutomaticTimer ( struct ata_smart_values *data){
    return data->offline_data_collection_capability & 0x02;
 }
diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp
index d4e178f41..e154a9b45 100644
--- a/sm5/atacmds.cpp
+++ b/sm5/atacmds.cpp
@@ -29,7 +29,7 @@
 #include <stdlib.h>
 #include "atacmds.h"
 
-const char *CVSid1="$Id: atacmds.cpp,v 1.40 2002/11/14 05:42:49 ballen4705 Exp $" CVSID1;
+const char *CVSid1="$Id: atacmds.cpp,v 1.41 2002/11/22 13:30:55 ballen4705 Exp $" CVSID1;
 
 // These Drive Identity tables are taken from hdparm 5.2, and are also
 // given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
@@ -448,7 +448,16 @@ int ataDisableAutoSave(int device){
   return 0;
 }
 
-// Note that in the ATA-5 standard this command is marked "OBSOLETE"
+// Note that in the ATA-5 standard the Enable/Disable AutoOffline
+// command is marked "OBSOLETE".  Curiously, I could not find it
+// documented in ANY of the ATA specifications.  In other words, it's
+// been obsolete forever. However some vendors (eg, IBM) seem to be
+// using this command anyway.  For example see the IBM Travelstar
+// 40GNX hard disk drive specifications page 164 Revision 1.1 22 Apr
+// 2002.  This gives a detailed description of the command, although
+// the drive claims to comply with the ATA/ATAPI-5 Revision 3
+// standard!  The latter document makes no mention of this command at
+// all, other than to say that it is "obsolete".
 int ataEnableAutoOffline (int device ){	
   
   /* timer hard coded to 4 hours */
@@ -461,7 +470,8 @@ int ataEnableAutoOffline (int device ){
   return 0;
 }
 
-// Another Obsolete Command!
+// Another Obsolete Command.  See comments directly above, associated
+// with the corresponding Enable command.
 int ataDisableAutoOffline (int device ){	
   unsigned char parms[4] = {WIN_SMART, 0, SMART_AUTO_OFFLINE, 0};
   
@@ -618,6 +628,12 @@ int isSmartErrorLogCapable ( struct ata_smart_values *data){
 int isSupportExecuteOfflineImmediate ( struct ata_smart_values *data){
    return data->offline_data_collection_capability & 0x01;
 }
+
+// Note in the ATA-5 standard, the following bit is listed as "Vendor
+// Specific".  So it may not be reliable. The only use of this that I
+// have found is in IBM drives, where it is well-documented.  See for
+// example page 170, section 13.32.1.18 of the IBM Travelstar 40GNX
+// hard disk drive specifications page 164 Revision 1.1 22 Apr 2002.
 int isSupportAutomaticTimer ( struct ata_smart_values *data){
    return data->offline_data_collection_capability & 0x02;
 }
diff --git a/sm5/smartctl.8 b/sm5/smartctl.8
index 56550862a..8361fd0cd 100644
--- a/sm5/smartctl.8
+++ b/sm5/smartctl.8
@@ -1,6 +1,6 @@
 \# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 \#
-\# $Id: smartctl.8,v 1.25 2002/11/07 21:51:34 ballen4705 Exp $
+\# $Id: smartctl.8,v 1.26 2002/11/22 13:30:55 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
@@ -16,7 +16,7 @@
 \# Research Center), Jack Baskin School of Engineering, University of
 \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/
 \#
-.TH SMARTCTL 8  "$Date: 2002/11/07 21:51:34 $" "smartmontools-5.0"
+.TH SMARTCTL 8  "$Date: 2002/11/22 13:30:55 $" "smartmontools-5.0"
 .SH NAME
 smartctl \- S.M.A.R.T. control and monitor utility 
 .SH SYNOPSIS
@@ -184,32 +184,60 @@ S.M.A.R.T. functionality. [I can't imagine why you would want to do
 this. Or do you cover up the oil-pressure warning light on your car?]
 .TP
 .B t
-Test: Enables S.M.A.R.T. automatic offline test timer which scans the drive
+Test: Enables S.M.A.R.T. automatic offline test which scans the drive
 every four hours for disk defects. This command can be given during normal
 system operation.
 
-S.M.A.R.T. provides three basic classes of testing.  The so-called 'online'
-testing has no effect on the performance of the device.  It
-is turned on by the '\-e' option. The offline testing, enabled by
-this '\-t' option, can, in principle, degrade the device performance.  Normally,
-the disk will suspend any offline testing while disk accesses are
-taking place, then automatically resume them when the disk would
-otherwise be idle, so in practice it has little effect.  The third
-class of testing is the 'self' testing; see below.
+Note that the S.M.A.R.T. automatic offline test command is listed as 'Obsolete'
+in every version of the ATA and ATA/ATAPI Specifications
+that I can find.  However it is implemented and used by some
+vendors. [Good documentation can be found in IBM's Official
+Published Disk Specifications.  For example the IBM Travelstar 40GNX
+Hard Disk Drive Specifications (Revision 1.1, 22 April 2002,
+Publication # 1541, Document S07N-7715-02) page 164.]
+
+S.M.A.R.T. provides three basic categories of testing.  The first
+category, called 'online' testing, has no effect on the performance of
+the device.  It is turned on by the '\-e' option.
+
+The second category of testing is called 'offline' testing. This type
+of test can, in principle, degrade the device performance.  The '\-t'
+option causes this offline testing to be carried out, automatically,
+on a regular scheduled basis.  Normally, the disk will suspend any
+offline testing while disk accesses are taking place, then
+automatically resume them when the disk would otherwise be idle, so in
+practice it has little effect.  Note that a one-time offline test can
+also be carried out immediately upon receipt of a user command.  See
+the '\-O' option below, which causes a one-time offline test to be
+carried out.
+
+Any errors detected in automatic or immediate offline testing will be
+shown in the S.M.A.R.T. error log, and will be reflected in the values
+of the S.M.A.R.T. attributes.  These are visible with the '\-l' and '\-v' options.
+
+The third class of testing is the 'self' testing.  This third type of
+test is only performed (immediately) when a command to run it is
+issued.  The '\-S', '\-s', '\-X', '\-x', and '\-A' options below can
+be used to carry out such self-tests; please see below for further
+details.
+
+Any errors detected in the self testign will be shown in the
+S.M.A.R.T. self-test log, which can be examined using the '\-L'
+option.
 
-Any errors detected in the automatic offline testing will be shown in
-the S.M.A.R.T. error log, and will be reflected in the values of the
-S.M.A.R.T. attributes.  These are visible with the '\-l' and '\-v'
-options.
 .TP
 .B T 
 unTest: Disables S.M.A.R.T. automatic offline test timer. 
 .TP
 .B f
-File: Enables S.M.A.R.T. autosave of device vendor-specific attributes.
+File: Enables S.M.A.R.T. autosave of device vendor-specific
+attributes. Note that this feature is preserved across disk power
+cycles, so you should only need to issue it once.
 .TP
 .B F
-unFile: Disables S.M.A.R.T. autosave of device vendor-specific attributes.
+unFile: Disables S.M.A.R.T. autosave of device vendor-specific
+attributes.  Note that this feature is preserved across disk power
+cycles, so you should only need to issue it once.
 .TP
 .B S.M.A.R.T. READ AND DISPLAY DATA OPTIONS:
 .TP
@@ -528,4 +556,4 @@ Please let us know if there is an on\-line source for this document.
 
 .SH
 CVS ID OF THIS PAGE:
-$Id: smartctl.8,v 1.25 2002/11/07 21:51:34 ballen4705 Exp $
+$Id: smartctl.8,v 1.26 2002/11/22 13:30:55 ballen4705 Exp $
diff --git a/sm5/smartd.8 b/sm5/smartd.8
index 3844052c8..76b24abd0 100644
--- a/sm5/smartd.8
+++ b/sm5/smartd.8
@@ -1,6 +1,6 @@
 \# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 \# 
-\# $Id: smartd.8,v 1.35 2002/11/22 09:32:52 ballen4705 Exp $
+\# $Id: smartd.8,v 1.36 2002/11/22 13:30:55 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
@@ -16,7 +16,7 @@
 \# Research Center), Jack Baskin School of Engineering, University of
 \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/
 \#
-.TH SMARTD 8  "$Date: 2002/11/22 09:32:52 $" "smartmontools-5.0"
+.TH SMARTD 8  "$Date: 2002/11/22 13:30:55 $" "smartmontools-5.0"
 .SH NAME
 smartd \- S.M.A.R.T. Daemon
 .SH SYNOPSIS
@@ -288,12 +288,14 @@ ATA: The device is an ATA device.  Don't try issuing SCSI commands to it.
 SCSI: The device is a SCSI device.  Don't try issuing IDE/ATA
 commands to it.  
 
-In the absence of either of these Directives,
+In the absence of either of these previous two Directives,
 .B smartd
-will attempt to guess the device type by looking at whether the fifth
-character in the device name is an 's' or an 'h'.  If it can't guess
-from this fifth character, then it will simply try to access the
-device using first ATA and then SCSI ioctl()s.
+will first attempt to guess the device type by looking at whether the sixth
+character in the device name is an 's' or an 'h'.  This will work for
+device names like /dev/hda or /dev/sdb.  If
+.B smartd
+can't guess from this sixth character, then it will simply try to
+access the device using first ATA and then SCSI ioctl()s.
 .TP
 .B \-C <N>
 This sets the time in between disk checks to be 
@@ -330,6 +332,28 @@ were incorporated into the ATA/ATAPI Specifications.  [Please see the
 .B smartctl \-P
 command-line option.]
 .TP
+.B \-T <N>
+Testing: This Directive takes a decimal integer argument <N> which can
+have value 0 or 1.  If <N>=1 this Directive enables Automatic Offline
+Testing.  The delay between tests is vendor-specific but is typically
+four hours. If <N>=0 this Directive disables Automatic Offline Testing.
+[Please see the
+.B smartctl \-t
+and
+.B \-T
+command-line options.]
+.TP
+.B \-s <N>
+Save:
+This Directive takes a decimal integer argument <N> which can
+have value 0 or 1.  If <N>=1 this Directive enables Attribute Autosave.
+If <N>=0 this Directive disables Attribute Autosave.
+[Please see the
+.B smartctl \-f
+and
+.B \-F
+command-line options.]
+.TP
 .B \-c
 Check: Will check the SMART status of the disk.  If any Prefailure
 Attributes are less than or equal to their threshold values, then disk
@@ -625,4 +649,4 @@ Please let us know if there is an on\-line source for this document.
 
 .SH
 CVS ID OF THIS PAGE:
-$Id: smartd.8,v 1.35 2002/11/22 09:32:52 ballen4705 Exp $
+$Id: smartd.8,v 1.36 2002/11/22 13:30:55 ballen4705 Exp $
diff --git a/sm5/smartd.c b/sm5/smartd.c
index 89d684695..c36f6f373 100644
--- a/sm5/smartd.c
+++ b/sm5/smartd.c
@@ -46,7 +46,7 @@
 
 // CVS ID strings
 extern const char *CVSid1, *CVSid2;
-const char *CVSid6="$Id: smartd.c,v 1.70 2002/11/22 09:35:31 ballen4705 Exp $" 
+const char *CVSid6="$Id: smartd.c,v 1.71 2002/11/22 13:30:55 ballen4705 Exp $" 
 CVSID1 CVSID2 CVSID3 CVSID4 CVSID7;
 
 // global variable used for control of printing, passing arguments, etc.
@@ -296,6 +296,8 @@ void Directives() {
   printout(LOG_INFO,"  -S     Device is a SCSI device\n");
   printout(LOG_INFO,"  -C N   Check disks once every N seconds, where N>=10.\n");
   printout(LOG_INFO,"  -P     Permissive, ignore apparent lack of SMART.\n");
+  printout(LOG_INFO,"  -T N   Automatic offline tests. N=0: Disable, 1: Enable.\n");
+  printout(LOG_INFO,"  -s N   Attribute Autosave. N=0: Disable, 1: Enable.\n");
   printout(LOG_INFO,"  -c     Monitor SMART Health Status, report if failed\n");
   printout(LOG_INFO,"  -l     Monitor SMART Error Log, report new errors\n");
   printout(LOG_INFO,"  -L     Monitor SMART Self-Test Log, report new errors\n");
@@ -397,7 +399,6 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
   printout(LOG_INFO,"Device: %s, opened\n", device);
   
   // Get drive identity structure
-  // May want to add options to enable autosave, automatic online testing
   if (ataReadHDIdentity (fd,&drive)){
     // Unable to read Identity structure
     printout(LOG_INFO,"Device: %s, unable to read Device Identity Structure\n",device);
@@ -411,14 +412,30 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
     close(fd);
     return 2; 
   }
-
- if (ataEnableSmart(fd)){
+  
+  if (ataEnableSmart(fd)){
     // Enable SMART command has failed
     printout(LOG_INFO,"Device: %s, could not enable SMART capability\n",device);
     close(fd);
     return 2; 
   }
   
+  // disable device attribute autosave...
+  if (cfg->autosave==1){
+    if (ataDisableAutoSave(fd))
+      printout(LOG_INFO,"Device: %s, could not disable SMART Attribute Autosave.\n",device);
+    else
+      printout(LOG_INFO,"Device: %s, disabled SMART Attribute Autosave.\n",device);
+  }
+
+  // or enable device attribute autosave
+  if (cfg->autosave==2){
+    if (ataEnableAutoSave(fd))
+      printout(LOG_INFO,"Device: %s, could not enable SMART Attribute Autosave.\n",device);
+    else
+      printout(LOG_INFO,"Device: %s, enabled SMART Attribute Autosave.\n",device);
+  }
+
   // capability check: SMART status
   if (cfg->smartcheck && ataSmartStatus2(fd)==-1){
     printout(LOG_INFO,"Device: %s, not capable of SMART Health Status check\n",device);
@@ -426,7 +443,7 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
   }
   
   // capability check: Read smart values and thresholds
-  if (cfg->usagefailed || cfg->prefail || cfg->usage) {
+  if (cfg->usagefailed || cfg->prefail || cfg->usage || cfg->autoofflinetest) {
     devices->smartval=(struct ata_smart_values *)calloc(1,sizeof(struct ata_smart_values));
     devices->smartthres=(struct ata_smart_thresholds *)calloc(1,sizeof(struct ata_smart_thresholds));
     
@@ -447,7 +464,23 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
       cfg->usagefailed=cfg->prefail=cfg->usage=0;
     }
   }
-  
+
+  // disable automatic on-line testing
+  if (cfg->autoofflinetest==1){
+    if (devices->smartval && isSupportAutomaticTimer(devices->smartval) && !ataDisableAutoOffline(fd))
+      printout(LOG_INFO,"Device: %s, disabled SMART Automatic Offline Testing .\n",device);
+    else
+      printout(LOG_INFO,"Device: %s, could not disable SMART Automatic Offline Testing.\n",device);
+  }
+
+  // enable automatic on-line testing
+  if (cfg->autoofflinetest==2){
+    if (devices->smartval && isSupportAutomaticTimer(devices->smartval) && !ataDisableAutoOffline(fd))
+      printout(LOG_INFO,"Device: %s, enabled SMART Automatic Offline Testing.\n",device);
+    else
+      printout(LOG_INFO,"Device: %s, could not enable SMART Automatic Offline Testing.\n",device);
+  }
+
   // capability check: self-test-log
   if (cfg->selftest){
     int val=selftesterrorcount(fd, device);
@@ -973,6 +1006,14 @@ int parsetoken(char *token,cfgfile *cfg){
     cfg->selftest=1;
     cfg->errorlog=1;
     break;
+  case 'T':
+    // Automatic offline testing on/off.  Note "1+" below!
+    cfg->autoofflinetest=1+inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 0, 1);
+    break;
+  case 's':
+    // Attribute autosave on/off.  Note "1+" below!
+    cfg->autosave=1+inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 0, 1);
+    break;
   case 'm':
     // email warning option
     cfg->emailopt=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, -3, 3);
diff --git a/sm5/smartd.conf b/sm5/smartd.conf
index 42ccb5270..10bfe8df0 100644
--- a/sm5/smartd.conf
+++ b/sm5/smartd.conf
@@ -36,6 +36,8 @@ monitor.
 #   -S      Device is a SCSI device
 #   -C N    Check disks every N seconds.  N must be 10 or greater
 #   -P      Ignore lack of SMART (for disks before ATA-3 Rev 4)
+#   -T N    Automatic Offline Testing.  N=1: enable, N=0: disable
+#   -s N    Attribute Autosave.  N=1: enable, N=0: disable
 #   -c      Monitor SMART Health Status
 #   -l      Monitor SMART Error Log for changes
 #   -L      Monitor SMART Self-Test Log for new errors
diff --git a/sm5/smartd.conf.5 b/sm5/smartd.conf.5
index ed16eed31..d27619479 100644
--- a/sm5/smartd.conf.5
+++ b/sm5/smartd.conf.5
@@ -1,6 +1,6 @@
 \# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 \# 
-\# $Id: smartd.conf.5,v 1.11 2002/11/22 09:32:52 ballen4705 Exp $
+\# $Id: smartd.conf.5,v 1.12 2002/11/22 13:30:55 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
@@ -16,7 +16,7 @@
 \# Research Center), Jack Baskin School of Engineering, University of
 \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/
 \#
-.TH SMARTD.CONF 5  "$Date: 2002/11/22 09:32:52 $" "smartmontools-5.0"
+.TH SMARTD.CONF 5  "$Date: 2002/11/22 13:30:55 $" "smartmontools-5.0"
 .SH NAME
 smartd.conf \- S.M.A.R.T. Monitoring Daemon Configuration File
 
@@ -173,12 +173,14 @@ ATA: The device is an ATA device.  Don't try issuing SCSI commands to it.
 SCSI: The device is a SCSI device.  Don't try issuing IDE/ATA
 commands to it.  
 
-In the absence of either of these Directives,
+In the absence of either of these previous two Directives,
 .B smartd
-will attempt to guess the device type by looking at whether the fifth
-character in the device name is an 's' or an 'h'.  If it can't guess
-from this fifth character, then it will simply try to access the
-device using first ATA and then SCSI ioctl()s.
+will first attempt to guess the device type by looking at whether the sixth
+character in the device name is an 's' or an 'h'.  This will work for
+device names like /dev/hda or /dev/sdb.  If
+.B smartd
+can't guess from this sixth character, then it will simply try to
+access the device using first ATA and then SCSI ioctl()s.
 .TP
 .B \-C <N>
 This sets the time in between disk checks to be 
@@ -215,6 +217,28 @@ were incorporated into the ATA/ATAPI Specifications.  [Please see the
 .B smartctl \-P
 command-line option.]
 .TP
+.B \-T <N>
+Testing: This Directive takes a decimal integer argument <N> which can
+have value 0 or 1.  If <N>=1 this Directive enables Automatic Offline
+Testing.  The delay between tests is vendor-specific but is typically
+four hours. If <N>=0 this Directive disables Automatic Offline Testing.
+[Please see the
+.B smartctl \-t
+and
+.B \-T
+command-line options.]
+.TP
+.B \-s <N>
+Save:
+This Directive takes a decimal integer argument <N> which can
+have value 0 or 1.  If <N>=1 this Directive enables Attribute Autosave.
+If <N>=0 this Directive disables Attribute Autosave.
+[Please see the
+.B smartctl \-f
+and
+.B \-F
+command-line options.]
+.TP
 .B \-c
 Check: Will check the SMART status of the disk.  If any Prefailure
 Attributes are less than or equal to their threshold values, then disk
@@ -440,4 +464,4 @@ SEE ALSO:
 
 .SH
 CVS ID OF THIS PAGE:
-$Id: smartd.conf.5,v 1.11 2002/11/22 09:32:52 ballen4705 Exp $
+$Id: smartd.conf.5,v 1.12 2002/11/22 13:30:55 ballen4705 Exp $
diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp
index 96eb42b19..835ed5768 100644
--- a/sm5/smartd.cpp
+++ b/sm5/smartd.cpp
@@ -46,7 +46,7 @@
 
 // CVS ID strings
 extern const char *CVSid1, *CVSid2;
-const char *CVSid6="$Id: smartd.cpp,v 1.70 2002/11/22 09:35:31 ballen4705 Exp $" 
+const char *CVSid6="$Id: smartd.cpp,v 1.71 2002/11/22 13:30:55 ballen4705 Exp $" 
 CVSID1 CVSID2 CVSID3 CVSID4 CVSID7;
 
 // global variable used for control of printing, passing arguments, etc.
@@ -296,6 +296,8 @@ void Directives() {
   printout(LOG_INFO,"  -S     Device is a SCSI device\n");
   printout(LOG_INFO,"  -C N   Check disks once every N seconds, where N>=10.\n");
   printout(LOG_INFO,"  -P     Permissive, ignore apparent lack of SMART.\n");
+  printout(LOG_INFO,"  -T N   Automatic offline tests. N=0: Disable, 1: Enable.\n");
+  printout(LOG_INFO,"  -s N   Attribute Autosave. N=0: Disable, 1: Enable.\n");
   printout(LOG_INFO,"  -c     Monitor SMART Health Status, report if failed\n");
   printout(LOG_INFO,"  -l     Monitor SMART Error Log, report new errors\n");
   printout(LOG_INFO,"  -L     Monitor SMART Self-Test Log, report new errors\n");
@@ -397,7 +399,6 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
   printout(LOG_INFO,"Device: %s, opened\n", device);
   
   // Get drive identity structure
-  // May want to add options to enable autosave, automatic online testing
   if (ataReadHDIdentity (fd,&drive)){
     // Unable to read Identity structure
     printout(LOG_INFO,"Device: %s, unable to read Device Identity Structure\n",device);
@@ -411,14 +412,30 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
     close(fd);
     return 2; 
   }
-
- if (ataEnableSmart(fd)){
+  
+  if (ataEnableSmart(fd)){
     // Enable SMART command has failed
     printout(LOG_INFO,"Device: %s, could not enable SMART capability\n",device);
     close(fd);
     return 2; 
   }
   
+  // disable device attribute autosave...
+  if (cfg->autosave==1){
+    if (ataDisableAutoSave(fd))
+      printout(LOG_INFO,"Device: %s, could not disable SMART Attribute Autosave.\n",device);
+    else
+      printout(LOG_INFO,"Device: %s, disabled SMART Attribute Autosave.\n",device);
+  }
+
+  // or enable device attribute autosave
+  if (cfg->autosave==2){
+    if (ataEnableAutoSave(fd))
+      printout(LOG_INFO,"Device: %s, could not enable SMART Attribute Autosave.\n",device);
+    else
+      printout(LOG_INFO,"Device: %s, enabled SMART Attribute Autosave.\n",device);
+  }
+
   // capability check: SMART status
   if (cfg->smartcheck && ataSmartStatus2(fd)==-1){
     printout(LOG_INFO,"Device: %s, not capable of SMART Health Status check\n",device);
@@ -426,7 +443,7 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
   }
   
   // capability check: Read smart values and thresholds
-  if (cfg->usagefailed || cfg->prefail || cfg->usage) {
+  if (cfg->usagefailed || cfg->prefail || cfg->usage || cfg->autoofflinetest) {
     devices->smartval=(struct ata_smart_values *)calloc(1,sizeof(struct ata_smart_values));
     devices->smartthres=(struct ata_smart_thresholds *)calloc(1,sizeof(struct ata_smart_thresholds));
     
@@ -447,7 +464,23 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){
       cfg->usagefailed=cfg->prefail=cfg->usage=0;
     }
   }
-  
+
+  // disable automatic on-line testing
+  if (cfg->autoofflinetest==1){
+    if (devices->smartval && isSupportAutomaticTimer(devices->smartval) && !ataDisableAutoOffline(fd))
+      printout(LOG_INFO,"Device: %s, disabled SMART Automatic Offline Testing .\n",device);
+    else
+      printout(LOG_INFO,"Device: %s, could not disable SMART Automatic Offline Testing.\n",device);
+  }
+
+  // enable automatic on-line testing
+  if (cfg->autoofflinetest==2){
+    if (devices->smartval && isSupportAutomaticTimer(devices->smartval) && !ataDisableAutoOffline(fd))
+      printout(LOG_INFO,"Device: %s, enabled SMART Automatic Offline Testing.\n",device);
+    else
+      printout(LOG_INFO,"Device: %s, could not enable SMART Automatic Offline Testing.\n",device);
+  }
+
   // capability check: self-test-log
   if (cfg->selftest){
     int val=selftesterrorcount(fd, device);
@@ -973,6 +1006,14 @@ int parsetoken(char *token,cfgfile *cfg){
     cfg->selftest=1;
     cfg->errorlog=1;
     break;
+  case 'T':
+    // Automatic offline testing on/off.  Note "1+" below!
+    cfg->autoofflinetest=1+inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 0, 1);
+    break;
+  case 's':
+    // Attribute autosave on/off.  Note "1+" below!
+    cfg->autosave=1+inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, 0, 1);
+    break;
   case 'm':
     // email warning option
     cfg->emailopt=inttoken(arg=strtok(NULL,delim), name, token, lineno, CONFIGFILE, -3, 3);
diff --git a/sm5/smartd.h b/sm5/smartd.h
index 3e70ab141..895da5594 100644
--- a/sm5/smartd.h
+++ b/sm5/smartd.h
@@ -23,7 +23,7 @@
  */
 
 #ifndef CVSID7
-#define CVSID7 "$Id: smartd.h,v 1.22 2002/11/21 14:11:20 ballen4705 Exp $\n"
+#define CVSID7 "$Id: smartd.h,v 1.23 2002/11/22 13:30:56 ballen4705 Exp $\n"
 #endif
 
 // Configuration file
@@ -87,6 +87,10 @@ typedef struct configfile_s {
   char errorlog;
   // Should we ignore missing capabilities/SMART errors
   char permissive;
+  // Disable (1) or Enable (2) device attribute autosave
+  char autosave;
+  // Disable (1) or Enable (2) autmatic offline testing
+  char autoofflinetest;
   // mailing information for four of the previous error types plus mailtest
   mailinfo maildata[5];
   char emailopt;
-- 
GitLab