]>
Commit | Line | Data |
---|---|---|
dc01aad8 SS |
1 | --- |
2 | libmultipath/config.c | 10 ++ | |
3 | libmultipath/config.h | 4 + | |
4 | libmultipath/dict.c | 92 ++++++++++++++++++++--- | |
5 | libmultipath/discovery.c | 56 +++++++------- | |
6 | libmultipath/prio.h | 1 | |
7 | libmultipath/prioritizers/Makefile | 3 | |
8 | libmultipath/prioritizers/weighted.c | 139 +++++++++++++++++++++++++++++++++++ | |
9 | libmultipath/prioritizers/weighted.h | 8 ++ | |
10 | libmultipath/propsel.c | 11 ++ | |
11 | libmultipath/structs.h | 1 | |
12 | 10 files changed, 286 insertions(+), 39 deletions(-) | |
13 | ||
14 | Index: multipath-tools/libmultipath/config.c | |
15 | =================================================================== | |
16 | --- multipath-tools.orig/libmultipath/config.c | |
17 | +++ multipath-tools/libmultipath/config.c | |
18 | @@ -156,6 +156,9 @@ free_hwe (struct hwentry * hwe) | |
19 | if (hwe->prio_name) | |
20 | FREE(hwe->prio_name); | |
21 | ||
22 | + if (hwe->prio_args) | |
23 | + FREE(hwe->prio_args); | |
24 | + | |
25 | if (hwe->bl_product) | |
26 | FREE(hwe->bl_product); | |
27 | ||
28 | @@ -195,6 +198,12 @@ free_mpe (struct mpentry * mpe) | |
29 | if (mpe->alias) | |
30 | FREE(mpe->alias); | |
31 | ||
32 | + if (mpe->prio_name) | |
33 | + FREE(mpe->prio_name); | |
34 | + | |
35 | + if (mpe->prio_args) | |
36 | + FREE(mpe->prio_args); | |
37 | + | |
38 | FREE(mpe); | |
39 | } | |
40 | ||
41 | @@ -279,6 +288,7 @@ merge_hwe (struct hwentry * hwe1, struct | |
42 | merge_str(selector); | |
43 | merge_str(checker_name); | |
44 | merge_str(prio_name); | |
45 | + merge_str(prio_args); | |
46 | merge_str(bl_product); | |
47 | merge_num(pgpolicy); | |
48 | merge_num(pgfailback); | |
49 | Index: multipath-tools/libmultipath/config.h | |
50 | =================================================================== | |
51 | --- multipath-tools.orig/libmultipath/config.h | |
52 | +++ multipath-tools/libmultipath/config.h | |
53 | @@ -25,6 +25,7 @@ struct hwentry { | |
54 | char * selector; | |
55 | char * checker_name; | |
56 | char * prio_name; | |
57 | + char * prio_args; | |
58 | ||
59 | int pgpolicy; | |
60 | int pgfailback; | |
61 | @@ -43,6 +44,8 @@ struct mpentry { | |
62 | char * alias; | |
63 | char * getuid; | |
64 | char * selector; | |
65 | + char * prio_name; | |
66 | + char * prio_args; | |
67 | ||
68 | int pgpolicy; | |
69 | int pgfailback; | |
70 | @@ -97,6 +100,7 @@ struct config { | |
71 | char * hwhandler; | |
72 | char * bindings_file; | |
73 | char * prio_name; | |
74 | + char * prio_args; | |
75 | char * checker_name; | |
76 | ||
77 | vector keywords; | |
78 | Index: multipath-tools/libmultipath/dict.c | |
79 | =================================================================== | |
80 | --- multipath-tools.orig/libmultipath/dict.c | |
81 | +++ multipath-tools/libmultipath/dict.c | |
82 | @@ -139,11 +139,23 @@ def_getuid_callout_handler(vector strvec | |
83 | static int | |
84 | def_prio_handler(vector strvec) | |
85 | { | |
86 | - conf->prio_name = set_value(strvec); | |
87 | + char *name, *args; | |
88 | ||
89 | - if (!conf->prio_name) | |
90 | + name = set_value(strvec); | |
91 | + if (!name) | |
92 | return 1; | |
93 | ||
94 | + args = strpbrk(name, " \t"); | |
95 | + if (args) { | |
96 | + *args = 0; | |
97 | + while(*++args && isblank(*args)); /* Do nothing */ | |
98 | + } | |
99 | + | |
100 | + conf->prio_name = STRDUP(name); | |
101 | + if (args && *args) | |
102 | + conf->prio_args = STRDUP(args); | |
103 | + | |
104 | + FREE(name); | |
105 | return 0; | |
106 | } | |
107 | ||
108 | @@ -806,16 +818,27 @@ hw_handler_handler(vector strvec) | |
109 | static int | |
110 | hw_prio_handler(vector strvec) | |
111 | { | |
112 | + char *name, *args; | |
113 | struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); | |
114 | ||
115 | if (!hwe) | |
116 | return 1; | |
117 | ||
118 | - hwe->prio_name = set_value(strvec); | |
119 | - | |
120 | - if (!hwe->prio_name) | |
121 | + name = set_value(strvec); | |
122 | + if (!name) | |
123 | return 1; | |
124 | ||
125 | + args = strpbrk(name, " \t"); | |
126 | + if (args) { | |
127 | + *args = 0; | |
128 | + while(*++args && isblank(*args)); /* Do nothing */ | |
129 | + } | |
130 | + | |
131 | + hwe->prio_name = STRDUP(name); | |
132 | + if (args && *args) | |
133 | + hwe->prio_args = STRDUP(args); | |
134 | + | |
135 | + FREE(name); | |
136 | return 0; | |
137 | } | |
138 | ||
139 | @@ -1293,6 +1316,33 @@ mp_flush_on_last_del_handler(vector strv | |
140 | return 0; | |
141 | } | |
142 | ||
143 | +static int | |
144 | +mp_prio_handler(vector strvec) | |
145 | +{ | |
146 | + char *name, *args; | |
147 | + struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); | |
148 | + | |
149 | + if (!mpe) | |
150 | + return 1; | |
151 | + | |
152 | + name = set_value(strvec); | |
153 | + if (!name) | |
154 | + return 1; | |
155 | + | |
156 | + args = strpbrk(name, " \t"); | |
157 | + if (args) { | |
158 | + *args = 0; | |
159 | + while(*++args && isblank(*args)); /* Do nothing */ | |
160 | + } | |
161 | + | |
162 | + mpe->prio_name = STRDUP(name); | |
163 | + if (args && *args) | |
164 | + mpe->prio_args = STRDUP(args); | |
165 | + | |
166 | + FREE(name); | |
167 | + return 0; | |
168 | +} | |
169 | + | |
170 | /* | |
171 | * config file keywords printing | |
172 | */ | |
173 | @@ -1472,6 +1522,20 @@ snprint_mp_flush_on_last_del (char * buf | |
174 | } | |
175 | ||
176 | static int | |
177 | +snprint_mp_prio (char * buff, int len, void * data) | |
178 | +{ | |
179 | + struct mpentry * mpe = (struct mpentry *)data; | |
180 | + | |
181 | + if (!mpe->prio_name) | |
182 | + return 0; | |
183 | + if (!strcmp(mpe->prio_name, conf->prio_name) && !mpe->prio_args) | |
184 | + return 0; | |
185 | + if (!mpe->prio_args) | |
186 | + return snprintf(buff, len, "%s", mpe->prio_name); | |
187 | + return snprintf(buff, len, "%s %s", mpe->prio_name, mpe->prio_args); | |
188 | +} | |
189 | + | |
190 | +static int | |
191 | snprint_hw_fast_io_fail(char * buff, int len, void * data) | |
192 | { | |
193 | struct hwentry * hwe = (struct hwentry *)data; | |
194 | @@ -1545,10 +1609,11 @@ snprint_hw_prio (char * buff, int len, v | |
195 | ||
196 | if (!hwe->prio_name) | |
197 | return 0; | |
198 | - if (!strcmp(hwe->prio_name, conf->prio_name)) | |
199 | + if (!strcmp(hwe->prio_name, conf->prio_name) && !hwe->prio_args) | |
200 | return 0; | |
201 | - | |
202 | - return snprintf(buff, len, "%s", hwe->prio_name); | |
203 | + if (!hwe->prio_args) | |
204 | + return snprintf(buff, len, "%s", hwe->prio_name); | |
205 | + return snprintf(buff, len, "%s %s", hwe->prio_name, hwe->prio_args); | |
206 | } | |
207 | ||
208 | static int | |
209 | @@ -1837,10 +1902,14 @@ snprint_def_prio (char * buff, int len, | |
210 | return 0; | |
211 | ||
212 | if (strlen(conf->prio_name) == strlen(DEFAULT_PRIO) && | |
213 | - !strcmp(conf->prio_name, DEFAULT_PRIO)) | |
214 | + !strcmp(conf->prio_name, DEFAULT_PRIO) && !conf->prio_args) | |
215 | return 0; | |
216 | - | |
217 | - return snprintf(buff, len, "%s", conf->prio_name); | |
218 | + | |
219 | + if (!conf->prio_args) | |
220 | + return snprintf(buff, len, "%s", conf->prio_name); | |
221 | + else | |
222 | + return snprintf(buff, len, "%s %s", conf->prio_name, | |
223 | + conf->prio_args); | |
224 | } | |
225 | ||
226 | static int | |
227 | @@ -2146,5 +2215,6 @@ init_keywords(void) | |
228 | install_keyword("mode", &mp_mode_handler, &snprint_mp_mode); | |
229 | install_keyword("uid", &mp_uid_handler, &snprint_mp_uid); | |
230 | install_keyword("gid", &mp_gid_handler, &snprint_mp_gid); | |
231 | + install_keyword("prio", &mp_prio_handler, &snprint_mp_prio); | |
232 | install_sublevel_end(); | |
233 | } | |
234 | Index: multipath-tools/libmultipath/discovery.c | |
235 | =================================================================== | |
236 | --- multipath-tools.orig/libmultipath/discovery.c | |
237 | +++ multipath-tools/libmultipath/discovery.c | |
238 | @@ -800,30 +800,6 @@ get_state (struct path * pp, int daemon) | |
239 | } | |
240 | ||
241 | static int | |
242 | -get_prio (struct path * pp) | |
243 | -{ | |
244 | - if (!pp) | |
245 | - return 0; | |
246 | - | |
247 | - if (!pp->prio) { | |
248 | - select_prio(pp); | |
249 | - if (!pp->prio) { | |
250 | - condlog(3, "%s: no prio selected", pp->dev); | |
251 | - return 1; | |
252 | - } | |
253 | - } | |
254 | - pp->priority = prio_getprio(pp->prio, pp); | |
255 | - if (pp->priority < 0) { | |
256 | - condlog(3, "%s: %s prio error", pp->dev, prio_name(pp->prio)); | |
257 | - pp->priority = PRIO_UNDEF; | |
258 | - return 1; | |
259 | - } | |
260 | - condlog(3, "%s: %s prio = %u", | |
261 | - pp->dev, prio_name(pp->prio), pp->priority); | |
262 | - return 0; | |
263 | -} | |
264 | - | |
265 | -static int | |
266 | get_uid (struct path * pp) | |
267 | { | |
268 | char buff[CALLOUT_MAX_SIZE]; | |
269 | @@ -850,6 +826,32 @@ get_uid (struct path * pp) | |
270 | return 0; | |
271 | } | |
272 | ||
273 | +static int | |
274 | +get_prio (struct path * pp) | |
275 | +{ | |
276 | + if (!pp) | |
277 | + return 0; | |
278 | + | |
279 | + if (!pp->prio) { | |
280 | + if (!strlen(pp->wwid)) | |
281 | + get_uid(pp); | |
282 | + select_prio(pp); | |
283 | + if (!pp->prio) { | |
284 | + condlog(3, "%s: no prio selected", pp->dev); | |
285 | + return 1; | |
286 | + } | |
287 | + } | |
288 | + pp->priority = prio_getprio(pp->prio, pp); | |
289 | + if (pp->priority < 0) { | |
290 | + condlog(3, "%s: %s prio error", pp->dev, prio_name(pp->prio)); | |
291 | + pp->priority = PRIO_UNDEF; | |
292 | + return 1; | |
293 | + } | |
294 | + condlog(3, "%s: %s prio = %u", | |
295 | + pp->dev, prio_name(pp->prio), pp->priority); | |
296 | + return 0; | |
297 | +} | |
298 | + | |
299 | extern int | |
300 | pathinfo (struct path *pp, vector hwtable, int mask) | |
301 | { | |
302 | @@ -887,6 +889,9 @@ pathinfo (struct path *pp, vector hwtabl | |
303 | goto blank; | |
304 | } | |
305 | ||
306 | + if (mask & DI_WWID && !strlen(pp->wwid)) | |
307 | + get_uid(pp); | |
308 | + | |
309 | /* | |
310 | * Retrieve path priority, even for PATH_DOWN paths if it has never | |
311 | * been successfully obtained before. | |
312 | @@ -895,9 +900,6 @@ pathinfo (struct path *pp, vector hwtabl | |
313 | (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF)) | |
314 | get_prio(pp); | |
315 | ||
316 | - if (mask & DI_WWID && !strlen(pp->wwid)) | |
317 | - get_uid(pp); | |
318 | - | |
319 | return 0; | |
320 | ||
321 | blank: | |
322 | Index: multipath-tools/libmultipath/prio.h | |
323 | =================================================================== | |
324 | --- multipath-tools.orig/libmultipath/prio.h | |
325 | +++ multipath-tools/libmultipath/prio.h | |
326 | @@ -24,6 +24,7 @@ | |
327 | #define PRIO_NETAPP "netapp" | |
328 | #define PRIO_RANDOM "random" | |
329 | #define PRIO_RDAC "rdac" | |
330 | +#define PRIO_WEIGHTED "weighted" | |
331 | ||
332 | /* | |
333 | * Value used to mark the fact prio was not defined | |
334 | Index: multipath-tools/libmultipath/prioritizers/Makefile | |
335 | =================================================================== | |
336 | --- multipath-tools.orig/libmultipath/prioritizers/Makefile | |
337 | +++ multipath-tools/libmultipath/prioritizers/Makefile | |
338 | @@ -13,7 +13,8 @@ LIBS = \ | |
339 | libprioalua.so \ | |
340 | libpriotpg_pref.so \ | |
341 | libprionetapp.so \ | |
342 | - libpriohds.so | |
343 | + libpriohds.so \ | |
344 | + libprioweighted.so \ | |
345 | ||
346 | CFLAGS += -I.. | |
347 | ||
348 | Index: multipath-tools/libmultipath/prioritizers/weighted.c | |
349 | =================================================================== | |
350 | --- /dev/null | |
351 | +++ multipath-tools/libmultipath/prioritizers/weighted.c | |
352 | @@ -0,0 +1,139 @@ | |
353 | +/****************************************************************************** | |
354 | +******************************************************************************* | |
355 | +** | |
356 | +** Copyright (C) 2009 Red Hat, Inc. All rights reserved. | |
357 | +** | |
358 | +** This copyrighted material is made available to anyone wishing to use, | |
359 | +** modify, copy, or redistribute it subject to the terms and conditions | |
360 | +** of the GNU General Public License v.2. | |
361 | +** | |
362 | +******************************************************************************* | |
363 | +******************************************************************************/ | |
364 | + | |
365 | +/* This prioritizer is based on a path's device name or its H:T:B:L. Both of | |
366 | + * these can change when the node is rebooted, and can differ from node to | |
367 | + * node. (i.e. there is no guarantee that sda will point to the same device | |
368 | + * after a reboot) If you use this prioritizer, it may be necessary to | |
369 | + * manually edit /etc/multipath.conf after any reboot | |
370 | + * | |
371 | + * Format: | |
372 | + * prio "weighted hbtl <regex> <prio> [<regex> <prio>] | |
373 | + * prio "weighted devname <regex> <prio> [<regex> <prio>] | |
374 | + * | |
375 | + * Examples: | |
376 | + * prio "weighted hbtl 4:* 2 3:.:.:. 1" | |
377 | + * prio "weighted devname sda 2 sde 1" | |
378 | + * | |
379 | + */ | |
380 | + | |
381 | +#include <string.h> | |
382 | +#include <prio.h> | |
383 | +#include <debug.h> | |
384 | +#include <regex.h> | |
385 | + | |
386 | +#include "weighted.h" | |
387 | + | |
388 | +#define DEFAULT_WEIGHTED_PRIO 0 | |
389 | + | |
390 | +#define pp_weighted_log(prio, fmt, args...) \ | |
391 | + condlog(prio, "%s: weighted prio: " fmt, dev, ##args) | |
392 | + | |
393 | +static char * | |
394 | +next_str(char **str) | |
395 | +{ | |
396 | + char *next; | |
397 | + | |
398 | + do { | |
399 | + next = strsep(str, " \t"); | |
400 | + } while (next && strcmp(next, "") == 0); | |
401 | + return next; | |
402 | +} | |
403 | + | |
404 | + | |
405 | +static int | |
406 | +match (char *dev, char *target, char *regex_str, char *prio_str, | |
407 | + unsigned int *prio) | |
408 | +{ | |
409 | + | |
410 | + regex_t regex; | |
411 | + int err, ret = 0; | |
412 | + char *errbuf; | |
413 | + size_t errbuf_size; | |
414 | + unsigned int prio_match; | |
415 | + | |
416 | + if (sscanf(prio_str, "%u", &prio_match) != 1) { | |
417 | + condlog(0, "%s: weighted prio: invalid prio '%s'", dev, | |
418 | + prio_str); | |
419 | + return 0; | |
420 | + } | |
421 | + err = regcomp(®ex, regex_str, REG_EXTENDED|REG_NOSUB); | |
422 | + if (err) { | |
423 | + errbuf_size = regerror(err, ®ex, NULL, 0); | |
424 | + errbuf = malloc(errbuf_size); | |
425 | + regerror(err, ®ex, errbuf, errbuf_size); | |
426 | + condlog(0, "%s: weighted prio: cannot compile regex '%s' : %s", | |
427 | + dev, regex_str, errbuf); | |
428 | + free(errbuf); | |
429 | + return 0; | |
430 | + } | |
431 | + if (regexec(®ex, target, 0, NULL, 0) == 0) { | |
432 | + *prio = prio_match; | |
433 | + ret = 1; | |
434 | + } | |
435 | + | |
436 | + regfree(®ex); | |
437 | + return ret; | |
438 | +} | |
439 | + | |
440 | +int | |
441 | +prio_weighted(struct path * pp) | |
442 | +{ | |
443 | + char target[FILE_NAME_SIZE]; | |
444 | + char *buff, *args, *ptr, *prio_str; | |
445 | + unsigned int prio = DEFAULT_WEIGHTED_PRIO; | |
446 | + char *regex_str = NULL; | |
447 | + int regex_size = 0; | |
448 | + | |
449 | + if (!pp->prio_args) | |
450 | + return DEFAULT_WEIGHTED_PRIO; | |
451 | + buff = args = strdup(pp->prio_args); | |
452 | + ptr = next_str(&args); | |
453 | + | |
454 | + if (strcasecmp(ptr, "hbtl") == 0) | |
455 | + sprintf(target, "%d:%d:%d:%d", pp->sg_id.host_no, | |
456 | + pp->sg_id.channel, pp->sg_id.scsi_id, pp->sg_id.lun); | |
457 | + else if (strcasecmp(ptr, "devname") == 0) | |
458 | + strcpy(target, pp->dev); | |
459 | + else { | |
460 | + condlog(0, "%s: weighted prio: invalid argument. Want 'hbtl' or 'devname'. Got '%s'", pp->dev, ptr); | |
461 | + goto out; | |
462 | + } | |
463 | + | |
464 | + while ((ptr = next_str(&args)) != NULL) { | |
465 | + | |
466 | + prio_str = next_str(&args); | |
467 | + if (!prio_str) { | |
468 | + condlog(0, "%s weighted prio: missing prio for regex '%s'", pp->dev, ptr); | |
469 | + goto out; | |
470 | + } | |
471 | + if (!regex_str || regex_size < strlen(ptr) + 3){ | |
472 | + regex_size = strlen(ptr) + 3; | |
473 | + regex_str = realloc(regex_str, regex_size); | |
474 | + } | |
475 | + sprintf(regex_str, "%s%s%s", (ptr[0] == '^')? "" : "^", | |
476 | + ptr, (ptr[strlen(ptr)-1] == '$')? "" : "$"); | |
477 | + if (match(pp->dev, target, regex_str, prio_str, &prio)) | |
478 | + break; | |
479 | + } | |
480 | +out: | |
481 | + free(buff); | |
482 | + if (regex_str) | |
483 | + free(regex_str); | |
484 | + return prio; | |
485 | +} | |
486 | + | |
487 | +int | |
488 | +getprio(struct path * pp) | |
489 | +{ | |
490 | + return prio_weighted(pp); | |
491 | +} | |
492 | Index: multipath-tools/libmultipath/propsel.c | |
493 | =================================================================== | |
494 | --- multipath-tools.orig/libmultipath/propsel.c | |
495 | +++ multipath-tools/libmultipath/propsel.c | |
496 | @@ -312,14 +312,25 @@ select_getuid (struct path * pp) | |
497 | extern int | |
498 | select_prio (struct path * pp) | |
499 | { | |
500 | + struct mpentry * mpe; | |
501 | + | |
502 | + if ((mpe = find_mpe(pp->wwid)) && mpe->prio_name) { | |
503 | + pp->prio = prio_lookup(mpe->prio_name); | |
504 | + pp->prio_args = mpe->prio_args; | |
505 | + condlog(3, "%s: prio = %s (LUN setting)", | |
506 | + pp->dev, mpe->prio_name); | |
507 | + return 0; | |
508 | + } | |
509 | if (pp->hwe && pp->hwe->prio_name) { | |
510 | pp->prio = prio_lookup(pp->hwe->prio_name); | |
511 | + pp->prio_args = pp->hwe->prio_args; | |
512 | condlog(3, "%s: prio = %s (controller setting)", | |
513 | pp->dev, pp->hwe->prio_name); | |
514 | return 0; | |
515 | } | |
516 | if (conf->prio_name) { | |
517 | pp->prio = prio_lookup(conf->prio_name); | |
518 | + pp->prio_args = conf->prio_args; | |
519 | condlog(3, "%s: prio = %s (config file default)", | |
520 | pp->dev, conf->prio_name); | |
521 | return 0; | |
522 | Index: multipath-tools/libmultipath/structs.h | |
523 | =================================================================== | |
524 | --- multipath-tools.orig/libmultipath/structs.h | |
525 | +++ multipath-tools/libmultipath/structs.h | |
526 | @@ -142,6 +142,7 @@ struct path { | |
527 | int priority; | |
528 | int pgindex; | |
529 | char * getuid; | |
530 | + char * prio_args; | |
531 | struct prio * prio; | |
532 | struct checker checker; | |
533 | struct multipath * mpp; | |
534 | Index: multipath-tools/libmultipath/prioritizers/weighted.h | |
535 | =================================================================== | |
536 | --- /dev/null | |
537 | +++ multipath-tools/libmultipath/prioritizers/weighted.h | |
538 | @@ -0,0 +1,8 @@ | |
539 | +#ifndef _WEIGHTED_H | |
540 | +#define _WEIGHTED_H | |
541 | + | |
542 | +#define PRIO_WEIGHTED "weighted" | |
543 | + | |
544 | +int prio_weighted(struct path *pp); | |
545 | + | |
546 | +#endif |