]>
Commit | Line | Data |
---|---|---|
dc01aad8 SS |
1 | --- |
2 | libmultipath/checkers.h | 15 +-------------- | |
3 | libmultipath/checkers/emc_clariion.c | 4 ++-- | |
4 | libmultipath/checkers/hp_sw.c | 12 ++++++------ | |
5 | libmultipath/checkers/libsg.c | 5 +++-- | |
6 | libmultipath/checkers/libsg.h | 3 ++- | |
7 | libmultipath/checkers/rdac.c | 9 +++++---- | |
8 | libmultipath/checkers/readsector0.c | 2 +- | |
9 | libmultipath/checkers/tur.c | 4 ++-- | |
10 | libmultipath/config.h | 1 + | |
11 | libmultipath/dict.c | 29 +++++++++++++++++++++++++++++ | |
12 | libmultipath/discovery.c | 27 +++++++++++++++++++++++++++ | |
13 | libmultipath/discovery.h | 1 + | |
14 | libmultipath/propsel.c | 19 +++++++++++++++++-- | |
15 | multipath.conf.annotated | 9 +++++++++ | |
16 | 14 files changed, 106 insertions(+), 34 deletions(-) | |
17 | ||
18 | Index: multipath-tools/libmultipath/checkers.h | |
19 | =================================================================== | |
20 | --- multipath-tools.orig/libmultipath/checkers.h | |
21 | +++ multipath-tools/libmultipath/checkers.h | |
22 | @@ -69,20 +69,6 @@ enum path_check_state { | |
23 | ||
24 | #define DEFAULT_CHECKER DIRECTIO | |
25 | ||
26 | -/* | |
27 | - * Overloaded storage response time can be very long. | |
28 | - * SG_IO timouts after DEF_TIMEOUT milliseconds, and checkers interprets this | |
29 | - * as a path failure. multipathd then proactively evicts the path from the DM | |
30 | - * multipath table in this case. | |
31 | - * | |
32 | - * This generaly snow balls and ends up in full eviction and IO errors for end | |
33 | - * users. Bad. This may also cause SCSI bus resets, causing disruption for all | |
34 | - * local and external storage hardware users. | |
35 | - * | |
36 | - * Provision a long timeout. Longer than any real-world application would cope | |
37 | - * with. | |
38 | - */ | |
39 | -#define DEF_TIMEOUT 300000 | |
40 | #define ASYNC_TIMEOUT_SEC 30 | |
41 | ||
42 | /* | |
43 | @@ -98,6 +84,7 @@ struct checker { | |
44 | struct list_head node; | |
45 | int fd; | |
46 | int sync; | |
47 | + unsigned int timeout; | |
48 | int disable; | |
49 | char name[CHECKER_NAME_LEN]; | |
50 | char message[CHECKER_MSG_LEN]; /* comm with callers */ | |
51 | Index: multipath-tools/libmultipath/checkers/emc_clariion.c | |
52 | =================================================================== | |
53 | --- multipath-tools.orig/libmultipath/checkers/emc_clariion.c | |
54 | +++ multipath-tools/libmultipath/checkers/emc_clariion.c | |
55 | @@ -113,7 +113,7 @@ int libcheck_check (struct checker * c) | |
56 | io_hdr.dxferp = sense_buffer; | |
57 | io_hdr.cmdp = inqCmdBlk; | |
58 | io_hdr.sbp = sb; | |
59 | - io_hdr.timeout = DEF_TIMEOUT; | |
60 | + io_hdr.timeout = c->timeout; | |
61 | io_hdr.pack_id = 0; | |
62 | if (ioctl(c->fd, SG_IO, &io_hdr) < 0) { | |
63 | MSG(c, "emc_clariion_checker: sending query command failed"); | |
64 | @@ -182,7 +182,7 @@ int libcheck_check (struct checker * c) | |
65 | unsigned char buf[4096]; | |
66 | ||
67 | memset(buf, 0, 4096); | |
68 | - ret = sg_read(c->fd, &buf[0], sbb = &sb[0]); | |
69 | + ret = sg_read(c->fd, &buf[0], sbb = &sb[0], c->timeout); | |
70 | if (ret == PATH_DOWN) { | |
71 | hexadecimal_to_ascii(ct->wwn, wwnstr); | |
72 | ||
73 | Index: multipath-tools/libmultipath/checkers/hp_sw.c | |
74 | =================================================================== | |
75 | --- multipath-tools.orig/libmultipath/checkers/hp_sw.c | |
76 | +++ multipath-tools/libmultipath/checkers/hp_sw.c | |
77 | @@ -46,7 +46,7 @@ void libcheck_free (struct checker * c) | |
78 | ||
79 | static int | |
80 | do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, | |
81 | - void *resp, int mx_resp_len, int noisy) | |
82 | + void *resp, int mx_resp_len, int noisy, unsigned int timeout) | |
83 | { | |
84 | unsigned char inqCmdBlk[INQUIRY_CMDLEN] = | |
85 | { INQUIRY_CMD, 0, 0, 0, 0, 0 }; | |
86 | @@ -70,7 +70,7 @@ do_inq(int sg_fd, int cmddt, int evpd, u | |
87 | io_hdr.dxferp = resp; | |
88 | io_hdr.cmdp = inqCmdBlk; | |
89 | io_hdr.sbp = sense_b; | |
90 | - io_hdr.timeout = DEF_TIMEOUT; | |
91 | + io_hdr.timeout = timeout; | |
92 | ||
93 | if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) | |
94 | return 1; | |
95 | @@ -98,7 +98,7 @@ do_inq(int sg_fd, int cmddt, int evpd, u | |
96 | } | |
97 | ||
98 | static int | |
99 | -do_tur (int fd) | |
100 | +do_tur (int fd, unsigned int timeout) | |
101 | { | |
102 | unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; | |
103 | struct sg_io_hdr io_hdr; | |
104 | @@ -111,7 +111,7 @@ do_tur (int fd) | |
105 | io_hdr.dxfer_direction = SG_DXFER_NONE; | |
106 | io_hdr.cmdp = turCmdBlk; | |
107 | io_hdr.sbp = sense_buffer; | |
108 | - io_hdr.timeout = DEF_TIMEOUT; | |
109 | + io_hdr.timeout = timeout; | |
110 | io_hdr.pack_id = 0; | |
111 | ||
112 | if (ioctl(fd, SG_IO, &io_hdr) < 0) | |
113 | @@ -128,12 +128,12 @@ libcheck_check (struct checker * c) | |
114 | { | |
115 | char buff[MX_ALLOC_LEN]; | |
116 | ||
117 | - if (0 != do_inq(c->fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) { | |
118 | + if (0 != do_inq(c->fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0, c->timeout)) { | |
119 | MSG(c, MSG_HP_SW_DOWN); | |
120 | return PATH_DOWN; | |
121 | } | |
122 | ||
123 | - if (do_tur(c->fd)) { | |
124 | + if (do_tur(c->fd, c->timeout)) { | |
125 | MSG(c, MSG_HP_SW_GHOST); | |
126 | return PATH_GHOST; | |
127 | } | |
128 | Index: multipath-tools/libmultipath/checkers/libsg.c | |
129 | =================================================================== | |
130 | --- multipath-tools.orig/libmultipath/checkers/libsg.c | |
131 | +++ multipath-tools/libmultipath/checkers/libsg.c | |
132 | @@ -11,7 +11,8 @@ | |
133 | #include "../libmultipath/sg_include.h" | |
134 | ||
135 | int | |
136 | -sg_read (int sg_fd, unsigned char * buff, unsigned char * senseBuff) | |
137 | +sg_read (int sg_fd, unsigned char * buff, unsigned char * senseBuff, | |
138 | + unsigned int timeout) | |
139 | { | |
140 | /* defaults */ | |
141 | int blocks = 1; | |
142 | @@ -51,7 +52,7 @@ sg_read (int sg_fd, unsigned char * buff | |
143 | io_hdr.dxferp = buff; | |
144 | io_hdr.mx_sb_len = SENSE_BUFF_LEN; | |
145 | io_hdr.sbp = senseBuff; | |
146 | - io_hdr.timeout = DEF_TIMEOUT; | |
147 | + io_hdr.timeout = timeout; | |
148 | io_hdr.pack_id = (int)start_block; | |
149 | if (diop && *diop) | |
150 | io_hdr.flags |= SG_FLAG_DIRECT_IO; | |
151 | Index: multipath-tools/libmultipath/checkers/libsg.h | |
152 | =================================================================== | |
153 | --- multipath-tools.orig/libmultipath/checkers/libsg.h | |
154 | +++ multipath-tools/libmultipath/checkers/libsg.h | |
155 | @@ -3,6 +3,7 @@ | |
156 | ||
157 | #define SENSE_BUFF_LEN 32 | |
158 | ||
159 | -int sg_read (int sg_fd, unsigned char * buff, unsigned char * senseBuff); | |
160 | +int sg_read (int sg_fd, unsigned char * buff, unsigned char * senseBuff, | |
161 | + unsigned int timeout); | |
162 | ||
163 | #endif /* _LIBSG_H */ | |
164 | Index: multipath-tools/libmultipath/checkers/rdac.c | |
165 | =================================================================== | |
166 | --- multipath-tools.orig/libmultipath/checkers/rdac.c | |
167 | +++ multipath-tools/libmultipath/checkers/rdac.c | |
168 | @@ -18,7 +18,6 @@ | |
169 | #define INQUIRY_CMDLEN 6 | |
170 | #define INQUIRY_CMD 0x12 | |
171 | #define SENSE_BUFF_LEN 32 | |
172 | -#define RDAC_DEF_TIMEOUT 60000 | |
173 | #define SCSI_CHECK_CONDITION 0x2 | |
174 | #define SCSI_COMMAND_TERMINATED 0x22 | |
175 | #define SG_ERR_DRIVER_SENSE 0x08 | |
176 | @@ -43,7 +42,8 @@ void libcheck_free (struct checker * c) | |
177 | } | |
178 | ||
179 | static int | |
180 | -do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len) | |
181 | +do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len, | |
182 | + unsigned int timeout) | |
183 | { | |
184 | unsigned char inqCmdBlk[INQUIRY_CMDLEN] = { INQUIRY_CMD, 1, 0, 0, 0, 0 }; | |
185 | unsigned char sense_b[SENSE_BUFF_LEN]; | |
186 | @@ -62,7 +62,7 @@ do_inq(int sg_fd, unsigned int pg_op, vo | |
187 | io_hdr.dxferp = resp; | |
188 | io_hdr.cmdp = inqCmdBlk; | |
189 | io_hdr.sbp = sense_b; | |
190 | - io_hdr.timeout = RDAC_DEF_TIMEOUT; | |
191 | + io_hdr.timeout = timeout; | |
192 | ||
193 | if (ioctl(sg_fd, SG_IO, &io_hdr) < 0) | |
194 | return 1; | |
195 | @@ -103,7 +103,8 @@ libcheck_check (struct checker * c) | |
196 | struct volume_access_inq inq; | |
197 | ||
198 | memset(&inq, 0, sizeof(struct volume_access_inq)); | |
199 | - if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq))) { | |
200 | + if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq), | |
201 | + c->timeout)) { | |
202 | MSG(c, MSG_RDAC_DOWN); | |
203 | return PATH_DOWN; | |
204 | } else { | |
205 | Index: multipath-tools/libmultipath/checkers/readsector0.c | |
206 | =================================================================== | |
207 | --- multipath-tools.orig/libmultipath/checkers/readsector0.c | |
208 | +++ multipath-tools/libmultipath/checkers/readsector0.c | |
209 | @@ -29,7 +29,7 @@ int libcheck_check (struct checker * c) | |
210 | unsigned char sbuf[SENSE_BUFF_LEN]; | |
211 | int ret; | |
212 | ||
213 | - ret = sg_read(c->fd, &buf[0], &sbuf[0]); | |
214 | + ret = sg_read(c->fd, &buf[0], &sbuf[0], c->timeout); | |
215 | ||
216 | switch (ret) | |
217 | { | |
218 | Index: multipath-tools/libmultipath/checkers/tur.c | |
219 | =================================================================== | |
220 | --- multipath-tools.orig/libmultipath/checkers/tur.c | |
221 | +++ multipath-tools/libmultipath/checkers/tur.c | |
222 | @@ -63,7 +63,7 @@ retry: | |
223 | io_hdr.dxferp = (unsigned char *)resp_buffer; | |
224 | io_hdr.cmdp = inq_cmd; | |
225 | io_hdr.sbp = sense_buffer; | |
226 | - io_hdr.timeout = 60; // IOCTL timeout value. | |
227 | + io_hdr.timeout = c->timeout; // IOCTL timeout value. | |
228 | ||
229 | if (ioctl(c->fd, SG_IO, &io_hdr) < 0) { | |
230 | condlog(0, "SG_IO ioctl failed: %s", strerror(errno)); | |
231 | @@ -148,7 +148,7 @@ libcheck_check (struct checker * c) | |
232 | io_hdr.dxfer_direction = SG_DXFER_NONE; | |
233 | io_hdr.cmdp = turCmdBlk; | |
234 | io_hdr.sbp = sense_buffer; | |
235 | - io_hdr.timeout = DEF_TIMEOUT; | |
236 | + io_hdr.timeout = c->timeout; | |
237 | io_hdr.pack_id = 0; | |
238 | if (ioctl(c->fd, SG_IO, &io_hdr) < 0) { | |
239 | MSG(c, MSG_TUR_DOWN); | |
240 | Index: multipath-tools/libmultipath/config.h | |
241 | =================================================================== | |
242 | --- multipath-tools.orig/libmultipath/config.h | |
243 | +++ multipath-tools/libmultipath/config.h | |
244 | @@ -80,6 +80,7 @@ struct config { | |
245 | int max_fds; | |
246 | int force_reload; | |
247 | int queue_without_daemon; | |
248 | + int checker_timeout; | |
249 | int daemon; | |
250 | int flush_on_last_del; | |
251 | int attribute_flags; | |
252 | Index: multipath-tools/libmultipath/dict.c | |
253 | =================================================================== | |
254 | --- multipath-tools.orig/libmultipath/dict.c | |
255 | +++ multipath-tools/libmultipath/dict.c | |
256 | @@ -396,6 +396,25 @@ def_queue_without_daemon(vector strvec) | |
257 | } | |
258 | ||
259 | static int | |
260 | +def_checker_timeout_handler(vector strvec) | |
261 | +{ | |
262 | + unsigned int checker_timeout; | |
263 | + char *buff; | |
264 | + | |
265 | + buff = set_value(strvec); | |
266 | + if (!buff) | |
267 | + return 1; | |
268 | + | |
269 | + if (sscanf(buff, "%u", &checker_timeout) == 1) | |
270 | + conf->checker_timeout = checker_timeout; | |
271 | + else | |
272 | + conf->checker_timeout = 0; | |
273 | + | |
274 | + free(buff); | |
275 | + return 0; | |
276 | +} | |
277 | + | |
278 | +static int | |
279 | def_pg_timeout_handler(vector strvec) | |
280 | { | |
281 | int pg_timeout; | |
282 | @@ -2068,6 +2087,15 @@ snprint_def_queue_without_daemon (char * | |
283 | } | |
284 | ||
285 | static int | |
286 | +snprint_def_checker_timeout (char *buff, int len, void *data) | |
287 | +{ | |
288 | + if (!conf->checker_timeout) | |
289 | + return 0; | |
290 | + | |
291 | + return snprintf(buff, len, "%u", conf->checker_timeout); | |
292 | +} | |
293 | + | |
294 | +static int | |
295 | snprint_def_pg_timeout (char * buff, int len, void * data) | |
296 | { | |
297 | if (conf->pg_timeout == DEFAULT_PGTIMEOUT) | |
298 | @@ -2166,6 +2194,7 @@ init_keywords(void) | |
299 | install_keyword("rr_weight", &def_weight_handler, &snprint_def_rr_weight); | |
300 | install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry); | |
301 | install_keyword("queue_without_daemon", &def_queue_without_daemon, &snprint_def_queue_without_daemon); | |
302 | + install_keyword("checker_timeout", &def_checker_timeout_handler, &snprint_def_checker_timeout); | |
303 | install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout); | |
304 | install_keyword("flush_on_last_del", &def_flush_on_last_del_handler, &snprint_def_flush_on_last_del); | |
305 | install_keyword("user_friendly_names", &names_handler, &snprint_def_user_friendly_names); | |
306 | Index: multipath-tools/libmultipath/discovery.c | |
307 | =================================================================== | |
308 | --- multipath-tools.orig/libmultipath/discovery.c | |
309 | +++ multipath-tools/libmultipath/discovery.c | |
310 | @@ -164,6 +164,31 @@ sysfs_get_dev (struct sysfs_device * dev | |
311 | } | |
312 | ||
313 | int | |
314 | +sysfs_get_timeout(struct sysfs_device *dev, unsigned int *timeout) | |
315 | +{ | |
316 | + char *attr; | |
317 | + char attr_path[SYSFS_PATH_SIZE]; | |
318 | + int r; | |
319 | + unsigned int t; | |
320 | + | |
321 | + if (safe_sprintf(attr_path, "%s/device", dev->devpath)) | |
322 | + return 1; | |
323 | + | |
324 | + attr = sysfs_attr_get_value(dev->devpath, "timeout"); | |
325 | + if (!attr) | |
326 | + return 1; | |
327 | + | |
328 | + r = sscanf(attr, "%u\n", &t); | |
329 | + | |
330 | + if (r != 1) | |
331 | + return 1; | |
332 | + | |
333 | + *timeout = t * 1000; | |
334 | + | |
335 | + return 0; | |
336 | +} | |
337 | + | |
338 | +int | |
339 | sysfs_get_size (struct sysfs_device * dev, unsigned long long * size) | |
340 | { | |
341 | char *attr; | |
342 | @@ -791,6 +816,8 @@ get_state (struct path * pp, int daemon) | |
343 | return PATH_PENDING; | |
344 | checker_set_async(c); | |
345 | } | |
346 | + if (!conf->checker_timeout) | |
347 | + sysfs_get_timeout(pp->sysdev, &(c->timeout)); | |
348 | state = checker_check(c); | |
349 | condlog(3, "%s: state = %i", pp->dev, state); | |
350 | if (state == PATH_DOWN && strlen(checker_message(c))) | |
351 | Index: multipath-tools/libmultipath/propsel.c | |
352 | =================================================================== | |
353 | --- multipath-tools.orig/libmultipath/propsel.c | |
354 | +++ multipath-tools/libmultipath/propsel.c | |
355 | @@ -16,6 +16,7 @@ | |
356 | #include "defaults.h" | |
357 | #include "devmapper.h" | |
358 | #include "prio.h" | |
359 | +#include "discovery.h" | |
360 | ||
361 | pgpolicyfn *pgpolicies[] = { | |
362 | NULL, | |
363 | @@ -274,17 +275,31 @@ select_checker(struct path *pp) | |
364 | checker_get(c, pp->hwe->checker_name); | |
365 | condlog(3, "%s: path checker = %s (controller setting)", | |
366 | pp->dev, checker_name(c)); | |
367 | - return 0; | |
368 | + goto out; | |
369 | } | |
370 | if (conf->checker_name) { | |
371 | checker_get(c, conf->checker_name); | |
372 | condlog(3, "%s: path checker = %s (config file default)", | |
373 | pp->dev, checker_name(c)); | |
374 | - return 0; | |
375 | + goto out; | |
376 | } | |
377 | checker_get(c, DEFAULT_CHECKER); | |
378 | condlog(3, "%s: path checker = %s (internal default)", | |
379 | pp->dev, checker_name(c)); | |
380 | +out: | |
381 | + if (conf->checker_timeout) { | |
382 | + c->timeout = conf->checker_timeout * 1000; | |
383 | + condlog(3, "%s: checker timeout = %u ms (config file default)", | |
384 | + pp->dev, c->timeout); | |
385 | + } | |
386 | + else if (sysfs_get_timeout(pp->sysdev, &c->timeout) == 0) | |
387 | + condlog(3, "%s: checker timeout = %u ms (sysfs setting)", | |
388 | + pp->dev, c->timeout); | |
389 | + else { | |
390 | + c->timeout = DEF_TIMEOUT; | |
391 | + condlog(3, "%s: checker timeout = %u ms (internal default)", | |
392 | + pp->dev, c->timeout); | |
393 | + } | |
394 | return 0; | |
395 | } | |
396 | ||
397 | Index: multipath-tools/multipath.conf.annotated | |
398 | =================================================================== | |
399 | --- multipath-tools.orig/multipath.conf.annotated | |
400 | +++ multipath-tools/multipath.conf.annotated | |
401 | @@ -202,6 +202,15 @@ | |
402 | # gid disk | |
403 | # | |
404 | # # | |
405 | +# # name : checker_timeout | |
406 | +# # scope : multipath & multipathd | |
407 | +# # desc : The timeout to use for path checkers that issue scsi | |
408 | +# # commands with an explicit timeout, in seconds. | |
409 | +# # values : n > 0 | |
410 | +# # default : taken from /sys/block/sd<x>/device/timeout | |
411 | +# checker_timeout 60 | |
412 | +# | |
413 | +# # | |
414 | # # name : fast_io_fail_tmo | |
415 | # # scope : multipath & multipathd | |
416 | # # desc : The number of seconds the scsi layer will wait after a | |
417 | Index: multipath-tools/libmultipath/discovery.h | |
418 | =================================================================== | |
419 | --- multipath-tools.orig/libmultipath/discovery.h | |
420 | +++ multipath-tools/libmultipath/discovery.h | |
421 | @@ -36,6 +36,7 @@ int pathinfo (struct path *, vector hwta | |
422 | struct path * store_pathinfo (vector pathvec, vector hwtable, | |
423 | char * devname, int flag); | |
424 | int sysfs_set_scsi_tmo (struct multipath *mpp); | |
425 | +int sysfs_get_timeout(struct sysfs_device *dev, unsigned int *timeout); | |
426 | ||
427 | /* | |
428 | * discovery bitmask |