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(-)
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)
23 + FREE(hwe->prio_args);
26 FREE(hwe->bl_product);
28 @@ -195,6 +198,12 @@ free_mpe (struct mpentry * mpe)
33 + FREE(mpe->prio_name);
36 + FREE(mpe->prio_args);
41 @@ -279,6 +288,7 @@ merge_hwe (struct hwentry * hwe1, struct
43 merge_str(checker_name);
45 + merge_str(prio_args);
46 merge_str(bl_product);
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 {
61 @@ -43,6 +44,8 @@ struct mpentry {
70 @@ -97,6 +100,7 @@ struct config {
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
84 def_prio_handler(vector strvec)
86 - conf->prio_name = set_value(strvec);
89 - if (!conf->prio_name)
90 + name = set_value(strvec);
94 + args = strpbrk(name, " \t");
97 + while(*++args && isblank(*args)); /* Do nothing */
100 + conf->prio_name = STRDUP(name);
102 + conf->prio_args = STRDUP(args);
108 @@ -806,16 +818,27 @@ hw_handler_handler(vector strvec)
110 hw_prio_handler(vector strvec)
113 struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
118 - hwe->prio_name = set_value(strvec);
120 - if (!hwe->prio_name)
121 + name = set_value(strvec);
125 + args = strpbrk(name, " \t");
128 + while(*++args && isblank(*args)); /* Do nothing */
131 + hwe->prio_name = STRDUP(name);
133 + hwe->prio_args = STRDUP(args);
139 @@ -1293,6 +1316,33 @@ mp_flush_on_last_del_handler(vector strv
144 +mp_prio_handler(vector strvec)
147 + struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable);
152 + name = set_value(strvec);
156 + args = strpbrk(name, " \t");
159 + while(*++args && isblank(*args)); /* Do nothing */
162 + mpe->prio_name = STRDUP(name);
164 + mpe->prio_args = STRDUP(args);
171 * config file keywords printing
173 @@ -1472,6 +1522,20 @@ snprint_mp_flush_on_last_del (char * buf
177 +snprint_mp_prio (char * buff, int len, void * data)
179 + struct mpentry * mpe = (struct mpentry *)data;
181 + if (!mpe->prio_name)
183 + if (!strcmp(mpe->prio_name, conf->prio_name) && !mpe->prio_args)
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);
191 snprint_hw_fast_io_fail(char * buff, int len, void * data)
193 struct hwentry * hwe = (struct hwentry *)data;
194 @@ -1545,10 +1609,11 @@ snprint_hw_prio (char * buff, int len, v
198 - if (!strcmp(hwe->prio_name, conf->prio_name))
199 + if (!strcmp(hwe->prio_name, conf->prio_name) && !hwe->prio_args)
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);
209 @@ -1837,10 +1902,14 @@ snprint_def_prio (char * buff, int len,
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)
217 - return snprintf(buff, len, "%s", conf->prio_name);
219 + if (!conf->prio_args)
220 + return snprintf(buff, len, "%s", conf->prio_name);
222 + return snprintf(buff, len, "%s %s", conf->prio_name,
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();
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)
242 -get_prio (struct path * pp)
250 - condlog(3, "%s: no prio selected", pp->dev);
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;
260 - condlog(3, "%s: %s prio = %u",
261 - pp->dev, prio_name(pp->prio), pp->priority);
266 get_uid (struct path * pp)
268 char buff[CALLOUT_MAX_SIZE];
269 @@ -850,6 +826,32 @@ get_uid (struct path * pp)
274 +get_prio (struct path * pp)
280 + if (!strlen(pp->wwid))
284 + condlog(3, "%s: no prio selected", pp->dev);
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;
294 + condlog(3, "%s: %s prio = %u",
295 + pp->dev, prio_name(pp->prio), pp->priority);
300 pathinfo (struct path *pp, vector hwtable, int mask)
302 @@ -887,6 +889,9 @@ pathinfo (struct path *pp, vector hwtabl
306 + if (mask & DI_WWID && !strlen(pp->wwid))
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))
316 - if (mask & DI_WWID && !strlen(pp->wwid))
322 Index: multipath-tools/libmultipath/prio.h
323 ===================================================================
324 --- multipath-tools.orig/libmultipath/prio.h
325 +++ multipath-tools/libmultipath/prio.h
327 #define PRIO_NETAPP "netapp"
328 #define PRIO_RANDOM "random"
329 #define PRIO_RDAC "rdac"
330 +#define PRIO_WEIGHTED "weighted"
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 = \
344 + libprioweighted.so \
348 Index: multipath-tools/libmultipath/prioritizers/weighted.c
349 ===================================================================
351 +++ multipath-tools/libmultipath/prioritizers/weighted.c
353 +/******************************************************************************
354 +*******************************************************************************
356 +** Copyright (C) 2009 Red Hat, Inc. All rights reserved.
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.
362 +*******************************************************************************
363 +******************************************************************************/
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
372 + * prio "weighted hbtl <regex> <prio> [<regex> <prio>]
373 + * prio "weighted devname <regex> <prio> [<regex> <prio>]
376 + * prio "weighted hbtl 4:* 2 3:.:.:. 1"
377 + * prio "weighted devname sda 2 sde 1"
386 +#include "weighted.h"
388 +#define DEFAULT_WEIGHTED_PRIO 0
390 +#define pp_weighted_log(prio, fmt, args...) \
391 + condlog(prio, "%s: weighted prio: " fmt, dev, ##args)
394 +next_str(char **str)
399 + next = strsep(str, " \t");
400 + } while (next && strcmp(next, "") == 0);
406 +match (char *dev, char *target, char *regex_str, char *prio_str,
407 + unsigned int *prio)
413 + size_t errbuf_size;
414 + unsigned int prio_match;
416 + if (sscanf(prio_str, "%u", &prio_match) != 1) {
417 + condlog(0, "%s: weighted prio: invalid prio '%s'", dev,
421 + err = regcomp(®ex, regex_str, REG_EXTENDED|REG_NOSUB);
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);
431 + if (regexec(®ex, target, 0, NULL, 0) == 0) {
432 + *prio = prio_match;
441 +prio_weighted(struct path * pp)
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;
449 + if (!pp->prio_args)
450 + return DEFAULT_WEIGHTED_PRIO;
451 + buff = args = strdup(pp->prio_args);
452 + ptr = next_str(&args);
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);
460 + condlog(0, "%s: weighted prio: invalid argument. Want 'hbtl' or 'devname'. Got '%s'", pp->dev, ptr);
464 + while ((ptr = next_str(&args)) != NULL) {
466 + prio_str = next_str(&args);
468 + condlog(0, "%s weighted prio: missing prio for regex '%s'", pp->dev, ptr);
471 + if (!regex_str || regex_size < strlen(ptr) + 3){
472 + regex_size = strlen(ptr) + 3;
473 + regex_str = realloc(regex_str, regex_size);
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))
488 +getprio(struct path * pp)
490 + return prio_weighted(pp);
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)
498 select_prio (struct path * pp)
500 + struct mpentry * mpe;
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);
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);
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);
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 {
532 struct checker checker;
533 struct multipath * mpp;
534 Index: multipath-tools/libmultipath/prioritizers/weighted.h
535 ===================================================================
537 +++ multipath-tools/libmultipath/prioritizers/weighted.h
542 +#define PRIO_WEIGHTED "weighted"
544 +int prio_weighted(struct path *pp);