Patch to implement weighted path priority routine in multipath-tools. Signed-off-by: Veena T S Sakshi Chaitanya Veni Vijayakumar Balasubramanian diff -pNur multipath-tools-0.4.8.org/libmultipath/config.c multipath-tools-0.4.8/libmultipath/config.c --- multipath-tools-0.4.8.org/libmultipath/config.c 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/config.c 2008-11-12 10:26:55.000000000 +0530 @@ -201,6 +201,12 @@ free_mpe (struct mpentry * mpe) if (mpe->alias) FREE(mpe->alias); + if (mpe->prio_name) + FREE(mpe->prio_name); + + if (mpe->prio_arg) + FREE(mpe->prio_arg); + FREE(mpe); } @@ -285,6 +291,7 @@ merge_hwe (struct hwentry * hwe1, struct merge_str(selector); merge_str(checker_name); merge_str(prio_name); + merge_str(prio_arg); merge_str(bl_product); merge_num(pgpolicy); merge_num(pgfailback); @@ -333,6 +340,9 @@ store_hwe (vector hwtable, struct hwentr if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name))) goto out; + if (dhwe->prio_arg && !(hwe->prio_arg = set_param_str(dhwe->prio_arg))) + goto out; + hwe->pgpolicy = dhwe->pgpolicy; hwe->pgfailback = dhwe->pgfailback; hwe->rr_weight = dhwe->rr_weight; @@ -547,8 +557,10 @@ load_config (char * file) !conf->hwhandler || !conf->bindings_file) goto out; - if (!conf->prio_name) + if (!conf->prio_name) { conf->prio_name = set_default(DEFAULT_PRIO); + conf->prio_arg = NULL; + } if (!conf->checker_name) conf->checker_name = set_default(DEFAULT_CHECKER); diff -pNur multipath-tools-0.4.8.org/libmultipath/config.h multipath-tools-0.4.8/libmultipath/config.h --- multipath-tools-0.4.8.org/libmultipath/config.h 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/config.h 2008-11-12 10:23:28.000000000 +0530 @@ -21,6 +21,7 @@ struct hwentry { char * selector; char * checker_name; char * prio_name; + char * prio_arg; int pgpolicy; int pgfailback; @@ -37,6 +38,8 @@ struct mpentry { char * getuid; char * selector; + char * prio_name; + char * prio_arg; int pgpolicy; int pgfailback; int rr_weight; @@ -75,6 +78,7 @@ struct config { char * hwhandler; char * bindings_file; char * prio_name; + char * prio_arg; char * checker_name; vector keywords; diff -pNur multipath-tools-0.4.8.org/libmultipath/dict.c multipath-tools-0.4.8/libmultipath/dict.c --- multipath-tools-0.4.8.org/libmultipath/dict.c 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/dict.c 2008-11-13 20:03:10.000000000 +0530 @@ -4,6 +4,7 @@ * Copyright (c) 2005 Benjamin Marzinski, Redhat * Copyright (c) 2005 Kiyoshi Ueda, NEC */ +#include #include "checkers.h" #include "vector.h" #include "hwtable.h" @@ -95,11 +96,29 @@ def_getuid_callout_handler(vector strvec static int def_prio_handler(vector strvec) { - conf->prio_name = set_value(strvec); + char *buff, *result, *temp; + char split_char[] = " \t"; - if (!conf->prio_name) + buff = set_value(strvec); + if (!buff) return 1; + temp = buff; + + while (temp) { + result = strsep(&temp, split_char); + if (strcmp(result, "")) { + if (prio_lookup(result)) { + conf->prio_name = STRDUP(result); + if (temp) + conf->prio_arg = STRDUP(temp); + else + conf->prio_arg = NULL; + break; + } + } + } + FREE(buff); return 0; } @@ -602,15 +621,32 @@ static int hw_prio_handler(vector strvec) { struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); + char *buff, *result, *temp; + char split_char[] = " \t"; if (!hwe) return 1; - hwe->prio_name = set_value(strvec); - - if (!hwe->prio_name) + buff = set_value(strvec); + if (!buff) return 1; + temp = buff; + while (temp) { + result = strsep(&temp, split_char); + if (strcmp(result, "")) { + if (prio_lookup(result)) { + hwe->prio_name = STRDUP(result); + if (temp) + hwe->prio_arg = STRDUP(temp); + else + hwe->prio_arg = NULL; + break; + } + } + } + + FREE(buff); return 0; } @@ -956,6 +992,41 @@ mp_pg_timeout_handler(vector strvec) return 0; } +static int +mp_prio_handler (vector strvec) +{ + struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); + char *buff, *result, *temp; + char split_char[] = " \t"; + + if (!mpe) + return 1; + + buff = set_value(strvec); + + if (!buff) + return 1; + + temp = buff; + + while (temp) { + result = strsep(&temp, split_char); + if (strcmp(result, "")) { + if (prio_lookup(result)) { + mpe->prio_name = STRDUP(result); + if (temp) + mpe->prio_arg = STRDUP(temp); + else + mpe->prio_arg = NULL; + break; + } + } + } + + FREE(buff); + return 0; +} + /* * config file keywords printing */ @@ -1091,6 +1162,17 @@ snprint_mp_pg_timeout (char * buff, int } static int +snprint_mp_prio(char * buff, int len, void * data) +{ + struct mpentry * mpe = (struct mpentry *)data; + + if (!mpe->prio_name) + return 0; + + return snprintf(buff, len, "%s", mpe->prio_name); +} + +static int snprint_hw_vendor (char * buff, int len, void * data) { struct hwentry * hwe = (struct hwentry *)data; @@ -1652,6 +1734,7 @@ init_keywords(void) install_keyword("alias", &alias_handler, &snprint_mp_alias); install_keyword("path_grouping_policy", &mp_pgpolicy_handler, &snprint_mp_path_grouping_policy); install_keyword("path_selector", &mp_selector_handler, &snprint_mp_selector); + install_keyword("prio", &mp_prio_handler, &snprint_mp_prio); install_keyword("failback", &mp_failback_handler, &snprint_mp_failback); install_keyword("rr_weight", &mp_weight_handler, &snprint_mp_rr_weight); install_keyword("no_path_retry", &mp_no_path_retry_handler, &snprint_mp_no_path_retry); diff -pNur multipath-tools-0.4.8.org/libmultipath/discovery.c multipath-tools-0.4.8/libmultipath/discovery.c --- multipath-tools-0.4.8.org/libmultipath/discovery.c 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/discovery.c 2008-11-13 19:43:55.000000000 +0530 @@ -759,8 +759,11 @@ pathinfo (struct path *pp, vector hwtabl * been successfully obtained before. */ if (mask & DI_PRIO && - (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF)) + (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF)) { + if (!strlen(pp->wwid)) + get_uid(pp); get_prio(pp); + } if (mask & DI_WWID && !strlen(pp->wwid)) get_uid(pp); diff -pNur multipath-tools-0.4.8.org/libmultipath/prio.h multipath-tools-0.4.8/libmultipath/prio.h --- multipath-tools-0.4.8.org/libmultipath/prio.h 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/prio.h 2008-11-13 22:41:11.000000000 +0530 @@ -24,6 +24,7 @@ #define PRIO_ONTAP "ontap" #define PRIO_RANDOM "random" #define PRIO_RDAC "rdac" +#define PRIO_WEIGHTED_PATH "weightedpath" /* * Value used to mark the fact prio was not defined diff -pNur multipath-tools-0.4.8.org/libmultipath/prioritizers/Makefile multipath-tools-0.4.8/libmultipath/prioritizers/Makefile --- multipath-tools-0.4.8.org/libmultipath/prioritizers/Makefile 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/prioritizers/Makefile 2008-11-11 18:11:07.000000000 +0530 @@ -12,7 +12,8 @@ LIBS = \ libpriordac.so \ libprioalua.so \ libprioontap.so \ - libpriohds.so + libpriohds.so \ + libprioweightedpath.so CFLAGS += -I.. diff -pNur multipath-tools-0.4.8.org/libmultipath/prioritizers/weightedpath.c multipath-tools-0.4.8/libmultipath/prioritizers/weightedpath.c --- multipath-tools-0.4.8.org/libmultipath/prioritizers/weightedpath.c 1970-01-01 05:30:00.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/prioritizers/weightedpath.c 2008-11-13 20:04:47.000000000 +0530 @@ -0,0 +1,99 @@ +/* + * + * (C) Copyright 2008 Hewlett-Packard Development Company, L.P + * + * This file is released under the GPL + */ + +/* + * Prioritizer for device mapper multipath, where specific paths and the + * corresponding priority values are provided as arguments. + * + * This prioritizer assigns the priority value provided in the configuration + * file based on the comparison made between the specified paths and the path + * instance for which this is called. + * Paths can be specified as a regular expression of devname of the path or + * as hbtl information of the path. + * + * Examples: + * prio "weightedpath hbtl 1:.:.:. 2 4:.:.:. 4" + * prio "weightedpath devname sda 10 sde 20" + * + * Returns zero as the default priority. + */ + +#include +#include + +#include +#include "weightedpath.h" +#include +#include +#include +#include +#include + +char *get_next_string(char **temp, char *split_char) +{ + char *token = NULL; + token = strsep(temp, split_char); + while (token != NULL && !strcmp(token, "")) + token = strsep(temp, split_char); + return token; +} + +/* main priority routine */ +int prio_path_weight(struct path *pp) +{ + char path[FILE_NAME_SIZE]; + char *arg; + char *temp, *regex, *prio; + char split_char[] = " \t"; + int priority = DEFAULT_PRIORITY, path_found = 0; + regex_t pathe; + + /* Return default priority if there is no argument */ + if (!pp->prio_arg) + return priority; + + arg = temp = STRDUP(pp->prio_arg); + + regex = get_next_string(&temp, split_char); + + if (!strcmp(regex, HBTL)) { + sprintf(path, "%d:%d:%d:%d", pp->sg_id.host_no, + pp->sg_id.channel, pp->sg_id.scsi_id, pp->sg_id.lun); + } else if (!strcmp(regex, DEV_NAME)) { + strcpy(path, pp->dev); + } else { + condlog(0, "%s: %s - Invalid arguments", pp->dev, + pp->prio->name); + return priority; + } + + while (!path_found) { + if (!temp) + break; + if (!(regex = get_next_string(&temp, split_char))) + break; + if (!(prio = get_next_string(&temp, split_char))) + break; + + if (!regcomp(&pathe, regex, REG_EXTENDED|REG_NOSUB)) { + if (!regexec(&pathe, path, 0, NULL, 0)) { + path_found = 1; + priority = atoi(prio); + } + regfree(&pathe); + } + } + + FREE(arg); + return priority; +} + +int getprio(struct path *pp) +{ + return prio_path_weight(pp); +} + diff -pNur multipath-tools-0.4.8.org/libmultipath/prioritizers/weightedpath.h multipath-tools-0.4.8/libmultipath/prioritizers/weightedpath.h --- multipath-tools-0.4.8.org/libmultipath/prioritizers/weightedpath.h 1970-01-01 05:30:00.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/prioritizers/weightedpath.h 2008-11-13 19:56:10.000000000 +0530 @@ -0,0 +1,11 @@ +#ifndef _WEIGHTED_PATH_H +#define _WEIGHTED_PATH_H + +#define PRIO_WEIGHTED_PATH "weightedpath" +#define HBTL "hbtl" +#define DEV_NAME "devname" +#define DEFAULT_PRIORITY 0 + +int prio_path_weight(struct path *pp); + +#endif diff -pNur multipath-tools-0.4.8.org/libmultipath/propsel.c multipath-tools-0.4.8/libmultipath/propsel.c --- multipath-tools-0.4.8.org/libmultipath/propsel.c 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/propsel.c 2008-11-13 19:58:58.000000000 +0530 @@ -258,14 +258,28 @@ select_getuid (struct path * pp) extern int select_prio (struct path * pp) { + struct mpentry * mpe; + + if ((mpe = find_mpe(pp->wwid))) { + if (mpe->prio_name) { + pp->prio = prio_lookup(mpe->prio_name); + pp->prio_arg = mpe->prio_arg; + condlog(3, "%s: prio = %s (LUN setting)", + pp->dev, pp->prio->name); + return 0; + } + } + if (pp->hwe && pp->hwe->prio_name) { pp->prio = prio_lookup(pp->hwe->prio_name); + pp->prio_arg = pp->hwe->prio_arg; condlog(3, "%s: prio = %s (controller setting)", pp->dev, pp->hwe->prio_name); return 0; } if (conf->prio_name) { pp->prio = prio_lookup(conf->prio_name); + pp->prio_arg = conf->prio_arg; condlog(3, "%s: prio = %s (config file default)", pp->dev, conf->prio_name); return 0; diff -pNur multipath-tools-0.4.8.org/libmultipath/structs.h multipath-tools-0.4.8/libmultipath/structs.h --- multipath-tools-0.4.8.org/libmultipath/structs.h 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/libmultipath/structs.h 2008-11-11 18:11:07.000000000 +0530 @@ -121,6 +121,7 @@ struct path { int pgindex; char * getuid; struct prio * prio; + char * prio_arg; struct checker checker; struct multipath * mpp; int fd; diff -pNur multipath-tools-0.4.8.org/multipath/multipath.conf.5 multipath-tools-0.4.8/multipath/multipath.conf.5 --- multipath-tools-0.4.8.org/multipath/multipath.conf.5 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/multipath/multipath.conf.5 2008-11-13 22:36:05.000000000 +0530 @@ -146,6 +146,24 @@ Generate the path priority for Hitachi H Default value is \fBnone\fR. .RE .TP +.B prio +The default program and args to path priority routine. The specified +routine should return a numeric value specifying the relative priority +of this path. Higher number have a higher priority. +.RS +.TP 12 +.B alua +Generate the path priority based on ALUA status of the path. +.TP 12 +.B weightedpath ... +.I hbtl +regex can be of SCSI H:B:T:L format Ex: 1:0:.:. , *:0:0:. +.I devname +regex can be of device name format Ex: sda , sd.e +Generate the path priority based on the regular expression and the +priority provided as argument. +.RE +.TP .B features Specify any device-mapper features to be used. Syntax is .I num list @@ -322,6 +340,8 @@ section: .TP .B path_selector .TP +.B prio +.TP .B failback .TP .B no_path_retry @@ -375,6 +395,8 @@ section: .TP .B path_checker .TP +.B prio +.TP .B features .TP .B prio_callout diff -pNur multipath-tools-0.4.8.org/multipath.conf.annotated multipath-tools-0.4.8/multipath.conf.annotated --- multipath-tools-0.4.8.org/multipath.conf.annotated 2008-11-11 18:11:56.000000000 +0530 +++ multipath-tools-0.4.8/multipath.conf.annotated 2008-11-12 18:29:01.000000000 +0530 @@ -261,6 +261,18 @@ # # default : 1000 # # # rr_min_io 100 +# +# # +# #name : prio +# #scope : multipath +# #desc : the function to call to obtain a path weight. +# # Weights are summed for each path group to +# # determine the next PG to use case of failure. +# #default : no callout, all paths equals +# # Ex: +# # prio alua +# # prio "weightedpath devname sda 50 sde 10 sdc 50 sdf 10" +# prio "weightedpath hbtl 1:.:.:. 2 4:.:.:. 4" # } # multipath { # wwid 1DEC_____321816758474