summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2014-09-16 18:22:40 -0500
committerBenjamin Marzinski <bmarzins@redhat.com>2014-09-16 18:22:40 -0500
commitefd38c93e9c0be988af2bc7e2d1d2d1931286ef5 (patch)
tree2dfc07fc06b8e30f4b0a11b5a7ff7fef6f59da30
parent2a2c963dcd724db5038f2975f91b378ff430b496 (diff)
device-mapper-multipath-0.4.9-68
Modify multipath.conf * remove getuid_callout example Re-add 0050-RH-listing-speedup.patch Add 0081-RHBZ-1066264-check-prefix-on-rename.patch * make multipath check the prefix on kpartx partitions during rename, and copy the existing behaviour Add 0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch * If async tur checker fails on threads, don't retry with the sync version Add 0083-RHBZ-1080055-orphan-paths-on-reload.patch * Fix case where pathlist wasn't getting updated properly Add 0084-RHBZ-1110000-multipath-man.patch * fix errors in multipath man page Add 0085-UPBZ-1110006-datacore-config.patch * Add support for DataCore Virtual Disk Add 0086-RHBZ-1110007-orphan-path-on-failed-add.patch * If multipathd fails to add path correctly, it now fully orphans the path Add 0087-RHBZ-1110013-config-error-checking.patch * Improve multipath.conf error checking. Add 0088-RHBZ-1069811-configurable-prio-timeout.patch * checker_timeout now adjusts the timeouts of the prioritizers as well. Add 0089-RHBZ-1110016-add-noasync-option.patch * Add a new defaults option, "force_sync", that disables the async mode of the path checkers. This is for cases where to many parallel checkers hog the cpu Add 0090-UPBZ-1080038-reorder-paths-for-round-robin.patch * make multipathd order paths for better throughput in round-robin mode Add 0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch * check for null pointers in configuration reading code. Add 0092-UPBZ-1104605-reload-on-rename.patch * Reload table on rename if necessary Add 0093-UPBZ-1086825-user-friendly-name-remap.patch * Keep existing user_friend_name if possible Add 0094-RHBZ-1086825-cleanup-remap.patch * Cleanup issues with upstream patch Add 0095-RHBZ-1127944-xtremIO-config.patch * Add support for EMC ExtremIO devices Add 0096-RHBZ-979474-new-wildcards.patch * Add N, n, R, and r path wildcards to print World Wide ids Add 0097-RH-fix-coverity-errors.patch * Fix a number of unterminated strings and memory leaks on failure paths. Add 0098-UPBZ-1067171-mutipath-i.patch * Add -i option to ignore wwids file when checking for valid paths Add 0099-RH-add-all-devs.patch * Add new devices config option all_devs. This makes the configuration overwrite the specified values in all builtin configs Add 0100-RHBZ-1067171-multipath-i-update.patch * make -i work correctly with find_multipaths Add 0101-RH-adapter-name-wildcard.patch * Add 'a' path wildcard to print adapter name
-rw-r--r--0050-RH-listing-speedup.patch17
-rw-r--r--0081-RHBZ-1066264-check-prefix-on-rename.patch41
-rw-r--r--0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch32
-rw-r--r--0083-RHBZ-1080055-orphan-paths-on-reload.patch85
-rw-r--r--0084-RHBZ-1110000-multipath-man.patch101
-rw-r--r--0085-UPBZ-1110006-datacore-config.patch28
-rw-r--r--0086-RHBZ-1110007-orphan-path-on-failed-add.patch17
-rw-r--r--0087-RHBZ-1110013-config-error-checking.patch190
-rw-r--r--0088-RHBZ-1069811-configurable-prio-timeout.patch178
-rw-r--r--0089-RHBZ-1110016-add-noasync-option.patch158
-rw-r--r--0090-UPBZ-1080038-reorder-paths-for-round-robin.patch529
-rw-r--r--0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch38
-rw-r--r--0092-UPBZ-1104605-reload-on-rename.patch63
-rw-r--r--0093-UPBZ-1086825-user-friendly-name-remap.patch199
-rw-r--r--0094-RHBZ-1086825-cleanup-remap.patch107
-rw-r--r--0095-RHBZ-1127944-xtremIO-config.patch28
-rw-r--r--0096-RHBZ-979474-new-wildcards.patch120
-rw-r--r--0097-RH-fix-coverity-errors.patch158
-rw-r--r--0098-UPBZ-1067171-mutipath-i.patch332
-rw-r--r--0099-RH-add-all-devs.patch170
-rw-r--r--0100-RHBZ-1067171-multipath-i-update.patch54
-rw-r--r--0101-RH-adapter-name-wildcard.patch33
-rw-r--r--device-mapper-multipath.spec100
-rw-r--r--multipath.conf2
24 files changed, 2775 insertions, 5 deletions
diff --git a/0050-RH-listing-speedup.patch b/0050-RH-listing-speedup.patch
new file mode 100644
index 0000000..4742634
--- /dev/null
+++ b/0050-RH-listing-speedup.patch
@@ -0,0 +1,17 @@
+---
+ multipath/main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools-130222/multipath/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipath/main.c
++++ multipath-tools-130222/multipath/main.c
+@@ -311,7 +311,7 @@ configure (void)
+ /*
+ * get a path list
+ */
+- if (conf->dev)
++ if (conf->dev && !conf->list)
+ di_flag = DI_WWID;
+
+ if (conf->list > 1)
diff --git a/0081-RHBZ-1066264-check-prefix-on-rename.patch b/0081-RHBZ-1066264-check-prefix-on-rename.patch
new file mode 100644
index 0000000..791f32e
--- /dev/null
+++ b/0081-RHBZ-1066264-check-prefix-on-rename.patch
@@ -0,0 +1,41 @@
+---
+ libmultipath/devmapper.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/devmapper.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/devmapper.c
++++ multipath-tools-130222/libmultipath/devmapper.c
+@@ -1151,6 +1151,8 @@ dm_rename_partmaps (char * old, char * n
+ unsigned long long size;
+ char dev_t[32];
+ int r = 1;
++ int offset;
++ char *delim;
+
+ if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
+ return 1;
+@@ -1171,6 +1173,11 @@ dm_rename_partmaps (char * old, char * n
+ if (dm_dev_t(old, &dev_t[0], 32))
+ goto out;
+
++ if (isdigit(new[strlen(new)-1]))
++ delim = "p";
++ else
++ delim = "";
++
+ do {
+ if (
+ /*
+@@ -1198,8 +1205,9 @@ dm_rename_partmaps (char * old, char * n
+ * then it's a kpartx generated partition.
+ * Rename it.
+ */
+- snprintf(buff, PARAMS_SIZE, "%s%s",
+- new, names->name + strlen(old));
++ for (offset = strlen(old); names->name[offset] && !(isdigit(names->name[offset])); offset++); /* do nothing */
++ snprintf(buff, PARAMS_SIZE, "%s%s%s",
++ new, delim, names->name + offset);
+ dm_rename(names->name, buff);
+ condlog(4, "partition map %s renamed",
+ names->name);
diff --git a/0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch b/0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch
new file mode 100644
index 0000000..9a1bd34
--- /dev/null
+++ b/0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch
@@ -0,0 +1,32 @@
+---
+ libmultipath/checkers/tur.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/checkers/tur.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/checkers/tur.c
++++ multipath-tools-130222/libmultipath/checkers/tur.c
+@@ -409,7 +409,6 @@ libcheck_check (struct checker * c)
+ ct->running = 0;
+ MSG(c, MSG_TUR_TIMEOUT);
+ tur_status = PATH_DOWN;
+- ct->state = PATH_UNCHECKED;
+ } else {
+ condlog(3, "%d:%d: tur checker not finished",
+ TUR_DEVT(ct));
+@@ -426,12 +425,10 @@ libcheck_check (struct checker * c)
+ pthread_mutex_unlock(&ct->lock);
+ } else {
+ if (ct->thread) {
+- /* pthread cancel failed. continue in sync mode */
+ pthread_mutex_unlock(&ct->lock);
+- condlog(3, "%d:%d: tur thread not responding, "
+- "using sync mode", TUR_DEVT(ct));
+- return tur_check(c->fd, c->timeout, c->message,
+- ct->wwid);
++ condlog(3, "%d:%d: tur thread not responding, ",
++ TUR_DEVT(ct));
++ return PATH_DOWN;
+ }
+ /* Start new TUR checker */
+ ct->state = PATH_UNCHECKED;
diff --git a/0083-RHBZ-1080055-orphan-paths-on-reload.patch b/0083-RHBZ-1080055-orphan-paths-on-reload.patch
new file mode 100644
index 0000000..8eaee74
--- /dev/null
+++ b/0083-RHBZ-1080055-orphan-paths-on-reload.patch
@@ -0,0 +1,85 @@
+---
+ libmultipath/structs_vec.c | 31 +++++++++++++++++++++++++++----
+ multipathd/main.c | 4 ++++
+ 2 files changed, 31 insertions(+), 4 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/structs_vec.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/structs_vec.c
++++ multipath-tools-130222/libmultipath/structs_vec.c
+@@ -280,12 +280,38 @@ update_multipath_status (struct multipat
+ return 0;
+ }
+
++void sync_paths(struct multipath *mpp, vector pathvec)
++{
++ struct path *pp;
++ struct pathgroup *pgp;
++ int found, i, j;
++
++ vector_foreach_slot (mpp->paths, pp, i) {
++ found = 0;
++ vector_foreach_slot(mpp->pg, pgp, j) {
++ if (find_slot(pgp->paths, (void *)pp) != -1) {
++ found = 1;
++ break;
++ }
++ }
++ if (!found) {
++ condlog(3, "%s dropped path %s", mpp->alias, pp->dev);
++ vector_del_slot(mpp->paths, i--);
++ orphan_path(pp);
++ }
++ }
++ update_mpp_paths(mpp, pathvec);
++ vector_foreach_slot (mpp->paths, pp, i)
++ pp->mpp = mpp;
++}
++
+ extern int
+ update_multipath_strings (struct multipath *mpp, vector pathvec)
+ {
+ if (!mpp)
+ return 1;
+
++ update_mpp_paths(mpp, pathvec);
+ condlog(4, "%s: %s", mpp->alias, __FUNCTION__);
+
+ free_multipath_attributes(mpp);
+@@ -294,6 +320,7 @@ update_multipath_strings (struct multipa
+
+ if (update_multipath_table(mpp, pathvec))
+ return 1;
++ sync_paths(mpp, pathvec);
+
+ if (update_multipath_status(mpp))
+ return 1;
+@@ -494,13 +521,9 @@ int update_multipath (struct vectors *ve
+ return 2;
+ }
+
+- free_pgvec(mpp->pg, KEEP_PATHS);
+- mpp->pg = NULL;
+-
+ if (__setup_multipath(vecs, mpp, reset))
+ return 1; /* mpp freed in setup_multipath */
+
+- adopt_paths(vecs->pathvec, mpp, 0);
+ /*
+ * compare checkers states with DM states
+ */
+Index: multipath-tools-130222/multipathd/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/main.c
++++ multipath-tools-130222/multipathd/main.c
+@@ -1152,6 +1152,10 @@ check_path (struct vectors * vecs, struc
+ pp->dev);
+ pp->dmstate = PSTATE_UNDEF;
+ }
++ /* if update_multipath_strings orphaned the path, quit early */
++ if (!pp->mpp)
++ return;
++
+ pp->chkrstate = newstate;
+ if (newstate != pp->state) {
+ int oldstate = pp->state;
diff --git a/0084-RHBZ-1110000-multipath-man.patch b/0084-RHBZ-1110000-multipath-man.patch
new file mode 100644
index 0000000..4ea422a
--- /dev/null
+++ b/0084-RHBZ-1110000-multipath-man.patch
@@ -0,0 +1,101 @@
+---
+ libmultipath/prioritizers/alua.c | 4 ++--
+ multipathd/multipathd.8 | 37 +++++++++++++++++++++++++++++++++----
+ 2 files changed, 35 insertions(+), 6 deletions(-)
+
+Index: multipath-tools-130222/multipathd/multipathd.8
+===================================================================
+--- multipath-tools-130222.orig/multipathd/multipathd.8
++++ multipath-tools-130222/multipathd/multipathd.8
+@@ -42,6 +42,9 @@ format wildcards.
+ .B list|show maps|multipaths
+ Show the multipath devices that the multipathd is monitoring.
+ .TP
++.B list|show daemon
++Show the current state of the multipathd daemon
++.TP
+ .B list|show maps|multipaths format $format
+ Show the status of all multipath devices that the multipathd is monitoring,
+ using a format string with multipath format wildcards.
+@@ -83,16 +86,16 @@ Add a path to the list of monitored path
+ .B remove|del path $path
+ Stop monitoring a path. $path is as listed in /sys/block (e.g. sda).
+ .TP
+-.B add map $map
++.B add map|multipath $map
+ Add a multipath device to the list of monitored devices. $map can either be a device-mapper device as listed in /sys/block (e.g. dm-0) or it can be the alias for the multipath device (e.g. mpath1) or the uid of the multipath device (e.g. 36005076303ffc56200000000000010aa).
+ .TP
+-.B remove|del map $map
++.B remove|del map|multipath $map
+ Stop monitoring a multipath device.
+ .TP
+ .B resize map|multipath $map
+ Resizes map $map to the given size
+ .TP
+-.B switch|switchgroup map $map group $group
++.B switch|switchgroup map|multipath $map group $group
+ Force a multipath device to switch to a specific path group. $group is the path group index, starting with 1.
+ .TP
+ .B reconfigure
+@@ -104,6 +107,13 @@ Sets map $map into suspend state.
+ .B resume map|multipath $map
+ Resumes map $map from suspend state.
+ .TP
++.B reset map|multipath $map
++Reassign existing device-mapper table(s) use use the multipath device, instead
++of its path devices.
++.TP
++.B reload map|multipath $map
++Reload a multipath device.
++.TP
+ .B fail path $path
+ Sets path $path into failed state.
+ .TP
+@@ -120,10 +130,29 @@ Restore queueing on all multipath device
+ Disable queuing on multipathed map $map
+ .TP
+ .B restorequeueing map|multipath $map
+-Restore queuing on multipahted map $map
++Restore queuing on multipathed map $map
++.TP
++.B forcequeueing daemon
++Forces multipathd into queue_without_daemon mode, so that no_path_retry queueing
++will not be disabled when the daemon stops
++.TP
++.B restorequeueing daemon
++Restores configured queue_without_daemon mode
++.TP
++.B map|multipath $map setprstatus
++Enable persistent reservation management on $map
++.TP
++.B map|multipath $map unsetprstatus
++Disable persistent reservation management on $map
++.TP
++.B map|multipath $map getprstatus
++Get the current persistent reservation management status of $map
+ .TP
+ .B quit|exit
+ End interactive session.
++.TP
++.B shutdown
++Stop multipathd.
+
+ .SH "SEE ALSO"
+ .BR multipath (8)
+Index: multipath-tools-130222/libmultipath/prioritizers/alua.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prioritizers/alua.c
++++ multipath-tools-130222/libmultipath/prioritizers/alua.c
+@@ -119,10 +119,10 @@ int getprio (struct path * pp, char * ar
+ condlog(0, "%s: couldn't get target port group", pp->dev);
+ break;
+ case ALUA_PRIO_GETAAS_FAILED:
+- condlog(0, "%s: couln't get asymmetric access state", pp->dev);
++ condlog(0, "%s: couldn't get asymmetric access state", pp->dev);
+ break;
+ case ALUA_PRIO_TPGS_FAILED:
+- condlog(3, "%s: couln't get supported alua states", pp->dev);
++ condlog(3, "%s: couldn't get supported alua states", pp->dev);
+ break;
+ }
+ }
diff --git a/0085-UPBZ-1110006-datacore-config.patch b/0085-UPBZ-1110006-datacore-config.patch
new file mode 100644
index 0000000..cedb5e3
--- /dev/null
+++ b/0085-UPBZ-1110006-datacore-config.patch
@@ -0,0 +1,28 @@
+---
+ libmultipath/hwtable.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+Index: multipath-tools-130222/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/hwtable.c
++++ multipath-tools-130222/libmultipath/hwtable.c
+@@ -1108,6 +1108,19 @@ static struct hwentry default_hw[] = {
+ .prio_name = PRIO_ALUA,
+ .prio_args = NULL,
+ },
++ {
++ .vendor = "DataCore",
++ .product = "Virtual Disk",
++ .features = DEFAULT_FEATURES,
++ .hwhandler = DEFAULT_HWHANDLER,
++ .pgpolicy = GROUP_BY_PRIO,
++ .pgfailback = -FAILBACK_IMMEDIATE,
++ .rr_weight = RR_WEIGHT_NONE,
++ .no_path_retry = NO_PATH_RETRY_QUEUE,
++ .checker_name = TUR,
++ .prio_name = PRIO_ALUA,
++ .prio_args = NULL,
++ },
+ /*
+ * EOL
+ */
diff --git a/0086-RHBZ-1110007-orphan-path-on-failed-add.patch b/0086-RHBZ-1110007-orphan-path-on-failed-add.patch
new file mode 100644
index 0000000..0d6aa58
--- /dev/null
+++ b/0086-RHBZ-1110007-orphan-path-on-failed-add.patch
@@ -0,0 +1,17 @@
+---
+ multipathd/main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools-130222/multipathd/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/main.c
++++ multipath-tools-130222/multipathd/main.c
+@@ -562,7 +562,7 @@ rescan:
+ return 0;
+ }
+ else
+- return 1;
++ goto fail;
+
+ fail_map:
+ remove_map(mpp, vecs, 1);
diff --git a/0087-RHBZ-1110013-config-error-checking.patch b/0087-RHBZ-1110013-config-error-checking.patch
new file mode 100644
index 0000000..c774bc5
--- /dev/null
+++ b/0087-RHBZ-1110013-config-error-checking.patch
@@ -0,0 +1,190 @@
+---
+ libmultipath/parser.c | 154 ++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 126 insertions(+), 28 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/parser.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/parser.c
++++ multipath-tools-130222/libmultipath/parser.c
+@@ -395,36 +395,57 @@ set_value(vector strvec)
+ char *alloc = NULL;
+ char *tmp;
+
+- if (!str)
++ if (!str) {
++ condlog(0, "option '%s' missing value",
++ (char *)VECTOR_SLOT(strvec, 0));
+ return NULL;
+-
++ }
+ size = strlen(str);
+- if (size == 0)
++ if (size == 0) {
++ condlog(0, "option '%s' has empty value",
++ (char *)VECTOR_SLOT(strvec, 0));
+ return NULL;
+-
+- if (*str == '"') {
+- for (i = 2; i < VECTOR_SIZE(strvec); i++) {
+- str = VECTOR_SLOT(strvec, i);
+- len += strlen(str);
+- if (!alloc)
+- alloc =
+- (char *) MALLOC(sizeof (char *) *
+- (len + 1));
+- else {
+- alloc =
+- REALLOC(alloc, sizeof (char *) * (len + 1));
+- tmp = VECTOR_SLOT(strvec, i-1);
+- if (alloc && *str != '"' && *tmp != '"')
+- strncat(alloc, " ", 1);
+- }
+-
+- if (alloc && i != VECTOR_SIZE(strvec)-1)
+- strncat(alloc, str, strlen(str));
+- }
+- } else {
+- alloc = MALLOC(sizeof (char *) * (size + 1));
++ }
++ if (*str != '"') {
++ alloc = MALLOC(sizeof (char) * (size + 1));
+ if (alloc)
+ memcpy(alloc, str, size);
++ else
++ condlog(0, "can't allocate memeory for option '%s'",
++ (char *)VECTOR_SLOT(strvec, 0));
++ return alloc;
++ }
++ /* Even empty quotes counts as a value (An empty string) */
++ alloc = (char *) MALLOC(sizeof (char));
++ if (!alloc) {
++ condlog(0, "can't allocate memeory for option '%s'",
++ (char *)VECTOR_SLOT(strvec, 0));
++ return NULL;
++ }
++ for (i = 2; i < VECTOR_SIZE(strvec); i++) {
++ str = VECTOR_SLOT(strvec, i);
++ if (!str) {
++ free(alloc);
++ condlog(0, "parse error for option '%s'",
++ (char *)VECTOR_SLOT(strvec, 0));
++ return NULL;
++ }
++ if (*str == '"')
++ break;
++ tmp = alloc;
++ /* The first +1 is for the NULL byte. The rest are for the
++ * spaces between words */
++ len += strlen(str) + 1;
++ alloc = REALLOC(alloc, sizeof (char) * len);
++ if (!alloc) {
++ FREE(tmp);
++ condlog(0, "can't allocate memeory for option '%s'",
++ (char *)VECTOR_SLOT(strvec, 0));
++ return NULL;
++ }
++ if (*alloc != '\0')
++ strncat(alloc, " ", 1);
++ strncat(alloc, str, strlen(str));
+ }
+ return alloc;
+ }
+@@ -465,6 +486,74 @@ void free_uniques(vector uniques)
+ }
+
+ int
++is_sublevel_keyword(char *str)
++{
++ return (strcmp(str, "defaults") == 0 || strcmp(str, "blacklist") == 0 ||
++ strcmp(str, "blacklist_exceptions") == 0 ||
++ strcmp(str, "devices") == 0 || strcmp(str, "devices") == 0 ||
++ strcmp(str, "device") == 0 || strcmp(str, "multipaths") == 0 ||
++ strcmp(str, "multipath") == 0);
++}
++
++int
++validate_config_strvec(vector strvec)
++{
++ char *str;
++ int i;
++
++ str = VECTOR_SLOT(strvec, 0);
++ if (str == NULL) {
++ condlog(0, "can't parse option on line %d of config file",
++ line_nr);
++ return -1;
++ }
++ if (*str == '}') {
++ if (VECTOR_SIZE(strvec) > 1)
++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 1), line_nr);
++ return 0;
++ }
++ if (*str == '{') {
++ condlog(0, "invalid keyword '%s' on line %d of config file", str, line_nr);
++ return -1;
++ }
++ if (is_sublevel_keyword(str)) {
++ str = VECTOR_SLOT(strvec, 1);
++ if (str == NULL)
++ condlog(0, "missing '{' on line %d of config file", line_nr);
++ else if (*str != '{')
++ condlog(0, "expecting '{' on line %d of config file. found '%s'", line_nr, str);
++ else if (VECTOR_SIZE(strvec) > 2)
++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr);
++ return 0;
++ }
++ str = VECTOR_SLOT(strvec, 1);
++ if (str == NULL) {
++ condlog(0, "missing value for option '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 0), line_nr);
++ return -1;
++ }
++ if (*str != '"') {
++ if (VECTOR_SIZE(strvec) > 2)
++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr);
++ return 0;
++ }
++ for (i = 2; i < VECTOR_SIZE(strvec); i++) {
++ str = VECTOR_SLOT(strvec, i);
++ if (str == NULL) {
++ condlog(0, "can't parse value on line %d of config file", line_nr);
++ return -1;
++ }
++ if (*str == '"') {
++ if (VECTOR_SIZE(strvec) > i + 1)
++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr);
++ return 0;
++ }
++ }
++ condlog(0, "missing closing quotes on line %d of config file",
++ line_nr);
++ return 0;
++}
++
++int
+ process_stream(vector keywords)
+ {
+ int i;
+@@ -494,11 +583,20 @@ process_stream(vector keywords)
+ if (!strvec)
+ continue;
+
++ if (validate_config_strvec(strvec) != 0) {
++ free_strvec(strvec);
++ continue;
++ }
++
+ str = VECTOR_SLOT(strvec, 0);
+
+- if (!strcmp(str, EOB) && kw_level > 0) {
+- free_strvec(strvec);
+- break;
++ if (!strcmp(str, EOB)) {
++ if (kw_level > 0) {
++ free_strvec(strvec);
++ break;
++ }
++ condlog(0, "unmatched '%s' at line %d of config file",
++ EOB, line_nr);
+ }
+
+ for (i = 0; i < VECTOR_SIZE(keywords); i++) {
diff --git a/0088-RHBZ-1069811-configurable-prio-timeout.patch b/0088-RHBZ-1069811-configurable-prio-timeout.patch
new file mode 100644
index 0000000..60f374b
--- /dev/null
+++ b/0088-RHBZ-1069811-configurable-prio-timeout.patch
@@ -0,0 +1,178 @@
+---
+ libmultipath/prio.c | 7 +++++++
+ libmultipath/prio.h | 1 +
+ libmultipath/prioritizers/alua_rtpg.c | 5 +++--
+ libmultipath/prioritizers/emc.c | 2 +-
+ libmultipath/prioritizers/hds.c | 2 +-
+ libmultipath/prioritizers/hp_sw.c | 2 +-
+ libmultipath/prioritizers/ontap.c | 4 ++--
+ libmultipath/prioritizers/rdac.c | 2 +-
+ multipath.conf.annotated | 5 +++--
+ multipath/multipath.conf.5 | 4 ++--
+ 10 files changed, 22 insertions(+), 12 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/prio.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prio.c
++++ multipath-tools-130222/libmultipath/prio.c
+@@ -10,6 +10,13 @@
+
+ static LIST_HEAD(prioritizers);
+
++unsigned int get_prio_timeout(unsigned int default_timeout)
++{
++ if (conf->checker_timeout)
++ return conf->checker_timeout * 1000;
++ return default_timeout;
++}
++
+ int init_prio (void)
+ {
+ if (!add_prio(DEFAULT_PRIO))
+Index: multipath-tools-130222/libmultipath/prio.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prio.h
++++ multipath-tools-130222/libmultipath/prio.h
+@@ -51,6 +51,7 @@ struct prio {
+ int (*getprio)(struct path *, char *);
+ };
+
++unsigned int get_prio_timeout(unsigned int default_timeout);
+ int init_prio (void);
+ void cleanup_prio (void);
+ struct prio * add_prio (char *);
+Index: multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prioritizers/alua_rtpg.c
++++ multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c
+@@ -21,6 +21,7 @@
+ #define __user
+ #include <scsi/sg.h>
+
++#include "../prio.h"
+ #include "alua_rtpg.h"
+
+ #define SENSE_BUFF_LEN 32
+@@ -134,7 +135,7 @@ do_inquiry(int fd, int evpd, unsigned in
+ hdr.dxfer_len = resplen;
+ hdr.sbp = sense;
+ hdr.mx_sb_len = sizeof(sense);
+- hdr.timeout = DEF_TIMEOUT;
++ hdr.timeout = get_prio_timeout(DEF_TIMEOUT);
+
+ if (ioctl(fd, SG_IO, &hdr) < 0) {
+ PRINT_DEBUG("do_inquiry: IOCTL failed!\n");
+@@ -253,7 +254,7 @@ do_rtpg(int fd, void* resp, long resplen
+ hdr.dxfer_len = resplen;
+ hdr.mx_sb_len = sizeof(sense);
+ hdr.sbp = sense;
+- hdr.timeout = DEF_TIMEOUT;
++ hdr.timeout = get_prio_timeout(DEF_TIMEOUT);
+
+ if (ioctl(fd, SG_IO, &hdr) < 0)
+ return -RTPG_RTPG_FAILED;
+Index: multipath-tools-130222/libmultipath/prioritizers/emc.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prioritizers/emc.c
++++ multipath-tools-130222/libmultipath/prioritizers/emc.c
+@@ -31,7 +31,7 @@ int emc_clariion_prio(const char *dev, i
+ io_hdr.dxferp = sense_buffer;
+ io_hdr.cmdp = inqCmdBlk;
+ io_hdr.sbp = sb;
+- io_hdr.timeout = 60000;
++ io_hdr.timeout = get_prio_timeout(60000);
+ io_hdr.pack_id = 0;
+ if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+ pp_emc_log(0, "sending query command failed");
+Index: multipath-tools-130222/libmultipath/prioritizers/hds.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prioritizers/hds.c
++++ multipath-tools-130222/libmultipath/prioritizers/hds.c
+@@ -114,7 +114,7 @@ int hds_modular_prio (const char *dev, i
+ io_hdr.dxferp = inqBuff;
+ io_hdr.cmdp = inqCmdBlk;
+ io_hdr.sbp = sense_buffer;
+- io_hdr.timeout = 2000; /* TimeOut = 2 seconds */
++ io_hdr.timeout = get_prio_timeout(2000); /* TimeOut = 2 seconds */
+
+ if (ioctl (fd, SG_IO, &io_hdr) < 0) {
+ pp_hds_log(0, "SG_IO error");
+Index: multipath-tools-130222/libmultipath/prioritizers/hp_sw.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prioritizers/hp_sw.c
++++ multipath-tools-130222/libmultipath/prioritizers/hp_sw.c
+@@ -46,7 +46,7 @@ int hp_sw_prio(const char *dev, int fd)
+ io_hdr.dxfer_direction = SG_DXFER_NONE;
+ io_hdr.cmdp = turCmdBlk;
+ io_hdr.sbp = sb;
+- io_hdr.timeout = 60000;
++ io_hdr.timeout = get_prio_timeout(60000);
+ io_hdr.pack_id = 0;
+ retry:
+ if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+Index: multipath-tools-130222/libmultipath/prioritizers/ontap.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prioritizers/ontap.c
++++ multipath-tools-130222/libmultipath/prioritizers/ontap.c
+@@ -89,7 +89,7 @@ static int send_gva(const char *dev, int
+ io_hdr.dxferp = results;
+ io_hdr.cmdp = cdb;
+ io_hdr.sbp = sb;
+- io_hdr.timeout = SG_TIMEOUT;
++ io_hdr.timeout = get_prio_timeout(SG_TIMEOUT);
+ io_hdr.pack_id = 0;
+ if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+ pp_ontap_log(0, "SG_IO ioctl failed, errno=%d", errno);
+@@ -141,7 +141,7 @@ static int get_proxy(const char *dev, in
+ io_hdr.dxferp = results;
+ io_hdr.cmdp = cdb;
+ io_hdr.sbp = sb;
+- io_hdr.timeout = SG_TIMEOUT;
++ io_hdr.timeout = get_prio_timeout(SG_TIMEOUT);
+ io_hdr.pack_id = 0;
+ if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+ pp_ontap_log(0, "ioctl sending inquiry command failed, "
+Index: multipath-tools-130222/libmultipath/prioritizers/rdac.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prioritizers/rdac.c
++++ multipath-tools-130222/libmultipath/prioritizers/rdac.c
+@@ -31,7 +31,7 @@ int rdac_prio(const char *dev, int fd)
+ io_hdr.dxferp = sense_buffer;
+ io_hdr.cmdp = inqCmdBlk;
+ io_hdr.sbp = sb;
+- io_hdr.timeout = 60000;
++ io_hdr.timeout = get_prio_timeout(60000);
+ io_hdr.pack_id = 0;
+ if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+ pp_rdac_log(0, "sending inquiry command failed");
+Index: multipath-tools-130222/multipath.conf.annotated
+===================================================================
+--- multipath-tools-130222.orig/multipath.conf.annotated
++++ multipath-tools-130222/multipath.conf.annotated
+@@ -188,8 +188,9 @@
+ # #
+ # # name : checker_timeout
+ # # scope : multipath & multipathd
+-# # desc : The timeout to use for path checkers that issue scsi
+-# # commands with an explicit timeout, in seconds.
++# # desc : The timeout to use for path checkers and prioritizers
++# # that issue scsi commands with an explicit timeout, in
++# # seconds.
+ # # values : n > 0
+ # # default : taken from /sys/block/sd<x>/device/timeout
+ # checker_timeout 60
+Index: multipath-tools-130222/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools-130222.orig/multipath/multipath.conf.5
++++ multipath-tools-130222/multipath/multipath.conf.5
+@@ -321,8 +321,8 @@ maximum number of open fds is taken from
+ if that number is greated than 1024.
+ .TP
+ .B checker_timeout
+-Specify the timeout to user for path checkers that issue scsi commands with an
+-explicit timeout, in seconds; default taken from
++Specify the timeout to use for path checkers and prioritizers that issue scsi
++commands with an explicit timeout, in seconds; default taken from
+ .I /sys/block/sd<x>/device/timeout
+ .TP
+ .B fast_io_fail_tmo
diff --git a/0089-RHBZ-1110016-add-noasync-option.patch b/0089-RHBZ-1110016-add-noasync-option.patch
new file mode 100644
index 0000000..2651c0e
--- /dev/null
+++ b/0089-RHBZ-1110016-add-noasync-option.patch
@@ -0,0 +1,158 @@
+---
+ libmultipath/config.c | 1 +
+ libmultipath/config.h | 1 +
+ libmultipath/dict.c | 33 +++++++++++++++++++++++++++++++++
+ libmultipath/discovery.c | 8 ++++++--
+ multipath.conf.annotated | 10 ++++++++++
+ multipath/multipath.conf.5 | 9 +++++++++
+ 6 files changed, 60 insertions(+), 2 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/config.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/config.c
++++ multipath-tools-130222/libmultipath/config.c
+@@ -556,6 +556,7 @@ load_config (char * file, struct udev *u
+ conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
+ conf->detect_prio = DEFAULT_DETECT_PRIO;
+ conf->hw_strmatch = 0;
++ conf->force_sync = 0;
+
+ /*
+ * preload default hwtable
+Index: multipath-tools-130222/libmultipath/config.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/config.h
++++ multipath-tools-130222/libmultipath/config.h
+@@ -115,6 +115,7 @@ struct config {
+ int reassign_maps;
+ int retain_hwhandler;
+ int detect_prio;
++ int force_sync;
+ unsigned int version[3];
+
+ char * dev;
+Index: multipath-tools-130222/libmultipath/dict.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/dict.c
++++ multipath-tools-130222/libmultipath/dict.c
+@@ -712,6 +712,29 @@ def_hw_strmatch_handler(vector strvec)
+ return 0;
+ }
+
++static int
++def_force_sync_handler(vector strvec)
++{
++ char * buff;
++
++ buff = set_value(strvec);
++
++ if (!buff)
++ return 1;
++
++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "0")))
++ conf->force_sync = 0;
++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "1")))
++ conf->force_sync = 1;
++ else
++ conf->force_sync = 0;
++
++ FREE(buff);
++ return 0;
++}
++
+ /*
+ * blacklist block handlers
+ */
+@@ -2822,6 +2845,15 @@ snprint_def_hw_strmatch(char * buff, int
+ }
+
+ static int
++snprint_def_force_sync(char * buff, int len, void * data)
++{
++ if (conf->force_sync)
++ return snprintf(buff, len, "yes");
++ else
++ return snprintf(buff, len, "no");
++}
++
++static int
+ snprint_ble_simple (char * buff, int len, void * data)
+ {
+ struct blentry * ble = (struct blentry *)data;
+@@ -2889,6 +2921,7 @@ init_keywords(void)
+ install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler_handler);
+ install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio);
+ install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch);
++ install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync);
+ __deprecated install_keyword("default_selector", &def_selector_handler, NULL);
+ __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
+ __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
+Index: multipath-tools-130222/libmultipath/discovery.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/discovery.c
++++ multipath-tools-130222/libmultipath/discovery.c
+@@ -952,8 +952,12 @@ get_state (struct path * pp, int daemon)
+ }
+ }
+ checker_clear_message(c);
+- if (daemon)
+- checker_set_async(c);
++ if (daemon) {
++ if (conf->force_sync == 0)
++ checker_set_async(c);
++ else
++ checker_set_sync(c);
++ }
+ if (!conf->checker_timeout &&
+ (pp->bus != SYSFS_BUS_SCSI ||
+ sysfs_get_timeout(pp, &(c->timeout))))
+Index: multipath-tools-130222/multipath.conf.annotated
+===================================================================
+--- multipath-tools-130222.orig/multipath.conf.annotated
++++ multipath-tools-130222/multipath.conf.annotated
+@@ -214,6 +214,8 @@
+ # # values : n > 0
+ # # default : determined by the OS
+ # dev_loss_tmo 600
++#
++# #
+ # # name : bindings_file
+ # # scope : multipath
+ # # desc : The location of the bindings file that is used with
+@@ -222,6 +224,14 @@
+ # # default : "/var/lib/multipath/bindings"
+ # bindings_file "/etc/multipath_bindings"
+ #
++# #
++# # name : force_sync
++# # scope : multipathd
++# # desc : If set to yes, multipath will run all of the checkers in
++# # sync mode, even if the checker has an async mode.
++# # values : yes|no
++# # default : no
++# force_sync yes
+ #}
+ #
+ ##
+Index: multipath-tools-130222/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools-130222.orig/multipath/multipath.conf.5
++++ multipath-tools-130222/multipath/multipath.conf.5
+@@ -411,6 +411,15 @@ modify an existing config, or create a n
+ , the user device configs will be regular expression matched against the
+ built-in configs instead. Default is
+ .I no
++.TP
++.B force_sync
++If set to
++.I yes
++, multipathd will call the path checkers in sync mode only. This means that
++only one checker will run at a time. This is useful in the case where many
++multipathd checkers running in parallel causes significant CPU pressure. The
++Default is
++.I no
+ .
+ .SH "blacklist section"
+ The
diff --git a/0090-UPBZ-1080038-reorder-paths-for-round-robin.patch b/0090-UPBZ-1080038-reorder-paths-for-round-robin.patch
new file mode 100644
index 0000000..44f8407
--- /dev/null
+++ b/0090-UPBZ-1080038-reorder-paths-for-round-robin.patch
@@ -0,0 +1,529 @@
+---
+ libmultipath/configure.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++
+ libmultipath/configure.h | 2
+ libmultipath/discovery.c | 87 +++++++++++++++++
+ libmultipath/discovery.h | 2
+ libmultipath/structs.c | 84 +++++++++++++++++
+ libmultipath/structs.h | 25 ++++-
+ 6 files changed, 427 insertions(+), 2 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/configure.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/configure.c
++++ multipath-tools-130222/libmultipath/configure.c
+@@ -39,6 +39,219 @@
+ #include "uxsock.h"
+ #include "wwids.h"
+
++/* group paths in pg by host adapter
++ */
++int group_by_host_adapter(struct pathgroup *pgp, vector adapters)
++{
++ struct adapter_group *agp;
++ struct host_group *hgp;
++ struct path *pp, *pp1;
++ char adapter_name1[SLOT_NAME_SIZE];
++ char adapter_name2[SLOT_NAME_SIZE];
++ int i, j;
++ int found_hostgroup = 0;
++
++ while (VECTOR_SIZE(pgp->paths) > 0) {
++
++ pp = VECTOR_SLOT(pgp->paths, 0);
++
++ if (sysfs_get_host_adapter_name(pp, adapter_name1))
++ goto out;
++ /* create a new host adapter group
++ */
++ agp = alloc_adaptergroup();
++ if (!agp)
++ goto out;
++ agp->pgp = pgp;
++
++ strncpy(agp->adapter_name, adapter_name1, SLOT_NAME_SIZE);
++ store_adaptergroup(adapters, agp);
++
++ /* create a new host port group
++ */
++ hgp = alloc_hostgroup();
++ if (!hgp)
++ goto out;
++ if (store_hostgroup(agp->host_groups, hgp))
++ goto out;
++
++ hgp->host_no = pp->sg_id.host_no;
++ agp->num_hosts++;
++ if (store_path(hgp->paths, pp))
++ goto out;
++
++ hgp->num_paths++;
++ /* delete path from path group
++ */
++ vector_del_slot(pgp->paths, 0);
++
++ /* add all paths belonging to same host adapter
++ */
++ vector_foreach_slot(pgp->paths, pp1, i) {
++ if (sysfs_get_host_adapter_name(pp1, adapter_name2))
++ goto out;
++ if (strcmp(adapter_name1, adapter_name2) == 0) {
++ found_hostgroup = 0;
++ vector_foreach_slot(agp->host_groups, hgp, j) {
++ if (hgp->host_no == pp1->sg_id.host_no) {
++ if (store_path(hgp->paths, pp1))
++ goto out;
++ hgp->num_paths++;
++ found_hostgroup = 1;
++ break;
++ }
++ }
++ if (!found_hostgroup) {
++ /* this path belongs to new host port
++ * within this adapter
++ */
++ hgp = alloc_hostgroup();
++ if (!hgp)
++ goto out;
++
++ if (store_hostgroup(agp->host_groups, hgp))
++ goto out;
++
++ agp->num_hosts++;
++ if (store_path(hgp->paths, pp1))
++ goto out;
++
++ hgp->host_no = pp1->sg_id.host_no;
++ hgp->num_paths++;
++ }
++ /* delete paths from original path_group
++ * as they are added into adapter group now
++ */
++ vector_del_slot(pgp->paths, i);
++ i--;
++ }
++ }
++ }
++ return 0;
++
++out: /* add back paths into pg as re-ordering failed
++ */
++ vector_foreach_slot(adapters, agp, i) {
++ vector_foreach_slot(agp->host_groups, hgp, j) {
++ while (VECTOR_SIZE(hgp->paths) > 0) {
++ pp = VECTOR_SLOT(hgp->paths, 0);
++ if (store_path(pgp->paths, pp))
++ condlog(3, "failed to restore "
++ "path %s into path group",
++ pp->dev);
++ vector_del_slot(hgp->paths, 0);
++ }
++ }
++ }
++ free_adaptergroup(adapters);
++ return 1;
++}
++
++/* re-order paths in pg by alternating adapters and host ports
++ * for optimized selection
++ */
++int order_paths_in_pg_by_alt_adapters(struct pathgroup *pgp, vector adapters,
++ int total_paths)
++{
++ int next_adapter_index = 0;
++ struct adapter_group *agp;
++ struct host_group *hgp;
++ struct path *pp;
++
++ while (total_paths > 0) {
++ agp = VECTOR_SLOT(adapters, next_adapter_index);
++ if (!agp) {
++ condlog(0, "can't get adapter group %d", next_adapter_index);
++ return 1;
++ }
++
++ hgp = VECTOR_SLOT(agp->host_groups, agp->next_host_index);
++ if (!hgp) {
++ condlog(0, "can't get host group %d of adapter group %d", next_adapter_index, agp->next_host_index);
++ return 1;
++ }
++
++ if (!hgp->num_paths) {
++ agp->next_host_index++;
++ agp->next_host_index %= agp->num_hosts;
++ next_adapter_index++;
++ next_adapter_index %= VECTOR_SIZE(adapters);
++ continue;
++ }
++
++ pp = VECTOR_SLOT(hgp->paths, 0);
++
++ if (store_path(pgp->paths, pp))
++ return 1;
++
++ total_paths--;
++
++ vector_del_slot(hgp->paths, 0);
++
++ hgp->num_paths--;
++
++ agp->next_host_index++;
++ agp->next_host_index %= agp->num_hosts;
++ next_adapter_index++;
++ next_adapter_index %= VECTOR_SIZE(adapters);
++ }
++
++ /* all paths are added into path_group
++ * in crafted child order
++ */
++ return 0;
++}
++
++/* round-robin: order paths in path group to alternate
++ * between all host adapters
++ */
++int rr_optimize_path_order(struct pathgroup *pgp)
++{
++ vector adapters;
++ struct path *pp;
++ int total_paths;
++ int i;
++
++ total_paths = VECTOR_SIZE(pgp->paths);
++ vector_foreach_slot(pgp->paths, pp, i) {
++ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP &&
++ pp->sg_id.proto_id != SCSI_PROTOCOL_SAS &&
++ pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI &&
++ pp->sg_id.proto_id != SCSI_PROTOCOL_SRP) {
++ /* return success as default path order
++ * is maintained in path group
++ */
++ return 0;
++ }
++ }
++ adapters = vector_alloc();
++ if (!adapters)
++ return 0;
++
++ /* group paths in path group by host adapters
++ */
++ if (group_by_host_adapter(pgp, adapters)) {
++ /* already freed adapters */
++ condlog(3, "Failed to group paths by adapters");
++ return 0;
++ }
++
++ /* re-order paths in pg to alternate between adapters and host ports
++ */
++ if (order_paths_in_pg_by_alt_adapters(pgp, adapters, total_paths)) {
++ condlog(3, "Failed to re-order paths in pg by adapters "
++ "and host ports");
++ free_adaptergroup(adapters);
++ /* return failure as original paths are
++ * removed form pgp
++ */
++ return 1;
++ }
++
++ free_adaptergroup(adapters);
++ return 0;
++}
++
+ extern int
+ setup_map (struct multipath * mpp, char * params, int params_size)
+ {
+@@ -101,6 +314,22 @@ setup_map (struct multipath * mpp, char
+ */
+ mpp->bestpg = select_path_group(mpp);
+
++ /* re-order paths in all path groups in an optimized way
++ * for round-robin path selectors to get maximum throughput.
++ */
++ if (!strncmp(mpp->selector, "round-robin", 11)) {
++ vector_foreach_slot(mpp->pg, pgp, i) {
++ if (VECTOR_SIZE(pgp->paths) <= 2)
++ continue;
++ if (rr_optimize_path_order(pgp)) {
++ condlog(2, "cannot re-order paths for "
++ "optimization: %s",
++ mpp->alias);
++ return 1;
++ }
++ }
++ }
++
+ /*
+ * transform the mp->pg vector of vectors of paths
+ * into a mp->params strings to feed the device-mapper
+Index: multipath-tools-130222/libmultipath/configure.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/configure.h
++++ multipath-tools-130222/libmultipath/configure.h
+@@ -29,4 +29,4 @@ int reinstate_paths (struct multipath *m
+ int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload);
+ int get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid);
+ int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh);
+-
++int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name);
+Index: multipath-tools-130222/libmultipath/discovery.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/discovery.c
++++ multipath-tools-130222/libmultipath/discovery.c
+@@ -310,6 +310,93 @@ sysfs_get_tgt_nodename (struct path *pp,
+ return 1;
+ }
+
++int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name)
++{
++ int proto_id;
++
++ if (!pp || !adapter_name)
++ return 1;
++
++ proto_id = pp->sg_id.proto_id;
++
++ if (proto_id != SCSI_PROTOCOL_FCP &&
++ proto_id != SCSI_PROTOCOL_SAS &&
++ proto_id != SCSI_PROTOCOL_ISCSI &&
++ proto_id != SCSI_PROTOCOL_SRP) {
++ return 1;
++ }
++ /* iscsi doesn't have adapter info in sysfs
++ * get ip_address for grouping paths
++ */
++ if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
++ return sysfs_get_iscsi_ip_address(pp, adapter_name);
++
++ /* fetch adapter pci name for other protocols
++ */
++ return sysfs_get_host_pci_name(pp, adapter_name);
++}
++
++int sysfs_get_host_pci_name(struct path *pp, char *pci_name)
++{
++ struct udev_device *hostdev, *parent;
++ char host_name[HOST_NAME_LEN];
++ const char *driver_name, *value;
++
++ if (!pp || !pci_name)
++ return 1;
++
++ sprintf(host_name, "host%d", pp->sg_id.host_no);
++ hostdev = udev_device_new_from_subsystem_sysname(conf->udev,
++ "scsi_host", host_name);
++ if (!hostdev)
++ return 1;
++
++ parent = udev_device_get_parent(hostdev);
++ while (parent) {
++ driver_name = udev_device_get_driver(parent);
++ if (!driver_name) {
++ parent = udev_device_get_parent(parent);
++ continue;
++ }
++ if (!strcmp(driver_name, "pcieport"))
++ break;
++ parent = udev_device_get_parent(parent);
++ }
++ if (parent) {
++ /* pci_device found
++ */
++ value = udev_device_get_sysname(parent);
++
++ strncpy(pci_name, value, SLOT_NAME_SIZE);
++ udev_device_unref(hostdev);
++ return 0;
++ }
++ udev_device_unref(hostdev);
++ return 1;
++}
++
++int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address)
++{
++ struct udev_device *hostdev;
++ char host_name[HOST_NAME_LEN];
++ const char *value;
++
++ sprintf(host_name, "host%d", pp->sg_id.host_no);
++ hostdev = udev_device_new_from_subsystem_sysname(conf->udev,
++ "iscsi_host", host_name);
++ if (hostdev) {
++ value = udev_device_get_sysattr_value(hostdev,
++ "ipaddress");
++ if (value) {
++ strncpy(ip_address, value, SLOT_NAME_SIZE);
++ udev_device_unref(hostdev);
++ return 0;
++ } else
++ udev_device_unref(hostdev);
++ }
++ return 1;
++}
++
+ static void
+ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
+ {
+Index: multipath-tools-130222/libmultipath/discovery.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/discovery.h
++++ multipath-tools-130222/libmultipath/discovery.h
+@@ -38,6 +38,8 @@ int store_pathinfo (vector pathvec, vect
+ struct path **pp_ptr);
+ int sysfs_set_scsi_tmo (struct multipath *mpp);
+ int sysfs_get_timeout(struct path *pp, unsigned int *timeout);
++int sysfs_get_host_pci_name(struct path *pp, char *pci_name);
++int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address);
+
+ /*
+ * discovery bitmask
+Index: multipath-tools-130222/libmultipath/structs.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/structs.c
++++ multipath-tools-130222/libmultipath/structs.c
+@@ -18,6 +18,70 @@
+ #include "blacklist.h"
+ #include "prio.h"
+
++struct adapter_group *
++alloc_adaptergroup(void)
++{
++ struct adapter_group *agp;
++
++ agp = (struct adapter_group *)MALLOC(sizeof(struct adapter_group));
++
++ if (!agp)
++ return NULL;
++
++ agp->host_groups = vector_alloc();
++ if (!agp->host_groups) {
++ FREE(agp);
++ agp = NULL;
++ }
++ return agp;
++}
++
++void free_adaptergroup(vector adapters)
++{
++ int i;
++ struct adapter_group *agp;
++
++ vector_foreach_slot(adapters, agp, i) {
++ free_hostgroup(agp->host_groups);
++ FREE(agp);
++ }
++ vector_free(adapters);
++}
++
++void free_hostgroup(vector hostgroups)
++{
++ int i;
++ struct host_group *hgp;
++
++ if (!hostgroups)
++ return;
++
++ vector_foreach_slot(hostgroups, hgp, i) {
++ vector_free(hgp->paths);
++ FREE(hgp);
++ }
++ vector_free(hostgroups);
++}
++
++struct host_group *
++alloc_hostgroup(void)
++{
++ struct host_group *hgp;
++
++ hgp = (struct host_group *)MALLOC(sizeof(struct host_group));
++
++ if (!hgp)
++ return NULL;
++
++ hgp->paths = vector_alloc();
++
++ if (!hgp->paths) {
++ FREE(hgp);
++ hgp = NULL;
++ }
++ return hgp;
++}
++
+ struct path *
+ alloc_path (void)
+ {
+@@ -242,6 +306,26 @@ store_pathgroup (vector pgvec, struct pa
+ return 0;
+ }
+
++int
++store_hostgroup(vector hostgroupvec, struct host_group * hgp)
++{
++ if (!vector_alloc_slot(hostgroupvec))
++ return 1;
++
++ vector_set_slot(hostgroupvec, hgp);
++ return 0;
++}
++
++int
++store_adaptergroup(vector adapters, struct adapter_group * agp)
++{
++ if (!vector_alloc_slot(adapters))
++ return 1;
++
++ vector_set_slot(adapters, agp);
++ return 0;
++}
++
+ struct multipath *
+ find_mp_by_minor (vector mpvec, int minor)
+ {
+Index: multipath-tools-130222/libmultipath/structs.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/structs.h
++++ multipath-tools-130222/libmultipath/structs.h
+@@ -15,7 +15,8 @@
+ #define BLK_DEV_SIZE 33
+ #define PATH_SIZE 512
+ #define NAME_SIZE 512
+-
++#define HOST_NAME_LEN 8
++#define SLOT_NAME_SIZE 40
+
+ #define SCSI_VENDOR_SIZE 9
+ #define SCSI_PRODUCT_SIZE 17
+@@ -251,6 +252,20 @@ struct pathgroup {
+ char * selector;
+ };
+
++struct adapter_group {
++ char adapter_name[SLOT_NAME_SIZE];
++ struct pathgroup *pgp;
++ int num_hosts;
++ vector host_groups;
++ int next_host_index;
++};
++
++struct host_group {
++ int host_no;
++ int num_paths;
++ vector paths;
++};
++
+ struct path * alloc_path (void);
+ struct pathgroup * alloc_pathgroup (void);
+ struct multipath * alloc_multipath (void);
+@@ -263,6 +278,14 @@ void free_multipath_attributes (struct m
+ void drop_multipath (vector mpvec, char * wwid, enum free_path_mode free_paths);
+ void free_multipathvec (vector mpvec, enum free_path_mode free_paths);
+
++struct adapter_group * alloc_adaptergroup(void);
++struct host_group * alloc_hostgroup(void);
++void free_adaptergroup(vector adapters);
++void free_hostgroup(vector hostgroups);
++
++int store_adaptergroup(vector adapters, struct adapter_group *agp);
++int store_hostgroup(vector hostgroupvec, struct host_group *hgp);
++
+ int store_path (vector pathvec, struct path * pp);
+ int store_pathgroup (vector pgvec, struct pathgroup * pgp);
+
diff --git a/0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch b/0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch
new file mode 100644
index 0000000..d164de1
--- /dev/null
+++ b/0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch
@@ -0,0 +1,38 @@
+---
+ libmultipath/dict.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+Index: multipath-tools-130222/libmultipath/dict.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/dict.c
++++ multipath-tools-130222/libmultipath/dict.c
+@@ -43,6 +43,9 @@ def_fast_io_fail_handler(vector strvec)
+ char * buff;
+
+ buff = set_value(strvec);
++ if (!buff)
++ return 1;
++
+ if (strlen(buff) == 3 && !strcmp(buff, "off"))
+ conf->fast_io_fail = MP_FAST_IO_FAIL_OFF;
+ else if (sscanf(buff, "%d", &conf->fast_io_fail) != 1 ||
+@@ -1002,6 +1005,9 @@ hw_dev_loss_handler(vector strvec)
+ char * buff;
+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
+
++ if (!hwe)
++ return 1;
++
+ buff = set_value(strvec);
+ if (!buff)
+ return 1;
+@@ -1021,6 +1027,9 @@ hw_pgpolicy_handler(vector strvec)
+ char * buff;
+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
+
++ if (!hwe)
++ return 1;
++
+ buff = set_value(strvec);
+
+ if (!buff)
diff --git a/0092-UPBZ-1104605-reload-on-rename.patch b/0092-UPBZ-1104605-reload-on-rename.patch
new file mode 100644
index 0000000..465257c
--- /dev/null
+++ b/0092-UPBZ-1104605-reload-on-rename.patch
@@ -0,0 +1,63 @@
+---
+ libmultipath/configure.c | 11 +++++++++++
+ libmultipath/configure.h | 1 +
+ libmultipath/devmapper.c | 3 +--
+ 3 files changed, 13 insertions(+), 2 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/configure.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/configure.c
++++ multipath-tools-130222/libmultipath/configure.c
+@@ -394,6 +394,8 @@ select_action (struct multipath * mpp, v
+ cmpp->alias, mpp->alias);
+ strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
+ mpp->action = ACT_RENAME;
++ if (force_reload)
++ mpp->action = ACT_RENAME2;
+ return;
+ }
+ mpp->action = ACT_CREATE;
+@@ -632,6 +634,15 @@ domap (struct multipath * mpp, char * pa
+ r = dm_rename(mpp->alias_old, mpp->alias);
+ break;
+
++ case ACT_RENAME2:
++ r = dm_rename(mpp->alias_old, mpp->alias);
++ if (r) {
++ r = dm_addmap_reload(mpp, params);
++ if (r)
++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, MPATH_UDEV_RELOAD_FLAG);
++ }
++ break;
++
+ default:
+ break;
+ }
+Index: multipath-tools-130222/libmultipath/configure.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/configure.h
++++ multipath-tools-130222/libmultipath/configure.h
+@@ -18,6 +18,7 @@ enum actions {
+ ACT_RENAME,
+ ACT_CREATE,
+ ACT_RESIZE,
++ ACT_RENAME2,
+ };
+
+ #define FLUSH_ONE 1
+Index: multipath-tools-130222/libmultipath/devmapper.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/devmapper.c
++++ multipath-tools-130222/libmultipath/devmapper.c
+@@ -565,10 +565,9 @@ dm_dev_t (const char * mapname, char * d
+ if (!dm_task_run(dmt))
+ goto out;
+
+- if (!dm_task_get_info(dmt, &info))
++ if (!dm_task_get_info(dmt, &info) || !info.exists)
+ goto out;
+
+- r = info.open_count;
+ if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len)
+ goto out;
+
diff --git a/0093-UPBZ-1086825-user-friendly-name-remap.patch b/0093-UPBZ-1086825-user-friendly-name-remap.patch
new file mode 100644
index 0000000..ab5abbd
--- /dev/null
+++ b/0093-UPBZ-1086825-user-friendly-name-remap.patch
@@ -0,0 +1,199 @@
+---
+ libmultipath/alias.c | 64 ++++++++++++++++++++++++++++++++++++++++++---
+ libmultipath/alias.h | 2 +
+ libmultipath/propsel.c | 32 +++++++++++++++-------
+ libmultipath/structs_vec.c | 15 ++++++++++
+ 4 files changed, 100 insertions(+), 13 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/alias.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/alias.c
++++ multipath-tools-130222/libmultipath/alias.c
+@@ -145,7 +145,7 @@ lookup_binding(FILE *f, char *map_wwid,
+ }
+
+ static int
+-rlookup_binding(FILE *f, char *buff, char *map_alias)
++rlookup_binding(FILE *f, char *buff, char *map_alias, char *prefix)
+ {
+ char line[LINE_MAX];
+ unsigned int line_nr = 0;
+@@ -164,7 +164,7 @@ rlookup_binding(FILE *f, char *buff, cha
+ alias = strtok(line, " \t");
+ if (!alias) /* blank line */
+ continue;
+- curr_id = scan_devname(alias, NULL); /* TBD: Why this call? */
++ curr_id = scan_devname(alias, prefix);
+ if (curr_id >= id)
+ id = curr_id + 1;
+ wwid = strtok(NULL, " \t");
+@@ -188,6 +188,11 @@ rlookup_binding(FILE *f, char *buff, cha
+ }
+ }
+ condlog(3, "No matching alias [%s] in bindings file.", map_alias);
++
++ /* Get the theoretical id for this map alias.
++ * Used by use_existing_alias
++ */
++ id = scan_devname(map_alias, prefix);
+ return id;
+ }
+
+@@ -237,6 +242,59 @@ allocate_binding(int fd, char *wwid, int
+ }
+
+ char *
++use_existing_alias (char *wwid, char *file, char *alias_old,
++ char *prefix, int bindings_read_only)
++{
++ char *alias = NULL;
++ int id = 0;
++ int fd, can_write;
++ char buff[WWID_SIZE];
++ FILE *f;
++
++ fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
++ if (fd < 0)
++ return NULL;
++
++ f = fdopen(fd, "r");
++ if (!f) {
++ condlog(0, "cannot fdopen on bindings file descriptor");
++ close(fd);
++ return NULL;
++ }
++ /* lookup the binding. if it exsists, the wwid will be in buff
++ * either way, id contains the id for the alias
++ */
++ id = rlookup_binding(f , buff, alias_old, prefix);
++ if (id < 0)
++ goto out;
++
++ if (strlen(buff) > 0) {
++ /* if buff is our wwid, it's already
++ * allocated correctly
++ */
++ if (strcmp(buff, wwid) == 0)
++ alias = STRDUP(alias_old);
++ else {
++ alias = NULL;
++ condlog(0, "alias %s already bound to wwid %s, cannot reuse",
++ alias_old, buff);
++ }
++ goto out;
++ }
++
++ /* allocate the existing alias in the bindings file */
++ if (can_write && id && !bindings_read_only) {
++ alias = allocate_binding(fd, wwid, id, prefix);
++ condlog(0, "Allocated existing binding [%s] for WWID [%s]",
++ alias, wwid);
++ }
++
++out:
++ fclose(f);
++ return alias;
++}
++
++char *
+ get_user_friendly_alias(char *wwid, char *file, char *prefix,
+ int bindings_read_only)
+ {
+@@ -305,7 +363,7 @@ get_user_friendly_wwid(char *alias, char
+ return -1;
+ }
+
+- rlookup_binding(f, buff, alias);
++ rlookup_binding(f, buff, alias, NULL);
+ if (!strlen(buff)) {
+ fclose(f);
+ return -1;
+Index: multipath-tools-130222/libmultipath/alias.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/alias.h
++++ multipath-tools-130222/libmultipath/alias.h
+@@ -10,3 +10,5 @@
+ char *get_user_friendly_alias(char *wwid, char *file, char *prefix,
+ int bindings_readonly);
+ int get_user_friendly_wwid(char *alias, char *buff, char *file);
++char *use_existing_alias (char *wwid, char *file, char *alias_old,
++ char *prefix, int bindings_read_only);
+Index: multipath-tools-130222/libmultipath/propsel.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/propsel.c
++++ multipath-tools-130222/libmultipath/propsel.c
+@@ -253,19 +253,31 @@ want_user_friendly_names(struct multipat
+ extern int
+ select_alias (struct multipath * mp)
+ {
+- if (mp->mpe && mp->mpe->alias)
++ if (mp->mpe && mp->mpe->alias) {
+ mp->alias = STRDUP(mp->mpe->alias);
+- else {
+- mp->alias = NULL;
+- if (want_user_friendly_names(mp)) {
+- select_alias_prefix(mp);
+- mp->alias = get_user_friendly_alias(mp->wwid,
+- conf->bindings_file, mp->alias_prefix, conf->bindings_read_only);
+- }
+- if (mp->alias == NULL)
+- mp->alias = STRDUP(mp->wwid);
++ goto out;
+ }
+
++ mp->alias = NULL;
++ if (!want_user_friendly_names(mp))
++ goto out;
++
++ select_alias_prefix(mp);
++
++ if (strlen(mp->alias_old) > 0) {
++ mp->alias = use_existing_alias(mp->wwid, conf->bindings_file,
++ mp->alias_old, mp->alias_prefix,
++ conf->bindings_read_only);
++ memset (mp->alias_old, 0, WWID_SIZE);
++ }
++
++ if (mp->alias == NULL)
++ mp->alias = get_user_friendly_alias(mp->wwid,
++ conf->bindings_file, mp->alias_prefix, conf->bindings_read_only);
++out:
++ if (mp->alias == NULL)
++ mp->alias = STRDUP(mp->wwid);
++
+ return mp->alias ? 0 : 1;
+ }
+
+Index: multipath-tools-130222/libmultipath/structs_vec.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/structs_vec.c
++++ multipath-tools-130222/libmultipath/structs_vec.c
+@@ -430,6 +430,20 @@ out:
+ return NULL;
+ }
+
++static void
++find_existing_alias (struct multipath * mpp,
++ struct vectors *vecs)
++{
++ struct multipath * mp;
++ int i;
++
++ vector_foreach_slot (vecs->mpvec, mp, i)
++ if (strcmp(mp->wwid, mpp->wwid) == 0) {
++ strncpy(mpp->alias_old, mp->alias, WWID_SIZE);
++ return;
++ }
++}
++
+ extern struct multipath *
+ add_map_with_path (struct vectors * vecs,
+ struct path * pp, int add_vec)
+@@ -443,6 +457,7 @@ add_map_with_path (struct vectors * vecs
+ mpp->hwe = pp->hwe;
+
+ strcpy(mpp->wwid, pp->wwid);
++ find_existing_alias(mpp, vecs);
+ if (select_alias(mpp))
+ goto out;
+ mpp->size = pp->size;
diff --git a/0094-RHBZ-1086825-cleanup-remap.patch b/0094-RHBZ-1086825-cleanup-remap.patch
new file mode 100644
index 0000000..7d85c2d
--- /dev/null
+++ b/0094-RHBZ-1086825-cleanup-remap.patch
@@ -0,0 +1,107 @@
+---
+ libmultipath/alias.c | 31 +++++++++++++++----------------
+ libmultipath/propsel.c | 4 ++--
+ 2 files changed, 17 insertions(+), 18 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/alias.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/alias.c
++++ multipath-tools-130222/libmultipath/alias.c
+@@ -149,13 +149,11 @@ rlookup_binding(FILE *f, char *buff, cha
+ {
+ char line[LINE_MAX];
+ unsigned int line_nr = 0;
+- int id = 0;
+
+ buff[0] = '\0';
+
+ while (fgets(line, LINE_MAX, f)) {
+ char *c, *alias, *wwid;
+- int curr_id;
+
+ line_nr++;
+ c = strpbrk(line, "#\n\r");
+@@ -164,9 +162,6 @@ rlookup_binding(FILE *f, char *buff, cha
+ alias = strtok(line, " \t");
+ if (!alias) /* blank line */
+ continue;
+- curr_id = scan_devname(alias, prefix);
+- if (curr_id >= id)
+- id = curr_id + 1;
+ wwid = strtok(NULL, " \t");
+ if (!wwid){
+ condlog(3,
+@@ -184,16 +179,12 @@ rlookup_binding(FILE *f, char *buff, cha
+ "\nSetting wwid to %s", alias, wwid);
+ strncpy(buff, wwid, WWID_SIZE);
+ buff[WWID_SIZE - 1] = '\0';
+- return id;
++ return 0;
+ }
+ }
+ condlog(3, "No matching alias [%s] in bindings file.", map_alias);
+
+- /* Get the theoretical id for this map alias.
+- * Used by use_existing_alias
+- */
+- id = scan_devname(map_alias, prefix);
+- return id;
++ return -1;
+ }
+
+ static char *
+@@ -264,9 +255,7 @@ use_existing_alias (char *wwid, char *fi
+ /* lookup the binding. if it exsists, the wwid will be in buff
+ * either way, id contains the id for the alias
+ */
+- id = rlookup_binding(f , buff, alias_old, prefix);
+- if (id < 0)
+- goto out;
++ rlookup_binding(f, buff, alias_old, prefix);
+
+ if (strlen(buff) > 0) {
+ /* if buff is our wwid, it's already
+@@ -279,11 +268,21 @@ use_existing_alias (char *wwid, char *fi
+ condlog(0, "alias %s already bound to wwid %s, cannot reuse",
+ alias_old, buff);
+ }
+- goto out;
++ goto out;
+ }
+
+ /* allocate the existing alias in the bindings file */
+- if (can_write && id && !bindings_read_only) {
++ id = scan_devname(alias_old, prefix);
++ if (id <= 0)
++ goto out;
++
++ if (fflush(f) != 0) {
++ condlog(0, "cannot fflush bindings file stream : %s",
++ strerror(errno));
++ goto out;
++ }
++
++ if (can_write && !bindings_read_only) {
+ alias = allocate_binding(fd, wwid, id, prefix);
+ condlog(0, "Allocated existing binding [%s] for WWID [%s]",
+ alias, wwid);
+Index: multipath-tools-130222/libmultipath/propsel.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/propsel.c
++++ multipath-tools-130222/libmultipath/propsel.c
+@@ -263,13 +263,13 @@ select_alias (struct multipath * mp)
+ goto out;
+
+ select_alias_prefix(mp);
+-
++
+ if (strlen(mp->alias_old) > 0) {
+ mp->alias = use_existing_alias(mp->wwid, conf->bindings_file,
+ mp->alias_old, mp->alias_prefix,
+ conf->bindings_read_only);
+ memset (mp->alias_old, 0, WWID_SIZE);
+- }
++ }
+
+ if (mp->alias == NULL)
+ mp->alias = get_user_friendly_alias(mp->wwid,
diff --git a/0095-RHBZ-1127944-xtremIO-config.patch b/0095-RHBZ-1127944-xtremIO-config.patch
new file mode 100644
index 0000000..6807cbc
--- /dev/null
+++ b/0095-RHBZ-1127944-xtremIO-config.patch
@@ -0,0 +1,28 @@
+---
+ libmultipath/hwtable.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+Index: multipath-tools-130222/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/hwtable.c
++++ multipath-tools-130222/libmultipath/hwtable.c
+@@ -1121,6 +1121,19 @@ static struct hwentry default_hw[] = {
+ .prio_name = PRIO_ALUA,
+ .prio_args = NULL,
+ },
++ {
++ .vendor = "XtremIO",
++ .product = "XtremApp",
++ .features = DEFAULT_FEATURES,
++ .hwhandler = DEFAULT_HWHANDLER,
++ .selector = "queue-length 0",
++ .pgpolicy = MULTIBUS,
++ .pgfailback = -FAILBACK_IMMEDIATE,
++ .checker_name = DIRECTIO,
++ .fast_io_fail = 15,
++ .prio_name = DEFAULT_PRIO,
++ .prio_args = NULL,
++ },
+ /*
+ * EOL
+ */
diff --git a/0096-RHBZ-979474-new-wildcards.patch b/0096-RHBZ-979474-new-wildcards.patch
new file mode 100644
index 0000000..9025efe
--- /dev/null
+++ b/0096-RHBZ-979474-new-wildcards.patch
@@ -0,0 +1,120 @@
+---
+ libmultipath/print.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 83 insertions(+), 1 deletion(-)
+
+Index: multipath-tools-130222/libmultipath/print.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/print.c
++++ multipath-tools-130222/libmultipath/print.c
+@@ -10,6 +10,7 @@
+ #include <unistd.h>
+ #include <string.h>
+ #include <errno.h>
++#include <libudev.h>
+
+ #include "checkers.h"
+ #include "vector.h"
+@@ -44,7 +45,7 @@
+ * information printing helpers
+ */
+ static int
+-snprint_str (char * buff, size_t len, char * str)
++snprint_str (char * buff, size_t len, const char * str)
+ {
+ return snprintf(buff, len, "%s", str);
+ }
+@@ -432,6 +433,83 @@ snprint_path_mpp (char * buff, size_t le
+ }
+
+ static int
++snprint_host_attr (char * buff, size_t len, struct path * pp, char *attr)
++{
++ struct udev_device *host_dev = NULL;
++ char host_id[32];
++ const char *value = NULL;
++ int ret;
++
++ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
++ return snprintf(buff, len, "[undef]");
++ sprintf(host_id, "host%d", pp->sg_id.host_no);
++ host_dev = udev_device_new_from_subsystem_sysname(conf->udev, "fc_host",
++ host_id);
++ if (!host_dev) {
++ condlog(1, "%s: No fc_host device for '%s'", pp->dev, host_id);
++ goto out;
++ }
++ value = udev_device_get_sysattr_value(host_dev, attr);
++ if (value)
++ ret = snprint_str(buff, len, value);
++ udev_device_unref(host_dev);
++out:
++ if (!value)
++ ret = snprintf(buff, len, "[unknown]");
++ return ret;
++}
++
++static int
++snprint_host_wwnn (char * buff, size_t len, struct path * pp)
++{
++ return snprint_host_attr(buff, len, pp, "node_name");
++}
++
++static int
++snprint_host_wwpn (char * buff, size_t len, struct path * pp)
++{
++ return snprint_host_attr(buff, len, pp, "port_name");
++}
++
++static int
++snprint_tgt_wwpn (char * buff, size_t len, struct path * pp)
++{
++ struct udev_device *rport_dev = NULL;
++ char rport_id[32];
++ const char *value = NULL;
++ int ret;
++
++ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP)
++ return snprintf(buff, len, "[undef]");
++ sprintf(rport_id, "rport-%d:%d-%d",
++ pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id);
++ rport_dev = udev_device_new_from_subsystem_sysname(conf->udev,
++ "fc_remote_ports", rport_id);
++ if (!rport_dev) {
++ condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev,
++ rport_id);
++ goto out;
++ }
++ value = udev_device_get_sysattr_value(rport_dev, "port_name");
++ if (value)
++ ret = snprint_str(buff, len, value);
++ udev_device_unref(rport_dev);
++out:
++ if (!value)
++ ret = snprintf(buff, len, "[unknown]");
++ return ret;
++}
++
++
++static int
++snprint_tgt_wwnn (char * buff, size_t len, struct path * pp)
++{
++ if (pp->tgt_node_name[0] == '\0')
++ return snprintf(buff, len, "[undef]");
++ return snprint_str(buff, len, pp->tgt_node_name);
++}
++
++static int
+ snprint_path_checker (char * buff, size_t len, struct path * pp)
+ {
+ struct checker * c = &pp->checker;
+@@ -475,6 +553,10 @@ struct path_data pd[] = {
+ {'S', "size", 0, snprint_path_size},
+ {'z', "serial", 0, snprint_path_serial},
+ {'m', "multipath", 0, snprint_path_mpp},
++ {'N', "host WWNN", 0, snprint_host_wwnn},
++ {'n', "target WWNN", 0, snprint_tgt_wwnn},
++ {'R', "host WWPN", 0, snprint_host_wwpn},
++ {'r', "target WWPN", 0, snprint_tgt_wwpn},
+ {0, NULL, 0 , NULL}
+ };
+
diff --git a/0097-RH-fix-coverity-errors.patch b/0097-RH-fix-coverity-errors.patch
new file mode 100644
index 0000000..8ce0e87
--- /dev/null
+++ b/0097-RH-fix-coverity-errors.patch
@@ -0,0 +1,158 @@
+---
+ kpartx/devmapper.c | 3 ++-
+ libmultipath/alias.c | 1 +
+ libmultipath/blacklist.c | 7 +++++++
+ libmultipath/prioritizers/iet.c | 2 ++
+ libmultipath/prioritizers/weightedpath.c | 5 ++++-
+ libmultipath/regex.c | 5 ++++-
+ libmultipath/sysfs.c | 3 ++-
+ libmultipath/util.c | 2 +-
+ 8 files changed, 23 insertions(+), 5 deletions(-)
+
+Index: multipath-tools-130222/kpartx/devmapper.c
+===================================================================
+--- multipath-tools-130222.orig/kpartx/devmapper.c
++++ multipath-tools-130222/kpartx/devmapper.c
+@@ -132,8 +132,9 @@ dm_addmap (int task, const char *name, c
+ goto addout;
+ r = dm_task_run (dmt);
+
+- addout:
++addout:
+ dm_task_destroy (dmt);
++ free(prefixed_uuid);
+
+ return r;
+ }
+Index: multipath-tools-130222/libmultipath/alias.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/alias.c
++++ multipath-tools-130222/libmultipath/alias.c
+@@ -328,6 +328,7 @@ get_user_friendly_alias(char *wwid, char
+ if (fflush(f) != 0) {
+ condlog(0, "cannot fflush bindings file stream : %s",
+ strerror(errno));
++ free(alias);
+ fclose(f);
+ return NULL;
+ }
+Index: multipath-tools-130222/libmultipath/blacklist.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/blacklist.c
++++ multipath-tools-130222/libmultipath/blacklist.c
+@@ -79,6 +79,8 @@ set_ble_device (vector blist, char * ven
+ if (regcomp(&ble->vendor_reg, vendor,
+ REG_EXTENDED|REG_NOSUB)) {
+ FREE(vendor);
++ if (product)
++ FREE(product);
+ return 1;
+ }
+ ble->vendor = vendor;
+@@ -87,6 +89,10 @@ set_ble_device (vector blist, char * ven
+ if (regcomp(&ble->product_reg, product,
+ REG_EXTENDED|REG_NOSUB)) {
+ FREE(product);
++ if (vendor) {
++ ble->vendor = NULL;
++ FREE(vendor);
++ }
+ return 1;
+ }
+ ble->product = product;
+@@ -189,6 +195,7 @@ setup_default_blist (struct config * con
+ STRDUP(hwe->bl_product),
+ ORIGIN_DEFAULT)) {
+ FREE(ble);
++ vector_del_slot(conf->blist_device, VECTOR_SIZE(conf->blist_device) - 1);
+ return 1;
+ }
+ }
+Index: multipath-tools-130222/libmultipath/prioritizers/iet.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prioritizers/iet.c
++++ multipath-tools-130222/libmultipath/prioritizers/iet.c
+@@ -109,6 +109,7 @@ int iet_prio(const char *dev, char * arg
+ ssize_t nchars = readlink(path, buffer, sizeof(buffer)-1);
+ if (nchars != -1) {
+ char *device;
++ buffer[nchars] = '\0';
+ device = find_regex(buffer,"(sd[a-z]+)");
+ // if device parsed is the right one
+ if (device!=NULL && strncmp(device, dev, strlen(device)) == 0) {
+@@ -118,6 +119,7 @@ int iet_prio(const char *dev, char * arg
+ if (ip!=NULL && strncmp(ip, preferredip, strlen(ip)) == 0) {
+ // high prio
+ free(ip);
++ free(device);
+ closedir(dir_p);
+ return 20;
+ }
+Index: multipath-tools-130222/libmultipath/prioritizers/weightedpath.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/prioritizers/weightedpath.c
++++ multipath-tools-130222/libmultipath/prioritizers/weightedpath.c
+@@ -61,8 +61,10 @@ int prio_path_weight(struct path *pp, ch
+ regex = get_next_string(&temp, split_char);
+
+ /* Return default priority if the argument is not parseable */
+- if (!regex)
++ if (!regex) {
++ FREE(arg);
+ return priority;
++ }
+
+ if (!strcmp(regex, HBTL)) {
+ sprintf(path, "%d:%d:%d:%d", pp->sg_id.host_no,
+@@ -72,6 +74,7 @@ int prio_path_weight(struct path *pp, ch
+ } else {
+ condlog(0, "%s: %s - Invalid arguments", pp->dev,
+ pp->prio.name);
++ FREE(arg);
+ return priority;
+ }
+
+Index: multipath-tools-130222/libmultipath/regex.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/regex.c
++++ multipath-tools-130222/libmultipath/regex.c
+@@ -3936,8 +3936,11 @@ int eflags;
+ regs.num_regs = nmatch;
+ regs.start = TALLOC(nmatch, regoff_t);
+ regs.end = TALLOC(nmatch, regoff_t);
+- if (regs.start == NULL || regs.end == NULL)
++ if (regs.start == NULL || regs.end == NULL) {
++ free(regs.start);
++ free(regs.end);
+ return (int) REG_NOMATCH;
++ }
+ }
+
+ /* Perform the searching operation. */
+Index: multipath-tools-130222/libmultipath/sysfs.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/sysfs.c
++++ multipath-tools-130222/libmultipath/sysfs.c
+@@ -88,7 +88,8 @@ ssize_t sysfs_attr_get_value(struct udev
+ } else if (size == value_len) {
+ condlog(4, "overflow while reading from %s", devpath);
+ size = 0;
+- }
++ } else
++ value[size] = '\0';
+
+ close(fd);
+ return size;
+Index: multipath-tools-130222/libmultipath/util.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/util.c
++++ multipath-tools-130222/libmultipath/util.c
+@@ -175,7 +175,7 @@ devt2devname (char *devname, int devname
+ sprintf(block_path,"/sys/dev/block/%u:%u", major, minor);
+ if (lstat(block_path, &statbuf) == 0) {
+ if (S_ISLNK(statbuf.st_mode) &&
+- readlink(block_path, dev, FILE_NAME_SIZE) > 0) {
++ readlink(block_path, dev, FILE_NAME_SIZE-1) > 0) {
+ char *p = strrchr(dev, '/');
+
+ if (!p) {
diff --git a/0098-UPBZ-1067171-mutipath-i.patch b/0098-UPBZ-1067171-mutipath-i.patch
new file mode 100644
index 0000000..cf41863
--- /dev/null
+++ b/0098-UPBZ-1067171-mutipath-i.patch
@@ -0,0 +1,332 @@
+---
+ libmultipath/config.h | 15 ++++++++-
+ libmultipath/configure.c | 2 -
+ libmultipath/discovery.c | 5 +--
+ multipath/main.c | 75 +++++++++++++++++++++++++----------------------
+ multipath/multipath.8 | 5 ++-
+ 5 files changed, 61 insertions(+), 41 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/config.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/config.h
++++ multipath-tools-130222/libmultipath/config.h
+@@ -23,6 +23,17 @@ enum devtypes {
+ DEV_DEVMAP
+ };
+
++enum mpath_cmds {
++ CMD_CREATE,
++ CMD_DRY_RUN,
++ CMD_LIST_SHORT,
++ CMD_LIST_LONG,
++ CMD_VALID_PATH,
++ CMD_REMOVE_WWID,
++ CMD_RESET_WWIDS,
++ CMD_ADD_WWID,
++};
++
+ struct hwentry {
+ char * vendor;
+ char * product;
+@@ -79,8 +90,7 @@ struct mpentry {
+
+ struct config {
+ int verbosity;
+- int dry_run;
+- int list;
++ enum mpath_cmds cmd;
+ int pgpolicy_flag;
+ int pgpolicy;
+ enum devtypes dev_type;
+@@ -98,6 +108,7 @@ struct config {
+ int max_fds;
+ int force_reload;
+ int queue_without_daemon;
++ int ignore_wwids;
+ int checker_timeout;
+ int daemon;
+ int flush_on_last_del;
+Index: multipath-tools-130222/multipath/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipath/main.c
++++ multipath-tools-130222/multipath/main.c
+@@ -85,7 +85,7 @@ usage (char * progname)
+ {
+ fprintf (stderr, VERSION_STRING);
+ fprintf (stderr, "Usage:\n");
+- fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-T tm:val] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname);
++ fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-T tm:val] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname);
+ fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname);
+ fprintf (stderr, " %s -F [-v lvl]\n", progname);
+ fprintf (stderr, " %s -t\n", progname);
+@@ -109,6 +109,7 @@ usage (char * progname)
+ " -d dry run, do not create or update devmaps\n" \
+ " -t dump internal hardware table\n" \
+ " -r force devmap reload\n" \
++ " -i ignore wwids file\n" \
+ " -B treat the bindings file as read only\n" \
+ " -p policy failover|multibus|group_by_serial|group_by_prio\n" \
+ " -b fil bindings file location\n" \
+@@ -209,18 +210,19 @@ get_dm_mpvec (vector curmp, vector pathv
+ * If not in "fast list mode", we need to fetch information
+ * about them
+ */
+- if (conf->list != 1)
++ if (conf->cmd != CMD_LIST_SHORT)
+ update_paths(mpp);
+
+- if (conf->list > 1)
++ if (conf->cmd == CMD_LIST_LONG)
+ mpp->bestpg = select_path_group(mpp);
+
+ disassemble_status(status, mpp);
+
+- if (conf->list)
++ if (conf->cmd == CMD_LIST_SHORT ||
++ conf->cmd == CMD_LIST_LONG)
+ print_multipath_topology(mpp, conf->verbosity);
+
+- if (!conf->dry_run)
++ if (conf->cmd == CMD_CREATE)
+ reinstate_paths(mpp);
+ }
+ return 0;
+@@ -262,10 +264,11 @@ configure (void)
+ /*
+ * if we have a blacklisted device parameter, exit early
+ */
+- if (dev && conf->dev_type == DEV_DEVNODE && conf->dry_run != 3 &&
++ if (dev && conf->dev_type == DEV_DEVNODE &&
++ conf->cmd != CMD_REMOVE_WWID &&
+ (filter_devnode(conf->blist_devnode,
+ conf->elist_devnode, dev) > 0)) {
+- if (conf->dry_run == 2)
++ if (conf->cmd == CMD_VALID_PATH)
+ printf("%s is not a valid multipath device path\n",
+ conf->dev);
+ goto out;
+@@ -278,13 +281,13 @@ configure (void)
+ int failed = get_refwwid(conf->dev, conf->dev_type, pathvec,
+ &refwwid);
+ if (!refwwid) {
+- if (failed == 2 && conf->dry_run == 2)
++ if (failed == 2 && conf->cmd == CMD_VALID_PATH)
+ printf("%s is not a valid multipath device path\n", conf->dev);
+ else
+ condlog(3, "scope is nul");
+ goto out;
+ }
+- if (conf->dry_run == 3) {
++ if (conf->cmd == CMD_REMOVE_WWID) {
+ r = remove_wwid(refwwid);
+ if (r == 0)
+ printf("wwid '%s' removed\n", refwwid);
+@@ -295,7 +298,7 @@ configure (void)
+ }
+ goto out;
+ }
+- if (conf->dry_run == 5) {
++ if (conf->cmd == CMD_ADD_WWID) {
+ r = remember_wwid(refwwid);
+ if (r == 0)
+ printf("wwid '%s' added\n", refwwid);
+@@ -305,13 +308,13 @@ configure (void)
+ goto out;
+ }
+ condlog(3, "scope limited to %s", refwwid);
+- if (conf->dry_run == 2) {
+- if (check_wwids_file(refwwid, 0) == 0){
+- printf("%s is a valid multipath device path\n", conf->dev);
++ if (conf->cmd == CMD_VALID_PATH) {
++ if (conf->ignore_wwids ||
++ check_wwids_file(refwwid, 0) == 0)
+ r = 0;
+- }
+- else
+- printf("%s is not a valid multipath device path\n", conf->dev);
++
++ printf("%s %s a valid multipath device path\n",
++ conf->dev, r == 0 ? "is" : "is not");
+ goto out;
+ }
+ }
+@@ -319,13 +322,13 @@ configure (void)
+ /*
+ * get a path list
+ */
+- if (conf->dev && !conf->list)
++ if (conf->dev)
+ di_flag = DI_WWID;
+
+- if (conf->list > 1)
++ if (conf->cmd == CMD_LIST_LONG)
+ /* extended path info '-ll' */
+ di_flag |= DI_SYSFS | DI_CHECKER;
+- else if (conf->list)
++ else if (conf->cmd == CMD_LIST_SHORT)
+ /* minimum path info '-l' */
+ di_flag |= DI_SYSFS;
+ else
+@@ -345,7 +348,7 @@ configure (void)
+
+ filter_pathvec(pathvec, refwwid);
+
+- if (conf->list) {
++ if (conf->cmd != CMD_CREATE && conf->cmd != CMD_DRY_RUN) {
+ r = 0;
+ goto out;
+ }
+@@ -440,7 +443,7 @@ main (int argc, char *argv[])
+ int r = 1;
+ long int timestamp = -1;
+ int valid = -1;
+- while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BrtT:qwW")) != EOF ) {
++ while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BritT:qwW")) != EOF ) {
+ switch(arg) {
+ case 'T':
+ if (optarg[0] == ':')
+@@ -476,7 +479,7 @@ main (int argc, char *argv[])
+ if (dm_prereq())
+ exit(1);
+
+- while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BrtT:qwW")) != EOF ) {
++ while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BritT:qwW")) != EOF ) {
+ switch(arg) {
+ case 1: printf("optarg : %s\n",optarg);
+ break;
+@@ -499,11 +502,11 @@ main (int argc, char *argv[])
+ conf->allow_queueing = 1;
+ break;
+ case 'c':
+- conf->dry_run = 2;
++ conf->cmd = CMD_VALID_PATH;
+ break;
+ case 'd':
+- if (!conf->dry_run)
+- conf->dry_run = 1;
++ if (conf->cmd == CMD_CREATE)
++ conf->cmd = CMD_DRY_RUN;
+ break;
+ case 'f':
+ conf->remove = FLUSH_ONE;
+@@ -512,11 +515,10 @@ main (int argc, char *argv[])
+ conf->remove = FLUSH_ALL;
+ break;
+ case 'l':
+- conf->list = 1;
+- conf->dry_run = 1;
+-
+ if (optarg && !strncmp(optarg, "l", 1))
+- conf->list++;
++ conf->cmd = CMD_LIST_LONG;
++ else
++ conf->cmd = CMD_LIST_SHORT;
+
+ break;
+ case 'M':
+@@ -535,6 +537,9 @@ main (int argc, char *argv[])
+ case 'r':
+ conf->force_reload = 1;
+ break;
++ case 'i':
++ conf->ignore_wwids = 1;
++ break;
+ case 't':
+ r = dump_config();
+ goto out;
+@@ -548,13 +553,13 @@ main (int argc, char *argv[])
+ usage(argv[0]);
+ exit(0);
+ case 'w':
+- conf->dry_run = 3;
++ conf->cmd = CMD_REMOVE_WWID;
+ break;
+ case 'W':
+- conf->dry_run = 4;
++ conf->cmd = CMD_RESET_WWIDS;
+ break;
+ case 'a':
+- conf->dry_run = 5;
++ conf->cmd = CMD_ADD_WWID;
+ break;
+ case ':':
+ fprintf(stderr, "Missing option argument\n");
+@@ -600,16 +605,16 @@ main (int argc, char *argv[])
+ }
+ dm_init();
+
+- if (conf->dry_run == 2 &&
++ if (conf->cmd == CMD_VALID_PATH &&
+ (!conf->dev || conf->dev_type == DEV_DEVMAP)) {
+ condlog(0, "the -c option requires a path to check");
+ goto out;
+ }
+- if (conf->dry_run == 3 && !conf->dev) {
++ if (conf->cmd == CMD_REMOVE_WWID && !conf->dev) {
+ condlog(0, "the -w option requires a device");
+ goto out;
+ }
+- if (conf->dry_run == 4) {
++ if (conf->cmd == CMD_RESET_WWIDS) {
+ struct multipath * mpp;
+ int i;
+ vector curmp;
+Index: multipath-tools-130222/multipath/multipath.8
+===================================================================
+--- multipath-tools-130222.orig/multipath/multipath.8
++++ multipath-tools-130222/multipath/multipath.8
+@@ -8,7 +8,7 @@ multipath \- Device mapper target autoco
+ .RB [\| \-b\ \c
+ .IR bindings_file \|]
+ .RB [\| \-d \|]
+-.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-a | \-A | \-w | \-W \|]
++.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-r | \-a | \-A | \-w | \-W \|]
+ .RB [\| \-p\ \c
+ .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|]
+ .RB [\| device \|]
+@@ -55,6 +55,9 @@ print internal hardware table to stdout
+ .B \-r
+ force devmap reload
+ .TP
++.B \-i
++ignore wwids file when processing devices
++.TP
+ .B \-B
+ treat the bindings file as read only
+ .TP
+Index: multipath-tools-130222/libmultipath/configure.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/configure.c
++++ multipath-tools-130222/libmultipath/configure.c
+@@ -580,7 +580,7 @@ domap (struct multipath * mpp, char * pa
+ /*
+ * last chance to quit before touching the devmaps
+ */
+- if (conf->dry_run && mpp->action != ACT_NOTHING) {
++ if (conf->cmd == CMD_DRY_RUN && mpp->action != ACT_NOTHING) {
+ print_multipath_topology(mpp, conf->verbosity);
+ return DOMAP_DRY;
+ }
+Index: multipath-tools-130222/libmultipath/discovery.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/discovery.c
++++ multipath-tools-130222/libmultipath/discovery.c
+@@ -54,7 +54,8 @@ store_pathinfo (vector pathvec, vector h
+ }
+ pp->udev = udev_device_ref(udevice);
+ err = pathinfo(pp, hwtable,
+- (conf->dry_run == 3)? flag : (flag | DI_BLACKLIST));
++ (conf->cmd == CMD_REMOVE_WWID)? flag :
++ (flag | DI_BLACKLIST));
+ if (err)
+ goto out;
+
+@@ -1101,7 +1102,7 @@ get_uid (struct path * pp)
+
+ memset(pp->wwid, 0, WWID_SIZE);
+ value = udev_device_get_property_value(pp->udev, pp->uid_attribute);
+- if ((!value || strlen(value) == 0) && conf->dry_run == 2)
++ if ((!value || strlen(value) == 0) && conf->cmd == CMD_VALID_PATH)
+ value = getenv(pp->uid_attribute);
+ if (value && strlen(value)) {
+ size_t len = WWID_SIZE;
diff --git a/0099-RH-add-all-devs.patch b/0099-RH-add-all-devs.patch
new file mode 100644
index 0000000..aca6d4c
--- /dev/null
+++ b/0099-RH-add-all-devs.patch
@@ -0,0 +1,170 @@
+---
+ libmultipath/config.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ libmultipath/config.h | 1
+ libmultipath/dict.c | 38 +++++++++++++++++++++++++++++
+ 3 files changed, 102 insertions(+), 1 deletion(-)
+
+Index: multipath-tools-130222/libmultipath/config.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/config.c
++++ multipath-tools-130222/libmultipath/config.c
+@@ -113,6 +113,8 @@ find_hwe (vector hwtable, char * vendor,
+ * continuing to the generic entries
+ */
+ vector_foreach_slot_backwards (hwtable, tmp, i) {
++ if (tmp->all_devs == 1)
++ continue;
+ if (hwe_regmatch(tmp, &hwe))
+ continue;
+ ret = tmp;
+@@ -348,6 +350,62 @@ merge_hwe (struct hwentry * dst, struct
+ return 0;
+ }
+
++#define overwrite_str(s) \
++do { \
++ if (src->s) { \
++ if (dst->s) \
++ FREE(dst->s); \
++ if (!(dst->s = set_param_str(src->s))) \
++ return 1; \
++ } \
++} while(0)
++
++#define overwrite_num(s) \
++do { \
++ if (src->s) \
++ dst->s = src->s; \
++} while(0)
++
++static int
++overwrite_hwe (struct hwentry * dst, struct hwentry * src)
++{
++ overwrite_str(vendor);
++ overwrite_str(product);
++ overwrite_str(revision);
++ overwrite_str(uid_attribute);
++ overwrite_str(features);
++ overwrite_str(hwhandler);
++ overwrite_str(selector);
++ overwrite_str(checker_name);
++ overwrite_str(prio_name);
++ overwrite_str(prio_args);
++ overwrite_str(alias_prefix);
++ overwrite_str(bl_product);
++ overwrite_num(pgpolicy);
++ overwrite_num(pgfailback);
++ overwrite_num(rr_weight);
++ overwrite_num(no_path_retry);
++ overwrite_num(minio);
++ overwrite_num(minio_rq);
++ overwrite_num(pg_timeout);
++ overwrite_num(flush_on_last_del);
++ overwrite_num(fast_io_fail);
++ overwrite_num(dev_loss);
++ overwrite_num(user_friendly_names);
++ overwrite_num(retain_hwhandler);
++ overwrite_num(detect_prio);
++
++ /*
++ * Make sure features is consistent with
++ * no_path_retry
++ */
++ if (dst->no_path_retry == NO_PATH_RETRY_FAIL)
++ remove_feature(&dst->features, "queue_if_no_path");
++ else if (dst->no_path_retry != NO_PATH_RETRY_UNDEF)
++ add_feature(&dst->features, "queue_if_no_path");
++ return 0;
++}
++
+ int
+ store_hwe (vector hwtable, struct hwentry * dhwe)
+ {
+@@ -431,7 +489,11 @@ restart:
+ break;
+ j = n;
+ vector_foreach_slot_after(hw, hwe2, j) {
+- if (conf->hw_strmatch) {
++ if (hwe2->all_devs == 1) {
++ overwrite_hwe(hwe1, hwe2);
++ continue;
++ }
++ else if (conf->hw_strmatch) {
+ if (hwe_strmatch(hwe2, hwe1))
+ continue;
+ }
+Index: multipath-tools-130222/libmultipath/config.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/config.h
++++ multipath-tools-130222/libmultipath/config.h
+@@ -47,6 +47,7 @@ struct hwentry {
+ char * prio_args;
+ char * alias_prefix;
+
++ int all_devs;
+ int pgpolicy;
+ int pgfailback;
+ int rr_weight;
+Index: multipath-tools-130222/libmultipath/dict.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/dict.c
++++ multipath-tools-130222/libmultipath/dict.c
+@@ -918,6 +918,32 @@ device_handler(vector strvec)
+ }
+
+ static int
++all_devs_handler(vector strvec)
++{
++ char * buff;
++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable);
++
++ if (!hwe)
++ return 1;
++
++ buff = set_value(strvec);
++ if (!buff)
++ return 1;
++
++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "0")))
++ hwe->all_devs = 0;
++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "1")))
++ hwe->all_devs = 1;
++ else
++ hwe->all_devs = 0;
++
++ FREE(buff);
++ return 0;
++}
++
++static int
+ vendor_handler(vector strvec)
+ {
+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
+@@ -2182,6 +2208,17 @@ snprint_hw_dev_loss(char * buff, int len
+ }
+
+ static int
++snprint_hw_all_devs (char *buff, int len, void *data)
++{
++ struct hwentry * hwe = (struct hwentry *)data;
++
++ if (!hwe->all_devs)
++ return 0;
++
++ return snprintf(buff, len, "yes");
++}
++
++static int
+ snprint_hw_vendor (char * buff, int len, void * data)
+ {
+ struct hwentry * hwe = (struct hwentry *)data;
+@@ -2968,6 +3005,7 @@ init_keywords(void)
+ install_keyword_root("devices", &devices_handler);
+ install_keyword_multi("device", &device_handler, NULL);
+ install_sublevel();
++ install_keyword("all_devs", &all_devs_handler, &snprint_hw_all_devs);
+ install_keyword("vendor", &vendor_handler, &snprint_hw_vendor);
+ install_keyword("product", &product_handler, &snprint_hw_product);
+ install_keyword("revision", &revision_handler, &snprint_hw_revision);
diff --git a/0100-RHBZ-1067171-multipath-i-update.patch b/0100-RHBZ-1067171-multipath-i-update.patch
new file mode 100644
index 0000000..9a67e7a
--- /dev/null
+++ b/0100-RHBZ-1067171-multipath-i-update.patch
@@ -0,0 +1,54 @@
+---
+ multipath/main.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+Index: multipath-tools-130222/multipath/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipath/main.c
++++ multipath-tools-130222/multipath/main.c
+@@ -198,6 +198,9 @@ get_dm_mpvec (vector curmp, vector pathv
+ continue;
+ }
+
++ if (conf->cmd == CMD_VALID_PATH)
++ continue;
++
+ dm_get_map(mpp->alias, &mpp->size, params);
+ condlog(3, "params = %s", params);
+ dm_get_status(mpp->alias, status);
+@@ -308,7 +311,13 @@ configure (void)
+ goto out;
+ }
+ condlog(3, "scope limited to %s", refwwid);
+- if (conf->cmd == CMD_VALID_PATH) {
++ /* If you are ignoring the wwids file and find_multipaths is
++ * set, you need to actually check if there are two available
++ * paths to determine if this path should be multipathed. To
++ * do this, we put off the check until after discovering all
++ * the paths */
++ if (conf->cmd == CMD_VALID_PATH &&
++ (!conf->find_multipaths || !conf->ignore_wwids)) {
+ if (conf->ignore_wwids ||
+ check_wwids_file(refwwid, 0) == 0)
+ r = 0;
+@@ -348,6 +357,20 @@ configure (void)
+
+ filter_pathvec(pathvec, refwwid);
+
++
++ if (conf->cmd == CMD_VALID_PATH) {
++ /* This only happens if find_multipaths is and
++ * ignore_wwids is set.
++ * If there is currently a multipath device matching
++ * the refwwid, or there is more than one path matching
++ * the refwwid, then the path is valid */
++ if (VECTOR_SIZE(curmp) != 0 || VECTOR_SIZE(pathvec) > 1)
++ r = 0;
++ printf("%s %s a valid multipath device path\n",
++ conf->dev, r == 0 ? "is" : "is not");
++ goto out;
++ }
++
+ if (conf->cmd != CMD_CREATE && conf->cmd != CMD_DRY_RUN) {
+ r = 0;
+ goto out;
diff --git a/0101-RH-adapter-name-wildcard.patch b/0101-RH-adapter-name-wildcard.patch
new file mode 100644
index 0000000..3c67de5
--- /dev/null
+++ b/0101-RH-adapter-name-wildcard.patch
@@ -0,0 +1,33 @@
+---
+ libmultipath/print.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+Index: multipath-tools-130222/libmultipath/print.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/print.c
++++ multipath-tools-130222/libmultipath/print.c
+@@ -510,6 +510,16 @@ snprint_tgt_wwnn (char * buff, size_t le
+ }
+
+ static int
++snprint_host_adapter (char * buff, size_t len, struct path * pp)
++{
++ char adapter[SLOT_NAME_SIZE];
++
++ if (sysfs_get_host_adapter_name(pp, adapter))
++ return snprintf(buff, len, "[undef]");
++ return snprint_str(buff, len, adapter);
++}
++
++static int
+ snprint_path_checker (char * buff, size_t len, struct path * pp)
+ {
+ struct checker * c = &pp->checker;
+@@ -557,6 +567,7 @@ struct path_data pd[] = {
+ {'n', "target WWNN", 0, snprint_tgt_wwnn},
+ {'R', "host WWPN", 0, snprint_host_wwpn},
+ {'r', "target WWPN", 0, snprint_tgt_wwpn},
++ {'a', "host adapter", 0, snprint_host_adapter},
+ {0, NULL, 0 , NULL}
+ };
+
diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec
index 43f24b8..6f17674 100644
--- a/device-mapper-multipath.spec
+++ b/device-mapper-multipath.spec
@@ -1,7 +1,7 @@
Summary: Tools to manage multipath devices using device-mapper
Name: device-mapper-multipath
Version: 0.4.9
-Release: 67%{?dist}
+Release: 68%{?dist}
License: GPL+
Group: System Environment/Base
URL: http://christophe.varoqui.free.fr/
@@ -57,7 +57,7 @@ Patch0046: 0046-RHBZ-883981-move-udev-rules.patch
Patch0047: 0047-RHBZ-980777-kpartx-read-only-loop-devs.patch
Patch0048: 0048-RH-print-defaults.patch
Patch0049: 0049-RH-remove-ID_FS_TYPE.patch
-#Patch0050: 0050-RH-listing-speedup.patch
+Patch0050: 0050-RH-listing-speedup.patch
Patch0051: 0051-UP-fix-cli-resize.patch
Patch0052: 0052-RH-fix-bad-derefs.patch
Patch0053: 0053-UP-fix-failback.patch
@@ -88,6 +88,27 @@ Patch0076: 0076-RHBZ-1056686-add-hw_str_match.patch
Patch0078: 0078-RHBZ-1054044-fix-mpathconf-manpage.patch
Patch0079: 0079-RHBZ-1070581-add-wwid-option.patch
Patch0080: 0080-RHBZ-1075796-cmdline-wwid.patch
+Patch0081: 0081-RHBZ-1066264-check-prefix-on-rename.patch
+Patch0082: 0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch
+Patch0083: 0083-RHBZ-1080055-orphan-paths-on-reload.patch
+Patch0084: 0084-RHBZ-1110000-multipath-man.patch
+Patch0085: 0085-UPBZ-1110006-datacore-config.patch
+Patch0086: 0086-RHBZ-1110007-orphan-path-on-failed-add.patch
+Patch0087: 0087-RHBZ-1110013-config-error-checking.patch
+Patch0088: 0088-RHBZ-1069811-configurable-prio-timeout.patch
+Patch0089: 0089-RHBZ-1110016-add-noasync-option.patch
+Patch0090: 0090-UPBZ-1080038-reorder-paths-for-round-robin.patch
+Patch0091: 0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch
+Patch0092: 0092-UPBZ-1104605-reload-on-rename.patch
+Patch0093: 0093-UPBZ-1086825-user-friendly-name-remap.patch
+Patch0094: 0094-RHBZ-1086825-cleanup-remap.patch
+Patch0095: 0095-RHBZ-1127944-xtremIO-config.patch
+Patch0096: 0096-RHBZ-979474-new-wildcards.patch
+Patch0097: 0097-RH-fix-coverity-errors.patch
+Patch0098: 0098-UPBZ-1067171-mutipath-i.patch
+Patch0099: 0099-RH-add-all-devs.patch
+Patch0100: 0100-RHBZ-1067171-multipath-i-update.patch
+Patch0101: 0101-RH-adapter-name-wildcard.patch
# runtime
Requires: %{name}-libs = %{version}-%{release}
@@ -189,7 +210,7 @@ kpartx manages partition creation and removal for device-mapper devices.
%patch0047 -p1
%patch0048 -p1
%patch0049 -p1
-# %%patch0050 -p1
+%patch0050 -p1
%patch0051 -p1
%patch0052 -p1
%patch0053 -p1
@@ -219,6 +240,27 @@ kpartx manages partition creation and removal for device-mapper devices.
%patch0078 -p1
%patch0079 -p1
%patch0080 -p1
+%patch0081 -p1
+%patch0082 -p1
+%patch0083 -p1
+%patch0084 -p1
+%patch0085 -p1
+%patch0086 -p1
+%patch0087 -p1
+%patch0088 -p1
+%patch0089 -p1
+%patch0090 -p1
+%patch0091 -p1
+%patch0092 -p1
+%patch0093 -p1
+%patch0094 -p1
+%patch0095 -p1
+%patch0096 -p1
+%patch0097 -p1
+%patch0098 -p1
+%patch0099 -p1
+%patch0100 -p1
+%patch0101 -p1
cp %{SOURCE1} .
%build
@@ -317,6 +359,58 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||:
%{_mandir}/man8/kpartx.8.gz
%changelog
+* Tue Sep 16 2014 Benjamin Marzinski <bmarzins@redhat.com> 0.4.9-68
+- Modify multipath.conf
+ * remove getuid_callout example
+- Re-add 0050-RH-listing-speedup.patch
+- Add 0081-RHBZ-1066264-check-prefix-on-rename.patch
+ * make multipath check the prefix on kpartx partitions during rename, and
+ copy the existing behaviour
+- Add 0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch
+ * If async tur checker fails on threads, don't retry with the sync version
+- Add 0083-RHBZ-1080055-orphan-paths-on-reload.patch
+ * Fix case where pathlist wasn't getting updated properly
+- Add 0084-RHBZ-1110000-multipath-man.patch
+ * fix errors in multipath man page
+- Add 0085-UPBZ-1110006-datacore-config.patch
+ * Add support for DataCore Virtual Disk
+- Add 0086-RHBZ-1110007-orphan-path-on-failed-add.patch
+ * If multipathd fails to add path correctly, it now fully orphans the path
+- Add 0087-RHBZ-1110013-config-error-checking.patch
+ * Improve multipath.conf error checking.
+- Add 0088-RHBZ-1069811-configurable-prio-timeout.patch
+ * checker_timeout now adjusts the timeouts of the prioritizers as well.
+- Add 0089-RHBZ-1110016-add-noasync-option.patch
+ * Add a new defaults option, "force_sync", that disables the async mode
+ of the path checkers. This is for cases where to many parallel checkers
+ hog the cpu
+- Add 0090-UPBZ-1080038-reorder-paths-for-round-robin.patch
+ * make multipathd order paths for better throughput in round-robin mode
+- Add 0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch
+ * check for null pointers in configuration reading code.
+- Add 0092-UPBZ-1104605-reload-on-rename.patch
+ * Reload table on rename if necessary
+- Add 0093-UPBZ-1086825-user-friendly-name-remap.patch
+ * Keep existing user_friend_name if possible
+- Add 0094-RHBZ-1086825-cleanup-remap.patch
+ * Cleanup issues with upstream patch
+- Add 0095-RHBZ-1127944-xtremIO-config.patch
+ * Add support for EMC ExtremIO devices
+- Add 0096-RHBZ-979474-new-wildcards.patch
+ * Add N, n, R, and r path wildcards to print World Wide ids
+- Add 0097-RH-fix-coverity-errors.patch
+ * Fix a number of unterminated strings and memory leaks on failure
+ paths.
+- Add 0098-UPBZ-1067171-mutipath-i.patch
+ * Add -i option to ignore wwids file when checking for valid paths
+- Add 0099-RH-add-all-devs.patch
+ * Add new devices config option all_devs. This makes the configuration
+ overwrite the specified values in all builtin configs
+- Add 0100-RHBZ-1067171-multipath-i-update.patch
+ * make -i work correctly with find_multipaths
+- Add 0101-RH-adapter-name-wildcard.patch
+ * Add 'a' path wildcard to print adapter name
+
* Sat Aug 16 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.9-67
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
diff --git a/multipath.conf b/multipath.conf
index 401992b..c7684fe 100644
--- a/multipath.conf
+++ b/multipath.conf
@@ -33,7 +33,6 @@ defaults {
# polling_interval 10
# selector "round-robin 0"
# path_grouping_policy multibus
-# getuid_callout "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
# prio alua
# path_checker readsector0
# rr_min_io 100
@@ -79,7 +78,6 @@ defaults {
# vendor "COMPAQ "
# product "HSV110 (C)COMPAQ"
# path_grouping_policy multibus
-# getuid_callout "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
# path_checker readsector0
# path_selector "round-robin 0"
# hardware_handler "0"