diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 992580e6d0e12f7e6bb49b6bf569486d2e3cf482..a443d48668aa9735dfbfbfa3448065965afd2d5b 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.750 2008/11/02 01:33:26 manfred99 Exp $ +$Id: CHANGELOG,v 1.751 2008/11/04 19:28:42 chrfranke Exp $ The most recent version of this file is: http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup @@ -40,6 +40,9 @@ NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [CF] Add smartd '-n powermode,N' directive parameter to limit the + number of skipped checks. Thanks to Michal Hlavinka for the patch. + [MS] knowndrives.cpp updates: - Added Hitachi Endurastar J4K30/N4K30 - Added Hitachi Travelstar 4K120 series diff --git a/sm5/smartd.8.in b/sm5/smartd.8.in index bd2161b73b9466815120bfcbce210901d7f4677f..c84f505a18b6b86669a476b4108177a634b54581 100644 --- a/sm5/smartd.8.in +++ b/sm5/smartd.8.in @@ -1,7 +1,7 @@ .ig Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net> -$Id: smartd.8.in,v 1.132 2008/10/13 19:45:19 chrfranke Exp $ +$Id: smartd.8.in,v 1.133 2008/11/04 19:28:42 chrfranke Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -824,7 +824,7 @@ behavior) if the device does not appear to be present when with the other \'\-d\' Directives. .TP -.B \-n POWERMODE[,q] +.B \-n POWERMODE[,N][,q] This \'nocheck\' Directive is used to prevent a disk from being spun-up when it is periodically polled by \fBsmartd\fP. @@ -872,11 +872,18 @@ not what you want. When a self test is scheduled (see \'\-s\' Directive below), the \'\fB\-n\fP\' Directive is ignored, and all tests are carried out. +Maximum number of skipped checks (in a row) can be specified by +appending positive number \',N\' to POWERMODE (like \'\-n standby,15\'). +After N checks are skipped in a row, powermode is ignored and the +check is performed anyway. + When a periodic test is skipped, \fBsmartd\fP normally writes an informal log message. The message can be suppressed by appending the option \',q\' to POWERMODE (like \'\-n standby,q\'). This prevents a laptop disk from spinning up due to this message. +Both \',N\' and \',q\' can be specified together. + .TP .B \-T TYPE Specifies how tolerant @@ -2080,4 +2087,4 @@ smartmontools home page at \fBhttp://smartmontools.sourceforge.net/#references\f .SH CVS ID OF THIS PAGE: -$Id: smartd.8.in,v 1.132 2008/10/13 19:45:19 chrfranke Exp $ +$Id: smartd.8.in,v 1.133 2008/11/04 19:28:42 chrfranke Exp $ diff --git a/sm5/smartd.conf.5.in b/sm5/smartd.conf.5.in index 4c2a4c1d2f8220c7c1766775b293c7101257164a..3ca9e855201ff56588483c07f039bdb8003964a9 100644 --- a/sm5/smartd.conf.5.in +++ b/sm5/smartd.conf.5.in @@ -1,7 +1,7 @@ .ig Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net> -$Id: smartd.conf.5.in,v 1.96 2008/10/11 14:18:07 chrfranke Exp $ +$Id: smartd.conf.5.in,v 1.97 2008/11/04 19:28:42 chrfranke Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -409,7 +409,7 @@ behavior) if the device does not appear to be present when with the other \'\-d\' Directives. .TP -.B \-n POWERMODE[,q] +.B \-n POWERMODE[,N][,q] This \'nocheck\' Directive is used to prevent a disk from being spun-up when it is periodically polled by \fBsmartd\fP. @@ -457,11 +457,18 @@ not what you want. When a self test is scheduled (see \'\-s\' Directive below), the \'\fB\-n\fP\' Directive is ignored, and all tests are carried out. +Maximum number of skipped checks (in a row) can be specified by +appending positive number \',N\' to POWERMODE (like \'\-n standby,15\'). +After N checks are skipped in a row, powermode is ignored and the +check is performed anyway. + When a periodic test is skipped, \fBsmartd\fP normally writes an informal log message. The message can be suppressed by appending the option \',q\' to POWERMODE (like \'\-n standby,q\'). This prevents a laptop disk from spinning up due to this message. +Both \',N\' and \',q\' can be specified together. + .TP .B \-T TYPE Specifies how tolerant @@ -1435,4 +1442,4 @@ SEE ALSO: .SH CVS ID OF THIS PAGE: -$Id: smartd.conf.5.in,v 1.96 2008/10/11 14:18:07 chrfranke Exp $ +$Id: smartd.conf.5.in,v 1.97 2008/11/04 19:28:42 chrfranke Exp $ diff --git a/sm5/smartd.cpp b/sm5/smartd.cpp index bd7559ddba7878e3e65677971d4fa8fc3cbc9fd1..e6fcad821bdb16a28fbae6837766997428c38987 100644 --- a/sm5/smartd.cpp +++ b/sm5/smartd.cpp @@ -138,7 +138,7 @@ extern const char *os_solaris_ata_s_cvsid; #ifdef _WIN32 extern const char *daemon_win32_c_cvsid, *hostname_win32_c_cvsid, *syslog_win32_c_cvsid; #endif -const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.432 2008/10/24 19:51:54 chrfranke Exp $" +const char *smartd_c_cvsid="$Id: smartd.cpp,v 1.433 2008/11/04 19:28:42 chrfranke Exp $" ATACMDS_H_CVSID CONFIG_H_CVSID #ifdef DAEMON_WIN32_H_CVSID DAEMON_WIN32_H_CVSID @@ -268,6 +268,7 @@ struct dev_config bool removable; // Device may disappear (not be present) char powermode; // skip check, if disk in idle or standby mode bool powerquiet; // skip powermode 'skipping checks' message + int powerskipmax; // how many times can be check skipped unsigned char tempdiff; // Track Temperature changes >= this limit unsigned char tempinfo, tempcrit; // Track Temperatures >= these limits as LOG_INFO, LOG_CRIT+mail regular_expression test_regex; // Regex for scheduled testing @@ -314,6 +315,7 @@ dev_config::dev_config() removable(false), powermode(0), powerquiet(false), + powerskipmax(0), tempdiff(0), tempinfo(0), tempcrit(0), pending(0), @@ -1424,7 +1426,7 @@ void Directives() { " -T TYPE Set the tolerance to one of: normal, permissive\n" " -o VAL Enable/disable automatic offline tests (on/off)\n" " -S VAL Enable/disable attribute autosave (on/off)\n" - " -n MODE No check if: never[,q], sleep[,q], standby[,q], idle[,q]\n" + " -n MODE No check if: never, sleep[,N][,q], standby[,N][,q], idle[,N][,q]\n" " -H Monitor SMART Health Status, report if failed\n" " -s REG Do Self-Test at time(s) given by regular expression REG\n" " -l TYPE Monitor SMART log. Type is one of: error, selftest\n" @@ -2626,14 +2628,21 @@ static int ATACheckDevice(const dev_config & cfg, dev_state & state, ata_device if (dontcheck){ // but ignore powermode on scheduled selftest if (!testtype) { - CloseDevice(atadev, name); - if (!state.powerskipcnt && !cfg.powerquiet) // report first only and avoid waking up system disk - PrintOut(LOG_INFO, "Device: %s, is in %s mode, suspending checks\n", name, mode); - state.powerskipcnt++; - return 0; + // skip at most powerskipmax checks + if (!cfg.powerskipmax || state.powerskipcnt<cfg.powerskipmax) { + CloseDevice(atadev, name); + if (!state.powerskipcnt && !cfg.powerquiet) // report first only and avoid waking up system disk + PrintOut(LOG_INFO, "Device: %s, is in %s mode, suspending checks\n", name, mode); + state.powerskipcnt++; + return 0; + } else { + PrintOut(LOG_INFO, "Device: %s, %s mode ignored due to reached limit of skipped checks (%d check%s skipped)\n", + name, mode, state.powerskipcnt, (state.powerskipcnt==1?"":"s")); + } + } else { + PrintOut(LOG_INFO, "Device: %s, %s mode ignored due to scheduled self test (%d check%s skipped)\n", + name, mode, state.powerskipcnt, (state.powerskipcnt==1?"":"s")); } - PrintOut(LOG_INFO, "Device: %s, %s mode ignored due to scheduled self test (%d check%s skipped)\n", - name, mode, state.powerskipcnt, (state.powerskipcnt==1?"":"s")); state.powerskipcnt = 0; state.tempmin_delay = time(0) + CHECKTIME - 60; // Delay Min Temperature update } @@ -3019,7 +3028,7 @@ void printoutvaliddirectiveargs(int priority, char d) { switch (d) { case 'n': - PrintOut(priority, "never[,q], sleep[,q], standby[,q], idle[,q]"); + PrintOut(priority, "never[,N][,q], sleep[,N][,q], standby[,N][,q], idle[,N][,q]"); break; case 's': PrintOut(priority, "valid_regular_expression"); @@ -3264,17 +3273,45 @@ static int ParseToken(char * token, dev_config & cfg) // skip disk check if in idle or standby mode if (!(arg = strtok(NULL, delim))) missingarg = 1; - else if (!strcmp(arg, "never") || !strcmp(arg, "never,q")) - cfg.powermode = 0; - else if (!strcmp(arg, "sleep") || !strcmp(arg, "sleep,q")) - cfg.powermode = 1; - else if (!strcmp(arg, "standby") || !strcmp(arg, "standby,q")) - cfg.powermode = 2; - else if (!strcmp(arg, "idle") || !strcmp(arg, "idle,q")) - cfg.powermode = 3; - else - badarg = 1; - cfg.powerquiet = !!strchr(arg, ','); + else { + char *endptr = NULL; + char *next = index(arg,','); + + cfg.powerquiet = false; + cfg.powerskipmax = 0; + + if (next!=NULL) *next='\0'; + if (!strcmp(arg, "never")) + cfg.powermode = 0; + else if (!strcmp(arg, "sleep")) + cfg.powermode = 1; + else if (!strcmp(arg, "standby")) + cfg.powermode = 2; + else if (!strcmp(arg, "idle")) + cfg.powermode = 3; + else + badarg = 1; + + // if optional arguments are present + if (!badarg && next!=NULL) { + next++; + cfg.powerskipmax = strtol(next, &endptr, 10); + if (endptr == next) + cfg.powerskipmax = 0; + else { + next = endptr + (*endptr != '\0'); + if (cfg.powerskipmax <= 0) + badarg = 1; + } + if (*next != '\0') { + if (!strcmp("q", next)) + cfg.powerquiet = true; + else { + badarg = 1; + } + } + } + } break; case 'S': // automatic attribute autosave enable/disable