diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 578fdd93c71e60ae8cdca61cfab145f02bd38654..ae0c680ad9882b3850851b121069274e20364834 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.31 2002/10/30 06:02:37 ballen4705 Exp $ +$Id: CHANGELOG,v 1.32 2002/10/30 10:18:37 ballen4705 Exp $ Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> @@ -23,9 +23,40 @@ California, Santa Cruz. http://ssrc.soe.ucsc.edu/ NOTES FOR FUTURE RELEASES: see TODO file. +Added +.B \-C <N> +This sets the time in between disk checks to be +.B <N> +seconds apart. Note that although you can give this Directive +multiple times on different lines of the configuration file, only the +final value that is given has an effect, and applies to all the disks. +The default value of +.B <N> +is 1800 sec, and the minimum allowed value is +ten seconds. CURRENT RELEASE (see VERSION file in this directory): +smartmontools-5.0.24 + + Added new Directive for Configuration file: +-C <N> This sets the time in between disk checks to be <N> + seconds apart. Note that although you can give + this Directive multiple times on different lines of + the configuration file, only the final value that + is given has an effect, and applies to all the + disks. The default value of <N> is 1800 sec, and + the minimum allowed value is ten seconds. + + Problem wasn't the print format. F.L.W. Meunier <0@pervalidus.net> + sent me a gcc 3.2 build and I ran it under a debugger. The + problem seems to be with passing the very large (2x512+4) byte + data structures as arguments. I never liked this anyway; it was + inherited from smartsuite. So I've changed all the heavyweight + functions (ATA ones, anyone) to just passing pointers, not hideous + kB size structures on the stack. Hopefully this will now build OK + under gcc 3.2 with any sensible compilation options. + smartmontools-5.0.23 Because of reported problems with GCC 3.2 compile, I have gone diff --git a/sm5/TODO b/sm5/TODO index 162c8ece26a4325e8aa6fd6e5b866bbbc3a74783..23c17e8aebaa25fa5edfaa9fac8457123e9b8702 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.18 2002/10/29 14:19:10 ballen4705 Exp $ +$Id: TODO,v 1.19 2002/10/30 10:18:37 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 @@ -67,6 +67,3 @@ General Fixes ------------- Fix lots of syntax like if (a != 0) - -Pass pointer to big structures like "device" and smartval, not the -whole 2kB of data! I've started doing this but haven't finished yet. diff --git a/sm5/VERSION b/sm5/VERSION index 409940768f2a684935a7d15a29f96e82c487f439..a45fd52cc5891570d6299fab38643103c3955474 100644 --- a/sm5/VERSION +++ b/sm5/VERSION @@ -1 +1 @@ -23 +24 diff --git a/sm5/atacmds.c b/sm5/atacmds.c index b78c270cb0af7fa75337f1518a075c3f523a5b16..f1a3bf671268efd62722069b0981ba90a7f81b15 100644 --- a/sm5/atacmds.c +++ b/sm5/atacmds.c @@ -30,7 +30,7 @@ #include <stdlib.h> #include "atacmds.h" -const char *CVSid1="$Id: atacmds.c,v 1.35 2002/10/30 06:02:38 ballen4705 Exp $" CVSID1; +const char *CVSid1="$Id: atacmds.c,v 1.36 2002/10/30 10:18:37 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 @@ -199,17 +199,17 @@ int ataReadHDIdentity (int device, struct hd_driveid *buf){ // describing which revision. Note that Revision 0 of ATA-3 does NOT // support SMART. For this one case we return -3 rather than +3 as // the version number. See notes above. -int ataVersionInfo (const char** description, struct hd_driveid drive, unsigned short *minor){ +int ataVersionInfo (const char** description, struct hd_driveid *drive, unsigned short *minor){ unsigned short major; int i; // get major and minor ATA revision numbers #ifdef __NEW_HD_DRIVE_ID - major=drive.major_rev_num; - *minor=drive.minor_rev_num; + major=drive->major_rev_num; + *minor=drive->minor_rev_num; #else - major=drive.word80; - *minor=drive.word81; + major=drive->word80; + *minor=drive->word81; #endif // First check if device has ANY ATA version information in it @@ -242,16 +242,16 @@ int ataVersionInfo (const char** description, struct hd_driveid drive, unsigned } // returns 1 if SMART supported, 0 if not supported or can't tell -int ataSmartSupport(struct hd_driveid drive){ +int ataSmartSupport(struct hd_driveid *drive){ unsigned short word82,word83; // get correct bits of IDENTIFY DEVICE structure #ifdef __NEW_HD_DRIVE_ID - word82=drive.command_set_1; - word83=drive.command_set_2; + word82=drive->command_set_1; + word83=drive->command_set_2; #else - word82=drive.command_sets; - word83=drive.word83; + word82=drive->command_sets; + word83=drive->word83; #endif // Note this does not work for ATA3 < Revision 6, when word82 and word83 were added @@ -260,16 +260,16 @@ int ataSmartSupport(struct hd_driveid drive){ } // returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell -int ataIsSmartEnabled(struct hd_driveid drive){ +int ataIsSmartEnabled(struct hd_driveid *drive){ unsigned short word85,word87; // Get correct bits of IDENTIFY DRIVE structure #ifdef __NEW_HD_DRIVE_ID - word85=drive.cfs_enable_1; - word87=drive.csf_default; + word85=drive->cfs_enable_1; + word87=drive->csf_default; #else - word85=drive.word85; - word87=drive.word87; + word85=drive->word85; + word87=drive->word87; #endif if ((word87 & 0x0001<<14) && !(word87 & 0x0001<<15)) @@ -583,39 +583,39 @@ int ataSmartTest(int device, int testtype){ } /* Test Time Functions */ -int TestTime(struct ata_smart_values data,int testtype){ +int TestTime(struct ata_smart_values *data,int testtype){ switch (testtype){ case OFFLINE_FULL_SCAN: - return (int) data.total_time_to_complete_off_line; + return (int) data->total_time_to_complete_off_line; case SHORT_SELF_TEST: case SHORT_CAPTIVE_SELF_TEST: - return (int) data.short_test_completion_time; + return (int) data->short_test_completion_time; case EXTEND_SELF_TEST: case EXTEND_CAPTIVE_SELF_TEST: - return (int) data.extend_test_completion_time; + return (int) data->extend_test_completion_time; default: return 0; } } -int isSmartErrorLogCapable ( struct ata_smart_values data){ - return data.errorlog_capability & 0x01; +int isSmartErrorLogCapable ( struct ata_smart_values *data){ + return data->errorlog_capability & 0x01; } -int isSupportExecuteOfflineImmediate ( struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x01; +int isSupportExecuteOfflineImmediate ( struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x01; } -int isSupportAutomaticTimer ( struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x02; +int isSupportAutomaticTimer ( struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x02; } -int isSupportOfflineAbort ( struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x04; +int isSupportOfflineAbort ( struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x04; } -int isSupportOfflineSurfaceScan ( struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x08; +int isSupportOfflineSurfaceScan ( struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x08; } -int isSupportSelfTest (struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x10; +int isSupportSelfTest (struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x10; } @@ -634,8 +634,8 @@ int isSupportSelfTest (struct ata_smart_values data){ // onlyfailed=0 : are or were any age or prefailure attributes <= threshold // onlyfailed=1: are any prefailure attributes <= threshold now -int ataCheckSmart(struct ata_smart_values data, - struct ata_smart_thresholds thresholds, +int ataCheckSmart(struct ata_smart_values *data, + struct ata_smart_thresholds *thresholds, int onlyfailed){ int i; @@ -643,8 +643,8 @@ int ataCheckSmart(struct ata_smart_values data, for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ // pointers to disk's values and vendor's thresholds - struct ata_smart_attribute *disk=data.vendor_attributes+i; - struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i; + struct ata_smart_attribute *disk=data->vendor_attributes+i; + struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i; // consider only valid attributes if (disk->id && thre->id){ diff --git a/sm5/atacmds.cpp b/sm5/atacmds.cpp index 21a84b46fc100f39937e91ffd380f1a43eec307d..acf7c86e714dffa070dd4518bd093ddd2a200f26 100644 --- a/sm5/atacmds.cpp +++ b/sm5/atacmds.cpp @@ -30,7 +30,7 @@ #include <stdlib.h> #include "atacmds.h" -const char *CVSid1="$Id: atacmds.cpp,v 1.35 2002/10/30 06:02:38 ballen4705 Exp $" CVSID1; +const char *CVSid1="$Id: atacmds.cpp,v 1.36 2002/10/30 10:18:37 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 @@ -199,17 +199,17 @@ int ataReadHDIdentity (int device, struct hd_driveid *buf){ // describing which revision. Note that Revision 0 of ATA-3 does NOT // support SMART. For this one case we return -3 rather than +3 as // the version number. See notes above. -int ataVersionInfo (const char** description, struct hd_driveid drive, unsigned short *minor){ +int ataVersionInfo (const char** description, struct hd_driveid *drive, unsigned short *minor){ unsigned short major; int i; // get major and minor ATA revision numbers #ifdef __NEW_HD_DRIVE_ID - major=drive.major_rev_num; - *minor=drive.minor_rev_num; + major=drive->major_rev_num; + *minor=drive->minor_rev_num; #else - major=drive.word80; - *minor=drive.word81; + major=drive->word80; + *minor=drive->word81; #endif // First check if device has ANY ATA version information in it @@ -242,16 +242,16 @@ int ataVersionInfo (const char** description, struct hd_driveid drive, unsigned } // returns 1 if SMART supported, 0 if not supported or can't tell -int ataSmartSupport(struct hd_driveid drive){ +int ataSmartSupport(struct hd_driveid *drive){ unsigned short word82,word83; // get correct bits of IDENTIFY DEVICE structure #ifdef __NEW_HD_DRIVE_ID - word82=drive.command_set_1; - word83=drive.command_set_2; + word82=drive->command_set_1; + word83=drive->command_set_2; #else - word82=drive.command_sets; - word83=drive.word83; + word82=drive->command_sets; + word83=drive->word83; #endif // Note this does not work for ATA3 < Revision 6, when word82 and word83 were added @@ -260,16 +260,16 @@ int ataSmartSupport(struct hd_driveid drive){ } // returns 1 if SMART enabled, 0 if SMART disabled, -1 if can't tell -int ataIsSmartEnabled(struct hd_driveid drive){ +int ataIsSmartEnabled(struct hd_driveid *drive){ unsigned short word85,word87; // Get correct bits of IDENTIFY DRIVE structure #ifdef __NEW_HD_DRIVE_ID - word85=drive.cfs_enable_1; - word87=drive.csf_default; + word85=drive->cfs_enable_1; + word87=drive->csf_default; #else - word85=drive.word85; - word87=drive.word87; + word85=drive->word85; + word87=drive->word87; #endif if ((word87 & 0x0001<<14) && !(word87 & 0x0001<<15)) @@ -583,39 +583,39 @@ int ataSmartTest(int device, int testtype){ } /* Test Time Functions */ -int TestTime(struct ata_smart_values data,int testtype){ +int TestTime(struct ata_smart_values *data,int testtype){ switch (testtype){ case OFFLINE_FULL_SCAN: - return (int) data.total_time_to_complete_off_line; + return (int) data->total_time_to_complete_off_line; case SHORT_SELF_TEST: case SHORT_CAPTIVE_SELF_TEST: - return (int) data.short_test_completion_time; + return (int) data->short_test_completion_time; case EXTEND_SELF_TEST: case EXTEND_CAPTIVE_SELF_TEST: - return (int) data.extend_test_completion_time; + return (int) data->extend_test_completion_time; default: return 0; } } -int isSmartErrorLogCapable ( struct ata_smart_values data){ - return data.errorlog_capability & 0x01; +int isSmartErrorLogCapable ( struct ata_smart_values *data){ + return data->errorlog_capability & 0x01; } -int isSupportExecuteOfflineImmediate ( struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x01; +int isSupportExecuteOfflineImmediate ( struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x01; } -int isSupportAutomaticTimer ( struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x02; +int isSupportAutomaticTimer ( struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x02; } -int isSupportOfflineAbort ( struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x04; +int isSupportOfflineAbort ( struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x04; } -int isSupportOfflineSurfaceScan ( struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x08; +int isSupportOfflineSurfaceScan ( struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x08; } -int isSupportSelfTest (struct ata_smart_values data){ - return data.offline_data_collection_capability & 0x10; +int isSupportSelfTest (struct ata_smart_values *data){ + return data->offline_data_collection_capability & 0x10; } @@ -634,8 +634,8 @@ int isSupportSelfTest (struct ata_smart_values data){ // onlyfailed=0 : are or were any age or prefailure attributes <= threshold // onlyfailed=1: are any prefailure attributes <= threshold now -int ataCheckSmart(struct ata_smart_values data, - struct ata_smart_thresholds thresholds, +int ataCheckSmart(struct ata_smart_values *data, + struct ata_smart_thresholds *thresholds, int onlyfailed){ int i; @@ -643,8 +643,8 @@ int ataCheckSmart(struct ata_smart_values data, for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ // pointers to disk's values and vendor's thresholds - struct ata_smart_attribute *disk=data.vendor_attributes+i; - struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i; + struct ata_smart_attribute *disk=data->vendor_attributes+i; + struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i; // consider only valid attributes if (disk->id && thre->id){ diff --git a/sm5/atacmds.h b/sm5/atacmds.h index 5140c89ef150d4c4d07bab86720895acc7f4f2df..cbe706cfced6dad816abb943f519ddbfb39e8cb1 100644 --- a/sm5/atacmds.h +++ b/sm5/atacmds.h @@ -26,7 +26,7 @@ #define _ATACMDS_H_ #ifndef CVSID1 -#define CVSID1 "$Id: atacmds.h,v 1.23 2002/10/30 06:02:39 ballen4705 Exp $\n" +#define CVSID1 "$Id: atacmds.h,v 1.24 2002/10/30 10:18:37 ballen4705 Exp $\n" #endif // These are the major and minor versions for smartd and smartctl @@ -297,50 +297,50 @@ int ataSmartSelfTestAbort (int device); // Returns the latest compatibility of ATA/ATAPI Version the device // supports. Returns -1 if Version command is not supported -int ataVersionInfo (const char **description, struct hd_driveid drive, unsigned short *minor); +int ataVersionInfo (const char **description, struct hd_driveid *drive, unsigned short *minor); // If SMART supported, this is guaranteed to return 1 if SMART is enabled, else 0. int ataDoesSmartWork(int device); // returns 1 if SMART supported, 0 if not supported or can't tell -int ataSmartSupport ( struct hd_driveid drive); +int ataSmartSupport ( struct hd_driveid *drive); // Return values: // 1: SMART enabled // 0: SMART disabled // -1: can't tell if SMART is enabled -- try issuing ataDoesSmartWork command to see -int ataIsSmartEnabled(struct hd_driveid drive); +int ataIsSmartEnabled(struct hd_driveid *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 ( struct ata_smart_values data, struct ata_smart_thresholds thresholds, int onlyfailed); +int ataCheckSmart ( struct ata_smart_values *data, struct ata_smart_thresholds *thresholds, int onlyfailed); int ataSmartStatus2(int device); // int isOfflineTestTime ( struct ata_smart_values data) // returns S.M.A.R.T. Offline Test Time in seconds -int isOfflineTestTime ( struct ata_smart_values data); +int isOfflineTestTime ( struct ata_smart_values *data); -int isShortSelfTestTime ( struct ata_smart_values data); +int isShortSelfTestTime ( struct ata_smart_values *data); -int isExtendedSelfTestTime ( struct ata_smart_values data); +int isExtendedSelfTestTime ( struct ata_smart_values *data); -int isSmartErrorLogCapable ( struct ata_smart_values data); +int isSmartErrorLogCapable ( struct ata_smart_values *data); -int isSupportExecuteOfflineImmediate ( struct ata_smart_values data); +int isSupportExecuteOfflineImmediate ( struct ata_smart_values *data); -int isSupportAutomaticTimer ( struct ata_smart_values data); +int isSupportAutomaticTimer ( struct ata_smart_values *data); -int isSupportOfflineAbort ( struct ata_smart_values data); +int isSupportOfflineAbort ( struct ata_smart_values *data); -int isSupportOfflineSurfaceScan ( struct ata_smart_values data); +int isSupportOfflineSurfaceScan ( struct ata_smart_values *data); -int isSupportSelfTest (struct ata_smart_values data); +int isSupportSelfTest (struct ata_smart_values *data); int ataSmartTest(int device, int testtype); -int TestTime(struct ata_smart_values data,int testtype); +int TestTime(struct ata_smart_values *data,int testtype); // Prints Attribute Name for standard SMART attributes. Writes a // 30 byte string with attribute name into output diff --git a/sm5/ataprint.c b/sm5/ataprint.c index e4ceb9a10371a6cbe238d7995425089180baa149..13e24bf3b63dcbc7618bf33de220d3e5076f337b 100644 --- a/sm5/ataprint.c +++ b/sm5/ataprint.c @@ -29,7 +29,7 @@ #include "smartctl.h" #include "extern.h" -const char *CVSid2="$Id: ataprint.c,v 1.39 2002/10/30 06:02:39 ballen4705 Exp $" +const char *CVSid2="$Id: ataprint.c,v 1.40 2002/10/30 10:18:37 ballen4705 Exp $" CVSID1 CVSID2 CVSID3 CVSID6; // for passing global control variables @@ -63,7 +63,7 @@ void printswap(char *in, unsigned int n){ } -void ataPrintDriveInfo (struct hd_driveid drive){ +void ataPrintDriveInfo (struct hd_driveid *drive){ int version; const char *description; char unknown[64]; @@ -71,13 +71,13 @@ void ataPrintDriveInfo (struct hd_driveid drive){ // print out model, serial # and firmware versions (byte-swap ASCI strings) pout("Device Model: "); - printswap(drive.model,40); + printswap(drive->model,40); pout("Serial Number: "); - printswap(drive.serial_no,20); + printswap(drive->serial_no,20); pout("Firmware Version: "); - printswap(drive.fw_rev,8); + printswap(drive->fw_rev,8); // now get ATA version info version=ataVersionInfo(&description,drive, &minorrev); @@ -107,89 +107,88 @@ void ataPrintDriveInfo (struct hd_driveid drive){ } -/* void PrintSmartOfflineStatus ( struct ata_smart_values data) - prints verbose value Off-line data collection status byte */ -void PrintSmartOfflineStatus(struct ata_smart_values data){ +/* prints verbose value Off-line data collection status byte */ +void PrintSmartOfflineStatus(struct ata_smart_values *data){ pout("Off-line data collection status: "); - switch(data.offline_data_collection_status){ + switch(data->offline_data_collection_status){ case 0x00: case 0x80: pout("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("never started.\n"); break; case 0x01: case 0x81: pout("(0x%02x)\tReserved.\n", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); break; case 0x02: case 0x82: pout("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("completed without error.\n"); break; case 0x03: case 0x83: pout("(0x%02x)\tReserved.\n", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); break; case 0x04: case 0x84: pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("suspended by an interrupting command from host.\n"); break; case 0x05: case 0x85: pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("aborted by an interrupting command from host.\n"); break; case 0x06: case 0x86: pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("aborted by the device with a fatal error.\n"); break; default: - if ( ((data.offline_data_collection_status >= 0x07) && - (data.offline_data_collection_status <= 0x3f)) || - ((data.offline_data_collection_status >= 0xc0) && - (data.offline_data_collection_status <= 0xff)) ) - pout("(0x%02x)\tVendor Specific.\n",(int)data.offline_data_collection_status); + if ( ((data->offline_data_collection_status >= 0x07) && + (data->offline_data_collection_status <= 0x3f)) || + ((data->offline_data_collection_status >= 0xc0) && + (data->offline_data_collection_status <= 0xff)) ) + pout("(0x%02x)\tVendor Specific.\n",(int)data->offline_data_collection_status); else - pout("(0x%02x)\tReserved.\n",(int)data.offline_data_collection_status); + pout("(0x%02x)\tReserved.\n",(int)data->offline_data_collection_status); } } -void PrintSmartSelfExecStatus ( struct ata_smart_values data) +void PrintSmartSelfExecStatus(struct ata_smart_values *data) { pout("Self-test execution status: "); - switch (data.self_test_exec_status >> 4) + switch (data->self_test_exec_status >> 4) { case 0: pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n"); break; case 1: pout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("the host.\n"); break; case 2: pout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("by the host with a hard or soft reset.\n"); break; case 3: pout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("occurred while the device was executing\n\t\t\t\t\t"); pout("its self-test routine and the device \n\t\t\t\t\t"); pout("was unable to complete the self-test \n\t\t\t\t\t"); @@ -197,36 +196,36 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data) break; case 4: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("a test element that failed and the test\n\t\t\t\t\t"); pout("element that failed is not known.\n"); break; case 5: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("the electrical element of the test\n\t\t\t\t\t"); pout("failed.\n"); break; case 6: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("the servo (and/or seek) element of the \n\t\t\t\t\t"); pout("test failed.\n"); break; case 7: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("the read element of the test failed.\n"); break; case 15: pout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("%1d0%% of test remaining.\n", - (int)(data.self_test_exec_status & 0x0f)); + (int)(data->self_test_exec_status & 0x0f)); break; default: pout("(%4d)\tReserved.\n", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); break; } @@ -234,21 +233,21 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data) -void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values data){ +void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values *data){ pout("Total time to complete off-line \n"); pout("data collection: \t\t (%4d) seconds.\n", - (int)data.total_time_to_complete_off_line); + (int)data->total_time_to_complete_off_line); } -void PrintSmartOfflineCollectCap ( struct ata_smart_values data) +void PrintSmartOfflineCollectCap(struct ata_smart_values *data) { pout("Offline data collection\n"); pout("capabilities: \t\t\t (0x%02x) ", - (int)data.offline_data_collection_capability); + (int)data->offline_data_collection_capability); - if (data.offline_data_collection_capability == 0x00) + if (data->offline_data_collection_capability == 0x00) { pout("\tOff-line data collection not supported.\n"); } @@ -278,23 +277,23 @@ void PrintSmartOfflineCollectCap ( struct ata_smart_values data) -void PrintSmartCapability ( struct ata_smart_values data) +void PrintSmartCapability ( struct ata_smart_values *data) { pout("SMART capabilities: "); - pout("(0x%04x)\t", (int)data.smart_capability); + pout("(0x%04x)\t", (int)data->smart_capability); - if (data.smart_capability == 0x00) + if (data->smart_capability == 0x00) { pout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n"); } else { - pout( "%s\n", (data.smart_capability & 0x01)? + pout( "%s\n", (data->smart_capability & 0x01)? "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.": "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode."); - if ( data.smart_capability & 0x02 ) + if ( data->smart_capability & 0x02 ) { pout("\t\t\t\t\tSupports SMART auto save timer.\n"); } @@ -303,7 +302,7 @@ void PrintSmartCapability ( struct ata_smart_values data) -void PrintSmartErrorLogCapability ( struct ata_smart_values data) +void PrintSmartErrorLogCapability ( struct ata_smart_values *data) { pout("Error logging capability: "); @@ -311,23 +310,23 @@ void PrintSmartErrorLogCapability ( struct ata_smart_values data) if ( isSmartErrorLogCapable(data) ) { pout(" (0x%02x)\tError logging supported.\n", - (int)data.errorlog_capability); + (int)data->errorlog_capability); } else { pout(" (0x%02x)\tError logging NOT supported.\n", - (int)data.errorlog_capability); + (int)data->errorlog_capability); } } -void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data) +void PrintSmartShortSelfTestPollingTime (struct ata_smart_values *data) { if ( isSupportSelfTest(data) ) { pout("Short self-test routine \n"); pout("recommended polling time: \t (%4d) minutes.\n", - (int)data.short_test_completion_time); + (int)data->short_test_completion_time); } else @@ -338,13 +337,13 @@ void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data) } -void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data) +void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values *data) { if ( isSupportSelfTest(data) ) { pout("Extended self-test routine \n"); pout("recommended polling time: \t (%4d) minutes.\n", - (int)data.extend_test_completion_time); + (int)data->extend_test_completion_time); } else { @@ -357,8 +356,8 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data) // 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 -void PrintSmartAttribWithThres (struct ata_smart_values data, - struct ata_smart_thresholds thresholds, +void PrintSmartAttribWithThres (struct ata_smart_values *data, + struct ata_smart_thresholds *thresholds, int onlyfailed){ int i,j; long long rawvalue; @@ -367,8 +366,8 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, // step through all vendor attributes for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ char *status; - struct ata_smart_attribute *disk=data.vendor_attributes+i; - struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i; + struct ata_smart_attribute *disk=data->vendor_attributes+i; + struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i; // consider only valid attributes if (disk->id && thre->id){ @@ -389,7 +388,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, // print header only if needed if (needheader){ if (!onlyfailed){ - pout("SMART Attributes Data Structure revision number: %d\n",(int)data.revnumber); + pout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber); pout("Vendor Specific SMART Attributes with Thresholds:\n"); } pout("ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE\n"); @@ -463,7 +462,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, } -void ataPrintGeneralSmartValues(struct ata_smart_values data){ +void ataPrintGeneralSmartValues(struct ata_smart_values *data){ pout("General SMART Values:\n"); PrintSmartOfflineStatus(data); @@ -494,31 +493,31 @@ int nonempty(unsigned char *testarea,int n){ } // returns number of errors -void ataPrintSmartErrorlog (struct ata_smart_errorlog data){ +void ataPrintSmartErrorlog (struct ata_smart_errorlog *data){ int i,j,k; - pout("SMART Error Log Version: %d\n", (int)data.revnumber); + pout("SMART Error Log Version: %d\n", (int)data->revnumber); // if no errors logged, return - if (!data.error_log_pointer){ + if (!data->error_log_pointer){ pout("No Errors Logged\n\n"); return; } QUIETON(con); // if log pointer out of range, return - if ( data.error_log_pointer>5 ){ + if ( data->error_log_pointer>5 ){ pout("Invalid Error Log index = %02x (T13/1321D rev 1c" "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n\n", - (int)data.error_log_pointer); + (int)data->error_log_pointer); return; } // starting printing error log info - if (data.ata_error_count<=5) - pout( "ATA Error Count: %d\n", (int)data.ata_error_count); + if (data->ata_error_count<=5) + pout( "ATA Error Count: %d\n", (int)data->ata_error_count); else pout( "ATA Error Count: %d (device log contains only the most recent five errors)\n", - (int)data.ata_error_count); + (int)data->ata_error_count); QUIETOFF(con); pout("\tDCR = Device Control Register\n"); pout("\tFR = Features Register\n"); @@ -537,12 +536,12 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){ for (k = 4; k >= 0; k-- ) { // The error log data structure entries are a circular buffer - i=(data.error_log_pointer+k)%5; + i=(data->error_log_pointer+k)%5; // Spec says: unused error log structures shall be zero filled - if (nonempty((unsigned char*)&(data.errorlog_struct[i]),sizeof(data.errorlog_struct[i]))){ + if (nonempty((unsigned char*)&(data->errorlog_struct[i]),sizeof(data->errorlog_struct[i]))){ char *msgstate; - switch (data.errorlog_struct[i].error_struct.state){ + switch (data->errorlog_struct[i].error_struct.state){ case 0x00: msgstate="in an unknown state";break; case 0x01: msgstate="sleeping"; break; case 0x02: msgstate="in standby mode"; break; @@ -553,22 +552,22 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){ // See table 42 of ATA5 spec QUIETON(con); pout("Error %d occurred at disk power-on lifetime: %d hours\n", - (int)(5-k), (int)data.errorlog_struct[i].error_struct.timestamp); + (int)(5-k), (int)data->errorlog_struct[i].error_struct.timestamp); QUIETOFF(con); pout("When the command that caused the error occurred, the device was %s.\n",msgstate); pout("After command completion occurred, registers were:\n"); pout("ER:%02x SC:%02x SN:%02x CL:%02x CH:%02x D/H:%02x ST:%02x\n", - (int)data.errorlog_struct[i].error_struct.error_register, - (int)data.errorlog_struct[i].error_struct.sector_count, - (int)data.errorlog_struct[i].error_struct.sector_number, - (int)data.errorlog_struct[i].error_struct.cylinder_low, - (int)data.errorlog_struct[i].error_struct.cylinder_high, - (int)data.errorlog_struct[i].error_struct.drive_head, - (int)data.errorlog_struct[i].error_struct.status); + (int)data->errorlog_struct[i].error_struct.error_register, + (int)data->errorlog_struct[i].error_struct.sector_count, + (int)data->errorlog_struct[i].error_struct.sector_number, + (int)data->errorlog_struct[i].error_struct.cylinder_low, + (int)data->errorlog_struct[i].error_struct.cylinder_high, + (int)data->errorlog_struct[i].error_struct.drive_head, + (int)data->errorlog_struct[i].error_struct.status); pout("Sequence of commands leading to the command that caused the error were:\n"); pout("DCR FR SC SN CL CH D/H CR Timestamp\n"); for ( j = 4; j >= 0; j--){ - struct ata_smart_errorlog_command_struct *thiscommand=&(data.errorlog_struct[i].commands[j]); + struct ata_smart_errorlog_command_struct *thiscommand=&(data->errorlog_struct[i].commands[j]); // Spec says: unused data command structures shall be zero filled if (nonempty((unsigned char*)thiscommand,sizeof(*thiscommand))) @@ -595,15 +594,15 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){ } // return value is number of entries found where the self-test showed an error -int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){ +int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *data,int allentries){ int i,j,noheaderprinted=1; int retval=0; if (allentries) - pout("SMART Self-test log, version number %d\n",(int)data.revnumber); - if ((data.revnumber!=0x0001) && allentries) + pout("SMART Self-test log, version number %d\n",(int)data->revnumber); + if ((data->revnumber!=0x0001) && allentries) pout("Warning - structure revision number does not match spec!\n"); - if (data.mostrecenttest==0){ + if (data->mostrecenttest==0){ if (allentries) pout("No self-tests have been logged\n\n"); return 0; @@ -613,8 +612,8 @@ int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){ for (i=20;i>=0;i--){ struct ata_smart_selftestlog_struct *log; // log is a circular buffer - j=(i+data.mostrecenttest)%21; - log=data.selftest_struct+j; + j=(i+data->mostrecenttest)%21; + log=data->selftest_struct+j; if (nonempty((unsigned char*)log,sizeof(*log))){ char *msgtest,*msgstat,percent[64],firstlba[64]; @@ -680,17 +679,17 @@ int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){ return retval; } -void ataPseudoCheckSmart ( struct ata_smart_values data, - struct ata_smart_thresholds thresholds) { +void ataPseudoCheckSmart ( struct ata_smart_values *data, + struct ata_smart_thresholds *thresholds) { int i; int failed = 0; for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++) { - if (data.vendor_attributes[i].id && - thresholds.thres_entries[i].id && - data.vendor_attributes[i].status.flag.prefailure && - (data.vendor_attributes[i].current <= thresholds.thres_entries[i].threshold) && - (thresholds.thres_entries[i].threshold != 0xFE)){ - pout("Attribute ID %d Failed\n",(int)data.vendor_attributes[i].id); + if (data->vendor_attributes[i].id && + thresholds->thres_entries[i].id && + data->vendor_attributes[i].status.flag.prefailure && + (data->vendor_attributes[i].current <= thresholds->thres_entries[i].threshold) && + (thresholds->thres_entries[i].threshold != 0xFE)){ + pout("Attribute ID %d Failed\n",(int)data->vendor_attributes[i].id); failed = 1; } } @@ -722,11 +721,11 @@ int ataPrintMain (int fd){ // Print most drive identity information if requested if (con->driveinfo){ pout("=== START OF INFORMATION SECTION ===\n"); - ataPrintDriveInfo(drive); + ataPrintDriveInfo(&drive); } // now check if drive supports SMART; otherwise time to exit - if (!ataSmartSupport(drive)){ + if (!ataSmartSupport(&drive)){ pout("SMART support is: Unavailable - device lacks SMART capability.\n"); pout(" Checking to be sure by trying SMART ENABLE command.\n"); if (ataEnableSmart(fd)){ @@ -816,7 +815,7 @@ int ataPrintMain (int fd){ // Enable/Disable Off-line testing if (con->smartautoofflineenable){ - if (!isSupportAutomaticTimer(smartval)){ + if (!isSupportAutomaticTimer(&smartval)){ pout("Warning: device does not support SMART Automatic Timers.\n\n"); } if (ataEnableAutoOffline(fd)){ @@ -827,7 +826,7 @@ int ataPrintMain (int fd){ pout("SMART Automatic Offline Testing Enabled every four hours.\n"); } if (con->smartautoofflinedisable){ - if (!isSupportAutomaticTimer(smartval)){ + if (!isSupportAutomaticTimer(&smartval)){ pout("Warning: device does not support SMART Automatic Timers.\n\n"); } if (ataDisableAutoOffline(fd)){ @@ -855,14 +854,14 @@ int ataPrintMain (int fd){ pout("SMART overall-health self-assessment test result: FAILED!\n" "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); QUIETOFF(con); - if (ataCheckSmart(smartval, smartthres,1)){ + if (ataCheckSmart(&smartval, &smartthres,1)){ returnval|=FAILATTR; if (con->smartvendorattrib) pout("See vendor-specific Attribute list for failed Attributes.\n\n"); else { QUIETON(con); pout("Failed Attributes:\n"); - PrintSmartAttribWithThres(smartval, smartthres,1); + PrintSmartAttribWithThres(&smartval, &smartthres,1); } } else @@ -872,13 +871,13 @@ int ataPrintMain (int fd){ } else { pout("SMART overall-health self-assessment test result: PASSED\n"); - if (ataCheckSmart(smartval, smartthres,0)){ + if (ataCheckSmart(&smartval, &smartthres,0)){ if (con->smartvendorattrib) pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); else { QUIETON(con); pout("Please note the following marginal attributes:\n"); - PrintSmartAttribWithThres(smartval, smartthres,2); + PrintSmartAttribWithThres(&smartval, &smartthres,2); } returnval|=FAILAGE; } @@ -890,18 +889,18 @@ int ataPrintMain (int fd){ // Print general SMART values if (con->generalsmartvalues) - ataPrintGeneralSmartValues(smartval); + ataPrintGeneralSmartValues(&smartval); // Print vendor-specific attributes if (con->smartvendorattrib){ QUIETON(con); - PrintSmartAttribWithThres(smartval, smartthres,con->quietmode?2:0); + PrintSmartAttribWithThres(&smartval, &smartthres,con->quietmode?2:0); QUIETOFF(con); } // Print SMART error log if (con->smarterrorlog){ - if (!isSmartErrorLogCapable(smartval)) + if (!isSmartErrorLogCapable(&smartval)) pout("Warning: device does not support Error Logging\n"); if (ataReadErrorLog(fd, &smarterror)){ pout("Smartctl: SMART Errorlog Read Failed\n"); @@ -909,14 +908,14 @@ int ataPrintMain (int fd){ } else { // turn on quiet mode inside this - ataPrintSmartErrorlog(smarterror); + ataPrintSmartErrorlog(&smarterror); QUIETOFF(con); } } // Print SMART self-test log if (con->smartselftestlog){ - if (!isSmartErrorLogCapable(smartval)) + if (!isSmartErrorLogCapable(&smartval)) pout("Warning: device does not support Self Test Logging\n"); else { if(ataReadSelfTestLog(fd, &smartselftest)){ @@ -925,7 +924,7 @@ int ataPrintMain (int fd){ } else { QUIETON(con); - if (ataPrintSmartSelfTestlog(smartselftest,!con->quietmode)) + if (ataPrintSmartSelfTestlog(&smartselftest,!con->quietmode)) returnval|=FAILLOG; QUIETOFF(con); pout("\n"); @@ -939,9 +938,9 @@ int ataPrintMain (int fd){ pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n"); // if doing a self-test, be sure it's supported by the hardware - if (con->testcase==OFFLINE_FULL_SCAN && !isSupportExecuteOfflineImmediate(smartval)) + if (con->testcase==OFFLINE_FULL_SCAN && !isSupportExecuteOfflineImmediate(&smartval)) pout("Warning: device does not support Execute Off-Line Immediate function.\n\n"); - else if (!isSupportSelfTest(smartval)) + else if (!isSupportSelfTest(&smartval)) pout("Warning: device does not support Self-Test functions.\n\n"); // Now do the test @@ -949,7 +948,7 @@ int ataPrintMain (int fd){ return returnval|=FAILSMART; // Tell user how long test will take to complete - if ((timewait=TestTime(smartval,con->testcase))){ + if ((timewait=TestTime(&smartval,con->testcase))){ pout("Please wait %d %s for test to complete.\n", (int)timewait, con->testcase==OFFLINE_FULL_SCAN?"seconds":"minutes"); diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp index 19159a7348c774a54f1c5ef5e3fd14b3fb18daf5..20d233d8439ad0d7d63d9b2970d8dc47a4abd916 100644 --- a/sm5/ataprint.cpp +++ b/sm5/ataprint.cpp @@ -29,7 +29,7 @@ #include "smartctl.h" #include "extern.h" -const char *CVSid2="$Id: ataprint.cpp,v 1.39 2002/10/30 06:02:39 ballen4705 Exp $" +const char *CVSid2="$Id: ataprint.cpp,v 1.40 2002/10/30 10:18:37 ballen4705 Exp $" CVSID1 CVSID2 CVSID3 CVSID6; // for passing global control variables @@ -63,7 +63,7 @@ void printswap(char *in, unsigned int n){ } -void ataPrintDriveInfo (struct hd_driveid drive){ +void ataPrintDriveInfo (struct hd_driveid *drive){ int version; const char *description; char unknown[64]; @@ -71,13 +71,13 @@ void ataPrintDriveInfo (struct hd_driveid drive){ // print out model, serial # and firmware versions (byte-swap ASCI strings) pout("Device Model: "); - printswap(drive.model,40); + printswap(drive->model,40); pout("Serial Number: "); - printswap(drive.serial_no,20); + printswap(drive->serial_no,20); pout("Firmware Version: "); - printswap(drive.fw_rev,8); + printswap(drive->fw_rev,8); // now get ATA version info version=ataVersionInfo(&description,drive, &minorrev); @@ -107,89 +107,88 @@ void ataPrintDriveInfo (struct hd_driveid drive){ } -/* void PrintSmartOfflineStatus ( struct ata_smart_values data) - prints verbose value Off-line data collection status byte */ -void PrintSmartOfflineStatus(struct ata_smart_values data){ +/* prints verbose value Off-line data collection status byte */ +void PrintSmartOfflineStatus(struct ata_smart_values *data){ pout("Off-line data collection status: "); - switch(data.offline_data_collection_status){ + switch(data->offline_data_collection_status){ case 0x00: case 0x80: pout("(0x%02x)\tOffline data collection activity was\n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("never started.\n"); break; case 0x01: case 0x81: pout("(0x%02x)\tReserved.\n", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); break; case 0x02: case 0x82: pout("(0x%02x)\tOffline data collection activity \n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("completed without error.\n"); break; case 0x03: case 0x83: pout("(0x%02x)\tReserved.\n", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); break; case 0x04: case 0x84: pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("suspended by an interrupting command from host.\n"); break; case 0x05: case 0x85: pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("aborted by an interrupting command from host.\n"); break; case 0x06: case 0x86: pout("(0x%02x)\tOffline data collection activity was \n\t\t\t\t\t", - (int)data.offline_data_collection_status); + (int)data->offline_data_collection_status); pout("aborted by the device with a fatal error.\n"); break; default: - if ( ((data.offline_data_collection_status >= 0x07) && - (data.offline_data_collection_status <= 0x3f)) || - ((data.offline_data_collection_status >= 0xc0) && - (data.offline_data_collection_status <= 0xff)) ) - pout("(0x%02x)\tVendor Specific.\n",(int)data.offline_data_collection_status); + if ( ((data->offline_data_collection_status >= 0x07) && + (data->offline_data_collection_status <= 0x3f)) || + ((data->offline_data_collection_status >= 0xc0) && + (data->offline_data_collection_status <= 0xff)) ) + pout("(0x%02x)\tVendor Specific.\n",(int)data->offline_data_collection_status); else - pout("(0x%02x)\tReserved.\n",(int)data.offline_data_collection_status); + pout("(0x%02x)\tReserved.\n",(int)data->offline_data_collection_status); } } -void PrintSmartSelfExecStatus ( struct ata_smart_values data) +void PrintSmartSelfExecStatus(struct ata_smart_values *data) { pout("Self-test execution status: "); - switch (data.self_test_exec_status >> 4) + switch (data->self_test_exec_status >> 4) { case 0: pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("without error or no self-test has ever \n\t\t\t\t\tbeen run.\n"); break; case 1: pout("(%4d)\tThe self-test routine was aborted by\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("the host.\n"); break; case 2: pout("(%4d)\tThe self-test routine was interrupted\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("by the host with a hard or soft reset.\n"); break; case 3: pout("(%4d)\tA fatal error or unknown test error\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("occurred while the device was executing\n\t\t\t\t\t"); pout("its self-test routine and the device \n\t\t\t\t\t"); pout("was unable to complete the self-test \n\t\t\t\t\t"); @@ -197,36 +196,36 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data) break; case 4: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("a test element that failed and the test\n\t\t\t\t\t"); pout("element that failed is not known.\n"); break; case 5: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("the electrical element of the test\n\t\t\t\t\t"); pout("failed.\n"); break; case 6: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("the servo (and/or seek) element of the \n\t\t\t\t\t"); pout("test failed.\n"); break; case 7: pout("(%4d)\tThe previous self-test completed having\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("the read element of the test failed.\n"); break; case 15: pout("(%4d)\tSelf-test routine in progress...\n\t\t\t\t\t", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); pout("%1d0%% of test remaining.\n", - (int)(data.self_test_exec_status & 0x0f)); + (int)(data->self_test_exec_status & 0x0f)); break; default: pout("(%4d)\tReserved.\n", - (int)data.self_test_exec_status); + (int)data->self_test_exec_status); break; } @@ -234,21 +233,21 @@ void PrintSmartSelfExecStatus ( struct ata_smart_values data) -void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values data){ +void PrintSmartTotalTimeCompleteOffline ( struct ata_smart_values *data){ pout("Total time to complete off-line \n"); pout("data collection: \t\t (%4d) seconds.\n", - (int)data.total_time_to_complete_off_line); + (int)data->total_time_to_complete_off_line); } -void PrintSmartOfflineCollectCap ( struct ata_smart_values data) +void PrintSmartOfflineCollectCap(struct ata_smart_values *data) { pout("Offline data collection\n"); pout("capabilities: \t\t\t (0x%02x) ", - (int)data.offline_data_collection_capability); + (int)data->offline_data_collection_capability); - if (data.offline_data_collection_capability == 0x00) + if (data->offline_data_collection_capability == 0x00) { pout("\tOff-line data collection not supported.\n"); } @@ -278,23 +277,23 @@ void PrintSmartOfflineCollectCap ( struct ata_smart_values data) -void PrintSmartCapability ( struct ata_smart_values data) +void PrintSmartCapability ( struct ata_smart_values *data) { pout("SMART capabilities: "); - pout("(0x%04x)\t", (int)data.smart_capability); + pout("(0x%04x)\t", (int)data->smart_capability); - if (data.smart_capability == 0x00) + if (data->smart_capability == 0x00) { pout("Automatic saving of SMART data\t\t\t\t\tis not implemented.\n"); } else { - pout( "%s\n", (data.smart_capability & 0x01)? + pout( "%s\n", (data->smart_capability & 0x01)? "Saves SMART data before entering\n\t\t\t\t\tpower-saving mode.": "Does not save SMART data before\n\t\t\t\t\tentering power-saving mode."); - if ( data.smart_capability & 0x02 ) + if ( data->smart_capability & 0x02 ) { pout("\t\t\t\t\tSupports SMART auto save timer.\n"); } @@ -303,7 +302,7 @@ void PrintSmartCapability ( struct ata_smart_values data) -void PrintSmartErrorLogCapability ( struct ata_smart_values data) +void PrintSmartErrorLogCapability ( struct ata_smart_values *data) { pout("Error logging capability: "); @@ -311,23 +310,23 @@ void PrintSmartErrorLogCapability ( struct ata_smart_values data) if ( isSmartErrorLogCapable(data) ) { pout(" (0x%02x)\tError logging supported.\n", - (int)data.errorlog_capability); + (int)data->errorlog_capability); } else { pout(" (0x%02x)\tError logging NOT supported.\n", - (int)data.errorlog_capability); + (int)data->errorlog_capability); } } -void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data) +void PrintSmartShortSelfTestPollingTime (struct ata_smart_values *data) { if ( isSupportSelfTest(data) ) { pout("Short self-test routine \n"); pout("recommended polling time: \t (%4d) minutes.\n", - (int)data.short_test_completion_time); + (int)data->short_test_completion_time); } else @@ -338,13 +337,13 @@ void PrintSmartShortSelfTestPollingTime ( struct ata_smart_values data) } -void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data) +void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values *data) { if ( isSupportSelfTest(data) ) { pout("Extended self-test routine \n"); pout("recommended polling time: \t (%4d) minutes.\n", - (int)data.extend_test_completion_time); + (int)data->extend_test_completion_time); } else { @@ -357,8 +356,8 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data) // 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 -void PrintSmartAttribWithThres (struct ata_smart_values data, - struct ata_smart_thresholds thresholds, +void PrintSmartAttribWithThres (struct ata_smart_values *data, + struct ata_smart_thresholds *thresholds, int onlyfailed){ int i,j; long long rawvalue; @@ -367,8 +366,8 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, // step through all vendor attributes for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){ char *status; - struct ata_smart_attribute *disk=data.vendor_attributes+i; - struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i; + struct ata_smart_attribute *disk=data->vendor_attributes+i; + struct ata_smart_threshold_entry *thre=thresholds->thres_entries+i; // consider only valid attributes if (disk->id && thre->id){ @@ -389,7 +388,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, // print header only if needed if (needheader){ if (!onlyfailed){ - pout("SMART Attributes Data Structure revision number: %d\n",(int)data.revnumber); + pout("SMART Attributes Data Structure revision number: %d\n",(int)data->revnumber); pout("Vendor Specific SMART Attributes with Thresholds:\n"); } pout("ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE WHEN_FAILED RAW_VALUE\n"); @@ -463,7 +462,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, } -void ataPrintGeneralSmartValues(struct ata_smart_values data){ +void ataPrintGeneralSmartValues(struct ata_smart_values *data){ pout("General SMART Values:\n"); PrintSmartOfflineStatus(data); @@ -494,31 +493,31 @@ int nonempty(unsigned char *testarea,int n){ } // returns number of errors -void ataPrintSmartErrorlog (struct ata_smart_errorlog data){ +void ataPrintSmartErrorlog (struct ata_smart_errorlog *data){ int i,j,k; - pout("SMART Error Log Version: %d\n", (int)data.revnumber); + pout("SMART Error Log Version: %d\n", (int)data->revnumber); // if no errors logged, return - if (!data.error_log_pointer){ + if (!data->error_log_pointer){ pout("No Errors Logged\n\n"); return; } QUIETON(con); // if log pointer out of range, return - if ( data.error_log_pointer>5 ){ + if ( data->error_log_pointer>5 ){ pout("Invalid Error Log index = %02x (T13/1321D rev 1c" "Section 8.41.6.8.2.2 gives valid range from 1 to 5)\n\n", - (int)data.error_log_pointer); + (int)data->error_log_pointer); return; } // starting printing error log info - if (data.ata_error_count<=5) - pout( "ATA Error Count: %d\n", (int)data.ata_error_count); + if (data->ata_error_count<=5) + pout( "ATA Error Count: %d\n", (int)data->ata_error_count); else pout( "ATA Error Count: %d (device log contains only the most recent five errors)\n", - (int)data.ata_error_count); + (int)data->ata_error_count); QUIETOFF(con); pout("\tDCR = Device Control Register\n"); pout("\tFR = Features Register\n"); @@ -537,12 +536,12 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){ for (k = 4; k >= 0; k-- ) { // The error log data structure entries are a circular buffer - i=(data.error_log_pointer+k)%5; + i=(data->error_log_pointer+k)%5; // Spec says: unused error log structures shall be zero filled - if (nonempty((unsigned char*)&(data.errorlog_struct[i]),sizeof(data.errorlog_struct[i]))){ + if (nonempty((unsigned char*)&(data->errorlog_struct[i]),sizeof(data->errorlog_struct[i]))){ char *msgstate; - switch (data.errorlog_struct[i].error_struct.state){ + switch (data->errorlog_struct[i].error_struct.state){ case 0x00: msgstate="in an unknown state";break; case 0x01: msgstate="sleeping"; break; case 0x02: msgstate="in standby mode"; break; @@ -553,22 +552,22 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){ // See table 42 of ATA5 spec QUIETON(con); pout("Error %d occurred at disk power-on lifetime: %d hours\n", - (int)(5-k), (int)data.errorlog_struct[i].error_struct.timestamp); + (int)(5-k), (int)data->errorlog_struct[i].error_struct.timestamp); QUIETOFF(con); pout("When the command that caused the error occurred, the device was %s.\n",msgstate); pout("After command completion occurred, registers were:\n"); pout("ER:%02x SC:%02x SN:%02x CL:%02x CH:%02x D/H:%02x ST:%02x\n", - (int)data.errorlog_struct[i].error_struct.error_register, - (int)data.errorlog_struct[i].error_struct.sector_count, - (int)data.errorlog_struct[i].error_struct.sector_number, - (int)data.errorlog_struct[i].error_struct.cylinder_low, - (int)data.errorlog_struct[i].error_struct.cylinder_high, - (int)data.errorlog_struct[i].error_struct.drive_head, - (int)data.errorlog_struct[i].error_struct.status); + (int)data->errorlog_struct[i].error_struct.error_register, + (int)data->errorlog_struct[i].error_struct.sector_count, + (int)data->errorlog_struct[i].error_struct.sector_number, + (int)data->errorlog_struct[i].error_struct.cylinder_low, + (int)data->errorlog_struct[i].error_struct.cylinder_high, + (int)data->errorlog_struct[i].error_struct.drive_head, + (int)data->errorlog_struct[i].error_struct.status); pout("Sequence of commands leading to the command that caused the error were:\n"); pout("DCR FR SC SN CL CH D/H CR Timestamp\n"); for ( j = 4; j >= 0; j--){ - struct ata_smart_errorlog_command_struct *thiscommand=&(data.errorlog_struct[i].commands[j]); + struct ata_smart_errorlog_command_struct *thiscommand=&(data->errorlog_struct[i].commands[j]); // Spec says: unused data command structures shall be zero filled if (nonempty((unsigned char*)thiscommand,sizeof(*thiscommand))) @@ -595,15 +594,15 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog data){ } // return value is number of entries found where the self-test showed an error -int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){ +int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *data,int allentries){ int i,j,noheaderprinted=1; int retval=0; if (allentries) - pout("SMART Self-test log, version number %d\n",(int)data.revnumber); - if ((data.revnumber!=0x0001) && allentries) + pout("SMART Self-test log, version number %d\n",(int)data->revnumber); + if ((data->revnumber!=0x0001) && allentries) pout("Warning - structure revision number does not match spec!\n"); - if (data.mostrecenttest==0){ + if (data->mostrecenttest==0){ if (allentries) pout("No self-tests have been logged\n\n"); return 0; @@ -613,8 +612,8 @@ int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){ for (i=20;i>=0;i--){ struct ata_smart_selftestlog_struct *log; // log is a circular buffer - j=(i+data.mostrecenttest)%21; - log=data.selftest_struct+j; + j=(i+data->mostrecenttest)%21; + log=data->selftest_struct+j; if (nonempty((unsigned char*)log,sizeof(*log))){ char *msgtest,*msgstat,percent[64],firstlba[64]; @@ -680,17 +679,17 @@ int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data,int allentries){ return retval; } -void ataPseudoCheckSmart ( struct ata_smart_values data, - struct ata_smart_thresholds thresholds) { +void ataPseudoCheckSmart ( struct ata_smart_values *data, + struct ata_smart_thresholds *thresholds) { int i; int failed = 0; for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++) { - if (data.vendor_attributes[i].id && - thresholds.thres_entries[i].id && - data.vendor_attributes[i].status.flag.prefailure && - (data.vendor_attributes[i].current <= thresholds.thres_entries[i].threshold) && - (thresholds.thres_entries[i].threshold != 0xFE)){ - pout("Attribute ID %d Failed\n",(int)data.vendor_attributes[i].id); + if (data->vendor_attributes[i].id && + thresholds->thres_entries[i].id && + data->vendor_attributes[i].status.flag.prefailure && + (data->vendor_attributes[i].current <= thresholds->thres_entries[i].threshold) && + (thresholds->thres_entries[i].threshold != 0xFE)){ + pout("Attribute ID %d Failed\n",(int)data->vendor_attributes[i].id); failed = 1; } } @@ -722,11 +721,11 @@ int ataPrintMain (int fd){ // Print most drive identity information if requested if (con->driveinfo){ pout("=== START OF INFORMATION SECTION ===\n"); - ataPrintDriveInfo(drive); + ataPrintDriveInfo(&drive); } // now check if drive supports SMART; otherwise time to exit - if (!ataSmartSupport(drive)){ + if (!ataSmartSupport(&drive)){ pout("SMART support is: Unavailable - device lacks SMART capability.\n"); pout(" Checking to be sure by trying SMART ENABLE command.\n"); if (ataEnableSmart(fd)){ @@ -816,7 +815,7 @@ int ataPrintMain (int fd){ // Enable/Disable Off-line testing if (con->smartautoofflineenable){ - if (!isSupportAutomaticTimer(smartval)){ + if (!isSupportAutomaticTimer(&smartval)){ pout("Warning: device does not support SMART Automatic Timers.\n\n"); } if (ataEnableAutoOffline(fd)){ @@ -827,7 +826,7 @@ int ataPrintMain (int fd){ pout("SMART Automatic Offline Testing Enabled every four hours.\n"); } if (con->smartautoofflinedisable){ - if (!isSupportAutomaticTimer(smartval)){ + if (!isSupportAutomaticTimer(&smartval)){ pout("Warning: device does not support SMART Automatic Timers.\n\n"); } if (ataDisableAutoOffline(fd)){ @@ -855,14 +854,14 @@ int ataPrintMain (int fd){ pout("SMART overall-health self-assessment test result: FAILED!\n" "Drive failure expected in less than 24 hours. SAVE ALL DATA.\n"); QUIETOFF(con); - if (ataCheckSmart(smartval, smartthres,1)){ + if (ataCheckSmart(&smartval, &smartthres,1)){ returnval|=FAILATTR; if (con->smartvendorattrib) pout("See vendor-specific Attribute list for failed Attributes.\n\n"); else { QUIETON(con); pout("Failed Attributes:\n"); - PrintSmartAttribWithThres(smartval, smartthres,1); + PrintSmartAttribWithThres(&smartval, &smartthres,1); } } else @@ -872,13 +871,13 @@ int ataPrintMain (int fd){ } else { pout("SMART overall-health self-assessment test result: PASSED\n"); - if (ataCheckSmart(smartval, smartthres,0)){ + if (ataCheckSmart(&smartval, &smartthres,0)){ if (con->smartvendorattrib) pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); else { QUIETON(con); pout("Please note the following marginal attributes:\n"); - PrintSmartAttribWithThres(smartval, smartthres,2); + PrintSmartAttribWithThres(&smartval, &smartthres,2); } returnval|=FAILAGE; } @@ -890,18 +889,18 @@ int ataPrintMain (int fd){ // Print general SMART values if (con->generalsmartvalues) - ataPrintGeneralSmartValues(smartval); + ataPrintGeneralSmartValues(&smartval); // Print vendor-specific attributes if (con->smartvendorattrib){ QUIETON(con); - PrintSmartAttribWithThres(smartval, smartthres,con->quietmode?2:0); + PrintSmartAttribWithThres(&smartval, &smartthres,con->quietmode?2:0); QUIETOFF(con); } // Print SMART error log if (con->smarterrorlog){ - if (!isSmartErrorLogCapable(smartval)) + if (!isSmartErrorLogCapable(&smartval)) pout("Warning: device does not support Error Logging\n"); if (ataReadErrorLog(fd, &smarterror)){ pout("Smartctl: SMART Errorlog Read Failed\n"); @@ -909,14 +908,14 @@ int ataPrintMain (int fd){ } else { // turn on quiet mode inside this - ataPrintSmartErrorlog(smarterror); + ataPrintSmartErrorlog(&smarterror); QUIETOFF(con); } } // Print SMART self-test log if (con->smartselftestlog){ - if (!isSmartErrorLogCapable(smartval)) + if (!isSmartErrorLogCapable(&smartval)) pout("Warning: device does not support Self Test Logging\n"); else { if(ataReadSelfTestLog(fd, &smartselftest)){ @@ -925,7 +924,7 @@ int ataPrintMain (int fd){ } else { QUIETON(con); - if (ataPrintSmartSelfTestlog(smartselftest,!con->quietmode)) + if (ataPrintSmartSelfTestlog(&smartselftest,!con->quietmode)) returnval|=FAILLOG; QUIETOFF(con); pout("\n"); @@ -939,9 +938,9 @@ int ataPrintMain (int fd){ pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n"); // if doing a self-test, be sure it's supported by the hardware - if (con->testcase==OFFLINE_FULL_SCAN && !isSupportExecuteOfflineImmediate(smartval)) + if (con->testcase==OFFLINE_FULL_SCAN && !isSupportExecuteOfflineImmediate(&smartval)) pout("Warning: device does not support Execute Off-Line Immediate function.\n\n"); - else if (!isSupportSelfTest(smartval)) + else if (!isSupportSelfTest(&smartval)) pout("Warning: device does not support Self-Test functions.\n\n"); // Now do the test @@ -949,7 +948,7 @@ int ataPrintMain (int fd){ return returnval|=FAILSMART; // Tell user how long test will take to complete - if ((timewait=TestTime(smartval,con->testcase))){ + if ((timewait=TestTime(&smartval,con->testcase))){ pout("Please wait %d %s for test to complete.\n", (int)timewait, con->testcase==OFFLINE_FULL_SCAN?"seconds":"minutes"); diff --git a/sm5/ataprint.h b/sm5/ataprint.h index 8bff3e5116a9152aaaa07824ca290d6d96392c59..993537101a617c3a344abacc1c3ce4cba878e229 100644 --- a/sm5/ataprint.h +++ b/sm5/ataprint.h @@ -26,7 +26,7 @@ #define _SMART_PRINT_H_ #ifndef CVSID2 -#define CVSID2 "$Id: ataprint.h,v 1.13 2002/10/28 23:46:59 ballen4705 Exp $\n" +#define CVSID2 "$Id: ataprint.h,v 1.14 2002/10/30 10:18:37 ballen4705 Exp $\n" #endif #include <stdio.h> @@ -40,24 +40,24 @@ /* Prints ATA Drive Information and S.M.A.R.T. Capability */ -void ataPrintDriveInfo(struct hd_driveid); +void ataPrintDriveInfo(struct hd_driveid *); -void ataPrintGeneralSmartValues(struct ata_smart_values); +void ataPrintGeneralSmartValues(struct ata_smart_values *); -void ataPrintSmartThresholds(struct ata_smart_thresholds); +void ataPrintSmartThresholds(struct ata_smart_thresholds *); -void ataPrintSmartErrorlog(struct ata_smart_errorlog); +void ataPrintSmartErrorlog(struct ata_smart_errorlog *); -void PrintSmartAttributes(struct ata_smart_values data); +void PrintSmartAttributes(struct ata_smart_values *data); -void PrintSmartAttribWithThres(struct ata_smart_values data, - struct ata_smart_thresholds thresholds, +void PrintSmartAttribWithThres(struct ata_smart_values *data, + struct ata_smart_thresholds *thresholds, int onlyfailed); // returns number of entries that had logged errors -int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog data, int allentries); +int ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *data, int allentries); -void ataPseudoCheckSmart(struct ata_smart_values, struct ata_smart_thresholds ); +void ataPseudoCheckSmart(struct ata_smart_values *, struct ata_smart_thresholds *); diff --git a/sm5/smartd.8 b/sm5/smartd.8 index 2efe776544498adeccfe0dd55ddba04126cf3ed3..9883d13b6e88d81790e4cbd9160cafcc7c70247d 100644 --- a/sm5/smartd.8 +++ b/sm5/smartd.8 @@ -13,7 +13,7 @@ \# at the Concurrent Systems Laboratory (now part of the Storage Systems \# Research Center), Jack Baskin School of Engineering, University of \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ -.TH SMARTD 8 "$Date: 2002/10/29 16:59:02 $" "smartmontools-5.0" +.TH SMARTD 8 "$Date: 2002/10/30 10:18:37 $" "smartmontools-5.0" .SH NAME smartd \- S.M.A.R.T. Daemon .SH SYNOPSIS @@ -256,6 +256,17 @@ 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. .TP +.B \-C <N> +This sets the time in between disk checks to be +.B <N> +seconds apart. Note that although you can give this Directive +multiple times on different lines of the configuration file, only the +final value that is given has an effect, and applies to all the disks. +The default value of +.B <N> +is 1800 sec, and the minimum allowed value is +ten seconds. +.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 @@ -302,7 +313,7 @@ its value since the last check, 30 min ago. .TP .B \-u Usage: Report anytime that a usage attribute has changed its value -since the last check, 30 min ago. +since the last check, N seconds ago. .TP .B \-t Track: Equivalent to turning on the two previous flags '\-t' and '\-u'. @@ -310,21 +321,21 @@ Tracks changes in .I all device attributes. .TP -.B \-i INT +.B \-i <ID> Ignore: This Directive modifies the behavior of the '\-f' attribute and has no effect without it. -.I This Directive takes a decimal integer argument INT in the range from 1 to 255. -It means to ignore device attribute number INT, when checking for +.I This Directive takes a decimal integer argument <ID> in the range from 1 to 255. +It means to ignore device attribute number <ID>, when checking for failure of usage attributes. This is useful, for example, if you have a very old disk and don't want to keep getting messages about the hours-on-lifetime attribute (usually attribute 9) failing. .TP -.B \-I INT +.B \-I <ID> Ignore: This Directive modifies the behavior of the '\-p', '\-u', and '\-t' attributes and has no effect without one of them. -.I This Directive takes a decimal integer argument INT in the range from 1 to 255. -It means to ignore device attribute INT, when tracking changes in the +.I This Directive takes a decimal integer argument <ID> in the range from 1 to 255. +It means to ignore device attribute <ID>, when tracking changes in the attribute values. This is useful, for example, if one of the device attributes is the disk temperature (usually attribute 194 or 231). It's annoying to get reports each time the temperature changes. @@ -466,4 +477,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.16 2002/10/29 16:59:02 ballen4705 Exp $ +$Id: smartd.8,v 1.17 2002/10/30 10:18:37 ballen4705 Exp $ diff --git a/sm5/smartd.c b/sm5/smartd.c index fcce22da6ba95862b61f78366799c522bb3db04e..fa567bf051beafd80f533f8b6ab46d1a9191a344 100644 --- a/sm5/smartd.c +++ b/sm5/smartd.c @@ -44,7 +44,7 @@ // CVS ID strings extern const char *CVSid1, *CVSid2; -const char *CVSid6="$Id: smartd.c,v 1.46 2002/10/30 06:02:40 ballen4705 Exp $" +const char *CVSid6="$Id: smartd.c,v 1.47 2002/10/30 10:18:37 ballen4705 Exp $" CVSID1 CVSID2 CVSID3 CVSID4 CVSID7; // global variable used for control of printing, passing arguments, etc. @@ -173,6 +173,7 @@ void Directives() { printout(LOG_INFO,"Configuration file Directives (following device name):\n"); printout(LOG_INFO," -A Device is an ATA device\n"); 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," -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"); @@ -251,7 +252,7 @@ int selftesterrorcount(int fd, char *name){ } // return current number of self-test errors - return ataPrintSmartSelfTestlog(log,0); + return ataPrintSmartSelfTestlog(&log,0); } @@ -274,7 +275,7 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){ // Get drive identity structure // May want to add options to enable autosave, automatic online testing - if (ataReadHDIdentity (fd,&drive) || !ataSmartSupport(drive) || ataEnableSmart(fd)){ + if (ataReadHDIdentity (fd,&drive) || !ataSmartSupport(&drive) || ataEnableSmart(fd)){ // device exists, but not able to do SMART printout(LOG_INFO,"Device: %s, not SMART capable, or couldn't enable SMART\n",device); close(fd); @@ -530,7 +531,7 @@ int ataCheckDevice(atadevices_t *drive){ struct ata_smart_values curval; struct ata_smart_thresholds *thresh=drive->smartthres; - // Read current attribute values. *drive contains old values adn thresholds + // Read current attribute values. *drive contains old values and thresholds if (ataReadSmartValues(fd,&curval)) printout(LOG_CRIT, "Device: %s, failed to read SMART Attribute Data\n", name); else { @@ -559,11 +560,16 @@ int ataCheckDevice(atadevices_t *drive){ // This block tracks usage or prefailure attributes to see if they are changing if ((cfg->usage || cfg->prefail) && ((att=ataCompareSmartValues2(&curval, drive->smartval, thresh, i, name)))){ + + // I should probably clean this up by defining a union to + // with one int=four unsigned chars to do this. const int mask=0xff; - int prefail=(att>>24) & mask; - int id =(att>>16) & mask; - int oldval =(att>>8) & mask; int newval =(att>>0) & mask; + int oldval =(att>>8) & mask; + int id =(att>>16) & mask; + int prefail=(att>>24) & mask; + + // for printing attribute name char attname[64],*loc=attname; // are we tracking this attribute? @@ -587,7 +593,7 @@ int ataCheckDevice(atadevices_t *drive){ } // end of loop over attributes // Save the new values into *drive for the next time around - memcpy(drive->smartval,&curval,sizeof(curval)); + *drive->smartval=curval; } } @@ -760,10 +766,11 @@ int parsetoken(char *token,cfgfile *cfg){ cfg->selftest=1; cfg->errorlog=1; break; - case 'i': - case 'I': + case 'i': // ignore + case 'I': // ignore + case 'C': // period (time interval) for checking // ignore a particular vendor attribute for tracking (i) or - // failure (I) + // failure (I). Or give a check interval for sleeping. arg=strtok(NULL,delim); // make sure argument is there if (!arg) { @@ -775,21 +782,34 @@ int parsetoken(char *token,cfgfile *cfg){ // get argument value, check that it's properly-formed, an // integer, and in-range val=strtol(arg,&endptr,10); - if (*endptr!='\0' || val<=0 || val>255) { - printout(LOG_CRIT,"Drive %s Directive: %s at line %d of file %s has argument: %s, needs 0 < n < 256\n", - name,token,lineno,CONFIGFILE,arg); - Directives(); - exit(1); + switch (sym) { + case 'C': + if (*endptr!='\0' || val<10) { + printout(LOG_CRIT,"Drive %s Directive: %s, line %d, file %s, has argument: %s, mimimum is ten secoonds\n", + name,token,lineno,CONFIGFILE,arg); + Directives(); + exit(1); + } + checktime=val; + return 1; + case 'i': + case 'I': + if (*endptr!='\0' || val<=0 || val>255 ) { + printout(LOG_CRIT,"Drive %s Directive: %s, line %d, file %s, has argument: %s, needs 0 < n < 256\n", + name,token,lineno,CONFIGFILE,arg); + Directives(); + exit(1); + } + // put into correct list (bitmaps, access only with isattoff() + // function. Turns OFF corresponding attribute. + if (sym=='I') + isattoff(val,cfg->trackatt,1); + else + isattoff(val,cfg->failatt,1); + return 1; } - // put into correct list (bitmaps, access only with isattoff() - // function. Turns OFF corresponding attribute. - if (sym=='I') - isattoff(val,cfg->trackatt,1); - else - isattoff(val,cfg->failatt,1); - break; default: - printout(LOG_CRIT,"Drive: %s, unknown option: %s at line %d of file %s\n", + printout(LOG_CRIT,"Drive: %s, unknown Directive: %s at line %d of file %s\n", name,token,lineno,CONFIGFILE); Directives(); exit(1); diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp index d86b3440a3461897a167c28d8d44e25b87490e5f..899a1a68760d0200c9fd12a6ff5f3bda7ffc22da 100644 --- a/sm5/smartd.cpp +++ b/sm5/smartd.cpp @@ -44,7 +44,7 @@ // CVS ID strings extern const char *CVSid1, *CVSid2; -const char *CVSid6="$Id: smartd.cpp,v 1.46 2002/10/30 06:02:40 ballen4705 Exp $" +const char *CVSid6="$Id: smartd.cpp,v 1.47 2002/10/30 10:18:37 ballen4705 Exp $" CVSID1 CVSID2 CVSID3 CVSID4 CVSID7; // global variable used for control of printing, passing arguments, etc. @@ -173,6 +173,7 @@ void Directives() { printout(LOG_INFO,"Configuration file Directives (following device name):\n"); printout(LOG_INFO," -A Device is an ATA device\n"); 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," -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"); @@ -251,7 +252,7 @@ int selftesterrorcount(int fd, char *name){ } // return current number of self-test errors - return ataPrintSmartSelfTestlog(log,0); + return ataPrintSmartSelfTestlog(&log,0); } @@ -274,7 +275,7 @@ int atadevicescan2(atadevices_t *devices, cfgfile *cfg){ // Get drive identity structure // May want to add options to enable autosave, automatic online testing - if (ataReadHDIdentity (fd,&drive) || !ataSmartSupport(drive) || ataEnableSmart(fd)){ + if (ataReadHDIdentity (fd,&drive) || !ataSmartSupport(&drive) || ataEnableSmart(fd)){ // device exists, but not able to do SMART printout(LOG_INFO,"Device: %s, not SMART capable, or couldn't enable SMART\n",device); close(fd); @@ -530,7 +531,7 @@ int ataCheckDevice(atadevices_t *drive){ struct ata_smart_values curval; struct ata_smart_thresholds *thresh=drive->smartthres; - // Read current attribute values. *drive contains old values adn thresholds + // Read current attribute values. *drive contains old values and thresholds if (ataReadSmartValues(fd,&curval)) printout(LOG_CRIT, "Device: %s, failed to read SMART Attribute Data\n", name); else { @@ -559,11 +560,16 @@ int ataCheckDevice(atadevices_t *drive){ // This block tracks usage or prefailure attributes to see if they are changing if ((cfg->usage || cfg->prefail) && ((att=ataCompareSmartValues2(&curval, drive->smartval, thresh, i, name)))){ + + // I should probably clean this up by defining a union to + // with one int=four unsigned chars to do this. const int mask=0xff; - int prefail=(att>>24) & mask; - int id =(att>>16) & mask; - int oldval =(att>>8) & mask; int newval =(att>>0) & mask; + int oldval =(att>>8) & mask; + int id =(att>>16) & mask; + int prefail=(att>>24) & mask; + + // for printing attribute name char attname[64],*loc=attname; // are we tracking this attribute? @@ -587,7 +593,7 @@ int ataCheckDevice(atadevices_t *drive){ } // end of loop over attributes // Save the new values into *drive for the next time around - memcpy(drive->smartval,&curval,sizeof(curval)); + *drive->smartval=curval; } } @@ -760,10 +766,11 @@ int parsetoken(char *token,cfgfile *cfg){ cfg->selftest=1; cfg->errorlog=1; break; - case 'i': - case 'I': + case 'i': // ignore + case 'I': // ignore + case 'C': // period (time interval) for checking // ignore a particular vendor attribute for tracking (i) or - // failure (I) + // failure (I). Or give a check interval for sleeping. arg=strtok(NULL,delim); // make sure argument is there if (!arg) { @@ -775,21 +782,34 @@ int parsetoken(char *token,cfgfile *cfg){ // get argument value, check that it's properly-formed, an // integer, and in-range val=strtol(arg,&endptr,10); - if (*endptr!='\0' || val<=0 || val>255) { - printout(LOG_CRIT,"Drive %s Directive: %s at line %d of file %s has argument: %s, needs 0 < n < 256\n", - name,token,lineno,CONFIGFILE,arg); - Directives(); - exit(1); + switch (sym) { + case 'C': + if (*endptr!='\0' || val<10) { + printout(LOG_CRIT,"Drive %s Directive: %s, line %d, file %s, has argument: %s, mimimum is ten secoonds\n", + name,token,lineno,CONFIGFILE,arg); + Directives(); + exit(1); + } + checktime=val; + return 1; + case 'i': + case 'I': + if (*endptr!='\0' || val<=0 || val>255 ) { + printout(LOG_CRIT,"Drive %s Directive: %s, line %d, file %s, has argument: %s, needs 0 < n < 256\n", + name,token,lineno,CONFIGFILE,arg); + Directives(); + exit(1); + } + // put into correct list (bitmaps, access only with isattoff() + // function. Turns OFF corresponding attribute. + if (sym=='I') + isattoff(val,cfg->trackatt,1); + else + isattoff(val,cfg->failatt,1); + return 1; } - // put into correct list (bitmaps, access only with isattoff() - // function. Turns OFF corresponding attribute. - if (sym=='I') - isattoff(val,cfg->trackatt,1); - else - isattoff(val,cfg->failatt,1); - break; default: - printout(LOG_CRIT,"Drive: %s, unknown option: %s at line %d of file %s\n", + printout(LOG_CRIT,"Drive: %s, unknown Directive: %s at line %d of file %s\n", name,token,lineno,CONFIGFILE); Directives(); exit(1); diff --git a/sm5/smartmontools.spec b/sm5/smartmontools.spec index 7a928dabe1241eaa5d811969f650f52ea13cbb8f..607f193051f9e68803da2e170ee18edf76eb301b 100644 --- a/sm5/smartmontools.spec +++ b/sm5/smartmontools.spec @@ -1,4 +1,4 @@ -Release: 23 +Release: 24 Summary: SMARTmontools - for monitoring S.M.A.R.T. disks and devices Name: smartmontools Version: 5.0 @@ -18,7 +18,7 @@ Packager: Bruce Allen <smartmontools-support@lists.sourceforge.net> # http://telia.dl.sourceforge.net/sourceforge/smartmontools/smartmontools-%{version}-%{release}.tar.gz # CVS ID of this file is: -# $Id: smartmontools.spec,v 1.34 2002/10/30 06:02:40 ballen4705 Exp $ +# $Id: smartmontools.spec,v 1.35 2002/10/30 10:18:37 ballen4705 Exp $ # Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> # Home page: http://smartmontools.sourceforge.net @@ -112,7 +112,24 @@ fi %define date %(echo `LC_ALL="C" date +"%a %b %d %Y"`) %changelog + * Wed Oct 29 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> + Added new Directive for Configuration file: +-C <N> This sets the time in between disk checks to be <N> + seconds apart. Note that although you can give + this Directive multiple times on different lines of + the configuration file, only the final value that + is given has an effect, and applies to all the + disks. The default value of <N> is 1800 sec, and + the minimum allowed value is ten seconds. +- Problem wasn't the print format. F.L.W. Meunier <0@pervalidus.net> + sent me a gcc 3.2 build and I ran it under a debugger. The + problem seems to be with passing the very large (2x512+4) byte + data structures as arguments. I never liked this anyway; it was + inherited from smartsuite. So I've changed all the heavyweight + functions (ATA ones, anyone) to just passing pointers, not hideous + kB size structures on the stack. Hopefully this will now build OK + under gcc 3.2 with any sensible compilation options. - Because of reported problems with GCC 3.2 compile, I have gone thorough the code and explicitly changed all print format parameters to correspond EXACTLY to int unless they have to be @@ -123,7 +140,6 @@ fi values. This means the objects of type char or short int (whether signed or not) are promoted to either int or unsigned int, as required. -* Wed Oct 29 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> - smartd, smartctl now warn if they find an attribute whose ID number does not match between Data and Threshold structures. - Fixed nasty bug which led to wrong number of arguments for a