]>
Commit | Line | Data |
---|---|---|
832b75ed GG |
1 | /* |
2 | * smartd.h | |
3 | * | |
4 | * Home page of code is: http://smartmontools.sourceforge.net | |
5 | * | |
6 | * Copyright (C) 2002-6 Bruce Allen <smartmontools-support@lists.sourceforge.net> | |
7 | * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2, or (at your option) | |
12 | * any later version. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * (for example COPYING); if not, write to the Free | |
16 | * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
17 | * | |
18 | * This code was originally developed as a Senior Thesis by Michael Cornwell | |
19 | * at the Concurrent Systems Laboratory (now part of the Storage Systems | |
20 | * Research Center), Jack Baskin School of Engineering, University of | |
21 | * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ | |
22 | * | |
23 | */ | |
24 | ||
25 | #ifndef SMARTD_H_ | |
26 | #define SMARTD_H_ | |
27 | ||
28 | // Needed since some structure definitions below require POSIX | |
29 | // extended regular expressions. | |
30 | #include <sys/types.h> | |
31 | #include <regex.h> | |
32 | ||
33 | ||
34 | #ifndef SMARTD_H_CVSID | |
ba59cff1 | 35 | #define SMARTD_H_CVSID "$Id: smartd.h,v 1.84 2006/11/11 17:50:50 ballen4705 Exp $\n" |
832b75ed GG |
36 | #endif |
37 | ||
38 | // Configuration file | |
39 | #define CONFIGFILENAME "smartd.conf" | |
40 | ||
41 | // Scan directive for configuration file | |
42 | #define SCANDIRECTIVE "DEVICESCAN" | |
43 | ||
44 | // maximum line length in configuration file | |
ba59cff1 | 45 | #define MAXLINELEN 256 |
832b75ed GG |
46 | |
47 | // maximum length of a continued line in configuration file | |
48 | #define MAXCONTLINE 1023 | |
49 | ||
50 | // default for how often SMART status is checked, in seconds | |
51 | #define CHECKTIME 1800 | |
52 | ||
53 | /* Boolean Values */ | |
54 | #define TRUE 0x01 | |
55 | #define FALSE 0x00 | |
56 | ||
57 | // Number of monitoring flags per Attribute and offsets. See | |
58 | // monitorattflags below. | |
59 | #define NMONITOR 4 | |
60 | #define MONITOR_FAILUSE 0 | |
61 | #define MONITOR_IGNORE 1 | |
62 | #define MONITOR_RAWPRINT 2 | |
63 | #define MONITOR_RAW 3 | |
64 | ||
65 | ||
66 | // Number of allowed mail message types | |
4d59bff9 | 67 | #define SMARTD_NMAIL 13 |
832b75ed GG |
68 | |
69 | typedef struct mailinfo_s { | |
70 | int logged;// number of times an email has been sent | |
71 | time_t firstsent;// time first email was sent, as defined by time(2) | |
72 | time_t lastsent; // time last email was sent, as defined by time(2) | |
73 | } mailinfo; | |
74 | ||
75 | // If user has requested email warning messages, then this structure | |
76 | // stores the information about them, and track type/date of email | |
77 | // messages. | |
78 | typedef struct maildata_s { | |
79 | mailinfo maillog[SMARTD_NMAIL]; // log info on when mail sent | |
80 | char *emailcmdline; // script to execute | |
81 | char *address; // email address, or null | |
82 | unsigned char emailfreq; // Emails once (1) daily (2) diminishing (3) | |
83 | unsigned char emailtest; // Send test email? | |
84 | } maildata; | |
85 | ||
86 | // If user has requested automatic testing, then this structure stores | |
87 | // their regular expression pattern, the compiled form of that regex, | |
88 | // and information about the disk capabilities and when the last text | |
89 | // took place | |
90 | ||
91 | typedef struct testinfo_s { | |
92 | char *regex; // text form of regex | |
93 | regex_t cregex; // compiled form of regex | |
94 | unsigned short hour; // 1+hour of year when last scheduled self-test done | |
95 | char testtype; // type of test done at hour indicated just above | |
96 | signed char not_cap_offline; // 0==unknown OR capable of offline, 1==not capable | |
97 | signed char not_cap_conveyance; | |
98 | signed char not_cap_short; | |
99 | signed char not_cap_long; | |
100 | } testinfo; | |
101 | ||
102 | ||
103 | // cfgfile is the main data structure of smartd. It is used in two | |
104 | // ways. First, to store a list of devices/options given in the | |
105 | // configuration smartd.conf or constructed with DEVICESCAN. And | |
106 | // second, to point to or provide all persistent storage needed to | |
107 | // track a device, if registered either as SCSI or ATA. | |
108 | // | |
109 | // After parsing the config file, each valid entry has a cfgfile data | |
110 | // structure allocated in memory for it. In parsing the configuration | |
111 | // file, some storage space may be needed, of indeterminate length, | |
112 | // for example for the device name. When this happens, memory should | |
113 | // be allocated and then pointed to from within the corresponding | |
114 | // cfgfile structure. | |
115 | ||
116 | // After parsing the configuration file, each device is then checked | |
117 | // to see if it can be monitored (this process is called "registering | |
118 | // the device". This is done in [scsi|ata]devicescan, which is called | |
119 | // exactly once, after the configuration file has been parsed and | |
120 | // cfgfile data structures have been created for each of its entries. | |
121 | // | |
122 | // If a device can not be monitored, the memory for its cfgfile data | |
123 | // structure should be freed by calling rmconfigentry(cfgfile *). In | |
124 | // this case, we say that this device "was not registered". All | |
125 | // memory associated with that particular cfgfile structure is thus | |
126 | // freed. | |
127 | // | |
128 | // The remaining devices are polled in a timing look, where | |
129 | // [ata|scsi]CheckDevice looks at each entry in turn. | |
130 | // | |
131 | // If you want to add small amounts of "private" data on a per-device | |
132 | // basis, just make a new field in cfgfile. This is guaranteed zero | |
133 | // on startup (when ata|scsi]scsidevicescan(cfgfile *cfg) is first | |
134 | // called with a pointer to cfgfile. | |
135 | // | |
136 | // If you need *substantial* persistent data space for a device | |
137 | // (dozens or hundreds of bytes) please add a pointer field to | |
138 | // cfgfile. As before, this is guaranteed NULL when | |
139 | // ata|scsi]scsidevicescan(cfgfile *cfg) is called. Allocate space for | |
140 | // it in scsidevicescan or atadevicescan, if needed, and deallocate | |
141 | // the space in rmconfigentry(cfgfile *cfg). Be sure to make the | |
142 | // pointer NULL unless it points to an area of the heap that can be | |
143 | // deallocated with free(). In other words, a non-NULL pointer in | |
144 | // cfgfile means "this points to data space that should be freed if I | |
145 | // stop monitoring this device." If you don't need the space anymore, | |
146 | // please call free() and then SET THE POINTER IN cfgfile TO NULL. | |
147 | // | |
148 | // Note that we allocate one cfgfile structure per device. This is | |
149 | // why substantial persisent data storage should only be pointed to | |
150 | // from within cfgfile, not kept within cfgfile itself - it saves | |
151 | // memory for those devices that don't need that type of persistent | |
152 | // data. | |
153 | // | |
154 | // In general, the capabilities of devices should be checked at | |
155 | // registration time within atadevicescan() and scsidevicescan(), and | |
156 | // then noted within *cfg. So if device lacks some capability, this | |
157 | // should be visible within *cfg after returning from | |
158 | // [ata|scsi]devicescan. | |
159 | // | |
160 | // Devices are then checked, once per polling interval, within | |
161 | // ataCheckDevice() and scsiCheckDevice(). These should only check | |
162 | // the capabilities that devices already are known to have (as noted | |
163 | // within *cfg). | |
164 | ||
165 | typedef struct configfile_s { | |
166 | // FIRST SET OF ENTRIES CORRESPOND TO WHAT THE USER PUT IN THE | |
167 | // CONFIG FILE. SOME ENTRIES MAY BE MODIFIED WHEN A DEVICE IS | |
168 | // REGISTERED AND WE LEARN ITS CAPABILITIES. | |
169 | int lineno; // Line number of entry in file | |
170 | char *name; // Device name (+ optional [3ware_disk_XX]) | |
4d59bff9 GG |
171 | unsigned char controller_explicit; // Controller (device) type has been specified explicitly |
172 | unsigned char controller_type; // Controller type, ATA/SCSI/SAT/3Ware/(more to come) | |
832b75ed | 173 | unsigned char controller_port; // 1 + (disk number in controller). 0 means controller only handles one disk. |
4d59bff9 GG |
174 | unsigned char hpt_data[3]; // combined controller/channle/pmport for highpoint rocketraid controller |
175 | unsigned char satpassthrulen; // length of SAT ata pass through scsi commands (12, 16 or 0 (platform choice)) | |
832b75ed GG |
176 | char smartcheck; // Check SMART status |
177 | char usagefailed; // Check for failed Usage Attributes | |
178 | char prefail; // Track changes in Prefail Attributes | |
179 | char usage; // Track changes in Usage Attributes | |
180 | char selftest; // Monitor number of selftest errors | |
181 | char errorlog; // Monitor number of ATA errors | |
182 | char permissive; // Ignore failed SMART commands | |
183 | char autosave; // 1=disable, 2=enable Autosave Attributes | |
184 | char autoofflinetest; // 1=disable, 2=enable Auto Offline Test | |
185 | unsigned char fixfirmwarebug; // Fix firmware bug | |
186 | char ignorepresets; // Ignore database of -v options | |
187 | char showpresets; // Show database entry for this device | |
188 | char removable; // Device may disappear (not be present) | |
189 | char powermode; // skip check, if disk in idle or standby mode | |
190 | char powerquiet; // skip powermode 'skipping checks' message | |
4d59bff9 GG |
191 | unsigned char tempdiff; // Track Temperature changes >= this limit |
192 | unsigned char tempinfo, tempcrit; // Track Temperatures >= these limits as LOG_INFO, LOG_CRIT+mail | |
193 | unsigned char tempmin, tempmax; // Min/Max Temperatures | |
832b75ed GG |
194 | unsigned char selflogcount; // total number of self-test errors |
195 | unsigned short selfloghour; // lifetime hours of last self-test error | |
196 | testinfo *testdata; // Pointer to data on scheduled testing | |
197 | unsigned short pending; // lower 8 bits: ID of current pending sector count | |
198 | // upper 8 bits: ID of offline pending sector count | |
199 | ||
200 | // THE NEXT SET OF ENTRIES ALSO TRACK DEVICE STATE AND ARE DYNAMIC | |
201 | maildata *mailwarn; // non-NULL: info about sending mail or executing script | |
4d59bff9 GG |
202 | unsigned char temperature; // last recorded Temperature (in Celsius) |
203 | unsigned char tempmininc; // #checks where Min Temperature is increased after powerup | |
204 | int powerskipcnt; // Number of checks skipped due to idle or standby mode | |
832b75ed GG |
205 | |
206 | // SCSI ONLY | |
207 | unsigned char SmartPageSupported; // has log sense IE page (0x2f) | |
208 | unsigned char TempPageSupported; // has log sense temperature page (0xd) | |
832b75ed GG |
209 | unsigned char SuppressReport; // minimize nuisance reports |
210 | unsigned char modese_len; // mode sense/select cmd len: 0 (don't | |
211 | // know yet) 6 or 10 | |
212 | unsigned char notused2[3]; // for packing alignment | |
213 | ||
214 | // ATA ONLY FROM HERE ON TO THE END | |
215 | int ataerrorcount; // Total number of ATA errors | |
216 | ||
217 | // following NMONITOR items each point to 32 bytes, in the form of | |
218 | // 32x8=256 single bit flags | |
219 | // valid attribute numbers are from 1 <= x <= 255 | |
220 | // monitorattflags+0 set: ignore failure for a usage attribute | |
221 | // monitorattflats+32 set: don't track attribute | |
222 | // monitorattflags+64 set: print raw value when tracking | |
223 | // monitorattflags+96 set: track changes in raw value | |
224 | unsigned char *monitorattflags; | |
225 | ||
226 | // NULL UNLESS (1) STORAGE IS ALLOCATED WHEN CONFIG FILE SCANNED | |
227 | // (SET BY USER) or (2) IT IS SET WHEN DRIVE IS AUTOMATICALLY | |
228 | // RECOGNIZED IN DATABASE (WHEN DRIVE IS REGISTERED) | |
229 | unsigned char *attributedefs; // -v options, see end of extern.h for def | |
230 | ||
231 | // ATA ONLY - SAVE SMART DATA. NULL POINTERS UNLESS NEEDED. IF | |
232 | // NEEDED, ALLOCATED WHEN DEVICE REGISTERED. | |
233 | struct ata_smart_values *smartval; // Pointer to SMART data | |
234 | struct ata_smart_thresholds_pvt *smartthres; // Pointer to SMART thresholds | |
235 | ||
236 | } cfgfile; | |
237 | ||
238 | ||
239 | typedef struct changedattribute_s { | |
240 | unsigned char newval; | |
241 | unsigned char oldval; | |
242 | unsigned char id; | |
243 | unsigned char prefail; | |
244 | unsigned char sameraw; | |
245 | } changedattribute_t; | |
246 | ||
247 | // Declare our own printing functions. Doing this provides error | |
248 | // messages if the argument number/types don't match the format. | |
249 | #ifndef __GNUC__ | |
250 | #define __attribute__(x) /* nothing */ | |
251 | #endif | |
4d59bff9 | 252 | void PrintOut(int priority, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); |
832b75ed GG |
253 | |
254 | void PrintAndMail(cfgfile *cfg, int which, int priority, char *fmt, ...) __attribute__ ((format(printf, 4, 5))); | |
255 | ||
256 | /* Debugging notes: to check for memory allocation/deallocation problems, use: | |
257 | ||
258 | export LD_PRELOAD=libnjamd.so; | |
259 | export NJAMD_PROT=strict; | |
260 | export NJAMD_CHK_FREE=error; | |
261 | export NJAMD_DUMP_LEAKS_ON_EXIT=num; | |
262 | export NJAMD_DUMP_LEAKS_ON_EXIT=3; | |
263 | export NJAMD_TRACE_LIBS=1 | |
264 | ||
265 | */ | |
266 | ||
267 | // Number of seconds to allow for registering a SCSI device. If this | |
268 | // time expires without sucess or failure, then treat it as failure. | |
269 | // Set to 0 to eliminate this timeout feature from the code | |
270 | // (equivalent to an infinite timeout interval). | |
271 | #define SCSITIMEOUT 0 | |
272 | ||
273 | // This is for solaris, where signal() resets the handler to SIG_DFL | |
274 | // after the first signal is caught. | |
275 | #ifdef HAVE_SIGSET | |
276 | #define SIGNALFN sigset | |
277 | #else | |
278 | #define SIGNALFN signal | |
279 | #endif | |
280 | ||
281 | #endif | |
282 | ||
283 | #define SELFTEST_ERRORCOUNT(x) (x & 0xff) | |
284 | #define SELFTEST_ERRORHOURS(x) ((x >> 8) & 0xffff) | |
285 | ||
286 | // cfg->pending is a 16 bit unsigned quantity. If the least | |
287 | // significant 8 bits are zero, this means monitor Attribute | |
288 | // CUR_UNC_DEFAULT's raw value. If they are CUR_UNC_DEFAULT, this | |
289 | // means DON'T MONITOR. If the most significant 8 bits are zero, this | |
290 | // means monitor Attribute OFF_UNC_DEFAULT's raw value. If they are | |
291 | // OFF_UNC_DEFAULT, this means DON'T MONITOR. | |
292 | #define OFF_UNC_DEFAULT 198 | |
293 | #define CUR_UNC_DEFAULT 197 | |
294 | ||
295 | #define CURR_PEND(x) (x & 0xff) | |
296 | #define OFF_PEND(x) ((x >> 8) & 0xff) | |
297 | ||
298 | // if cfg->pending has this value, dont' monitor | |
299 | #define DONT_MONITOR_UNC (256*OFF_UNC_DEFAULT+CUR_UNC_DEFAULT) |