[device-mapper-multipath] Modify 0012-RH-udev-sync-support.patch Modify 0021-RHBZ-548874-add-find-multipaths.patch Modify 0022

Benjamin Marzinski bmarzins at fedoraproject.org
Fri Jul 15 23:18:28 UTC 2011


commit b0ec4a42c85b8a4962352eddffcba84132a2eb78
Author: Benjamin Marzinski <bmarzins at redhat.com>
Date:   Fri Jul 15 12:25:48 2011 -0500

    Modify 0012-RH-udev-sync-support.patch
    Modify 0021-RHBZ-548874-add-find-multipaths.patch
    Modify 0022-RHBZ-557845-RHEL5-style-partitions.patch
    Add 0025-RHBZ-508827-update-multipathd-manpage.patch through
        0101-RHBZ-631009-disable-udev-disk-rules-on-reload.patch
      * sync with current state of RHEL6. Next release should include a updated
        source tarball with most of these fixes rolled in.
    Add 0102-RHBZ-690828-systemd-unit-file.patch
      * Add Jóhann B. Guðmundsson's unit file for systemd.
      * Add sub-package sysvinit for SysV init script.
    Resolves: bz #690828

 0012-RH-udev-sync-support.patch                    |   22 +-
 0021-RHBZ-548874-add-find-multipaths.patch         |   94 ++--
 0022-RHBZ-557845-RHEL5-style-partitions.patch      |    8 +-
 0025-RHBZ-508827-update-multipathd-manpage.patch   |   68 +++
 0026-RHBZ-549636-default-path-selector.patch       |   98 +++
 0027-RHBZ-509443-enhance-show-config.patch         |  442 ++++++++++++++
 0028-RHBZ-452617-add-revision-parameter.patch      |   57 ++
 ...HBZ-567219-recalculate-pgs-in-checkerloop.patch |   68 +++
 ...-RHBZ-558636-check-if-multipath-owns-path.patch |  146 +++++
 0031-RHBZ-570546-display-avg-pg-prio.patch         |   23 +
 0032-RHBZ-575767-ontap_prio.patch                  |  617 ++++++++++++++++++++
 0033-RHBZ-573715-eurologic-config.patch            |   53 ++
 0034-RHBZ-579575-add-q-multipath-option.patch      |  135 +++++
 0035-RHBZ-467709-add-followover.patch              |  141 +++++
 0036-RH-clear-messages.patch                       |   46 ++
 0037-RH-adopt-paths.patch                          |   31 +
 0038-RHBZ-587201-IBM-SGI.patch                     |   61 ++
 0039-RHBZ-589153-manpage-update.patch              |  251 ++++++++
 0040-RHBZ-587695-add-checker-msg-alias.patch       |   17 +
 0041-RHBZ-587695-add-rdac-message.patch            |   54 ++
 0042-RHBZ-590038-fix-fast-io-fail-tmo.patch        |   17 +
 0043-RHBZ-590028-close-sysfs_attr_fd.patch         |   16 +
 0044-RHBZ-591940-dont-clear-daemon.patch           |   16 +
 0045-RHBZ-593379-dont-add-unknown-paths.patch      |   25 +
 0046-RHBZ-593426-move-adopt-path.patch             |   24 +
 0047-RHBZ-591608-only-switch-pgs-once.patch        |   52 ++
 0048-RHBZ-592494-fix-user-configs.patch            |  114 ++++
 0049-RHBZ-591644-enhance-mpathconf.patch           |  228 ++++++++
 0050-RHBZ-595400-fix-checker-tmo.patch             |   17 +
 0051-RHBZ-596156-mpathconf-man-page.patch          |  154 +++++
 0052-RHBZ-601247-fix-path-adoption.patch           |  115 ++++
 0053-RHBZ-596323-remember_more_wwids.patch         |   16 +
 0054-RHBZ-596319-rules-cleanup.patch               |   41 ++
 0055-RHBZ-602257-update-on-show-topology.patch     |  142 +++++
 0056-RHBZ-603812-better-type-check.patch           |   91 +++
 0057-RHBZ-607869-fix-resize.patch                  |   35 ++
 0058-RHBZ-601665-assemble-features.patch           |   66 +++
 0059-RHBZ-607874-handle-offlined-paths.patch       |   68 +++
 0060-RHBZ-606420-fix-remove-map.patch              |   16 +
 0061-RHBZ-620479-find-rport.patch                  |   77 +++
 0062-RHBZ-592998-hpsc-config.patch                 |   17 +
 0063-RHBZ-595719-udev_link_priority.patch          |   19 +
 0064-RHBZ-612173-fix-reverse-lookup.patch          |   13 +
 0065-RHBZ-635088-update-priority.patch             |   79 +++
 0066-RHBZ-636071-mpathconf-variable_names.patch    |   35 ++
 0067-RHBZ-622569-symmetrix-config.patch            |   36 ++
 0068-RHBZ-632734-nvdisk-config.patch               |   89 +++
 0069-RHBZ-636246-hp-open-config.patch              |   74 +++
 0070-RHBZ-639037-hitachi-open-config.patch         |   30 +
 0071-RHBZ-611779-fix-whitespace-crash.patch        |   20 +
 0072-RHBZ-651389-change-scsi-tmo-order.patch       |   34 ++
 0073-RHBZ-650664-clarify-error-msg.patch           |  157 +++++
 0074-RHBZ-602883-dont-print-change.patch           |   31 +
 0075-RHBZ-576919-log-checker-err.patch             |  139 +++++
 0076-RHBZ-599690-update-multipath-conf.patch       |   18 +
 0077-RHBZ-622608-nvdisk-config.patch               |   49 ++
 0078-RHBZ-628095-config-warnings.patch             |  248 ++++++++
 0079-RHBZ-650797-display-iscsi-tgt-name.patch      |   55 ++
 ...-RHBZ-662731-fix-no-config-value-segfault.patch |   31 +
 0081-RHBZ-623644-fix-sysfs-caching.patch           |  376 ++++++++++++
 0083-RHBZ-636213-633643-new-configs.patch          |   99 ++++
 0084-RHBZ-644111-read-only-bindings.patch          |  160 +++++
 0085-RHBZ-645605-fix-offline-check.patch           |   17 +
 0086-RHBZ-681144-sysfs-device-cleanup.patch        |   92 +++
 0087-RHBZ-680480-skip-if-no-sysdev.patch           |   19 +
 0088-RHBZ-693524-fix-prio-segfault.patch           |   29 +
 0089-RHBZ-694602-RSSM-config.patch                 |   58 ++
 0090-RHBZ-700169-fix-nr-active.patch               |   17 +
 0091-RHBZ-699577-manpage-clarification.patch       |   51 ++
 0092-RHBZ-689504-rdac-retry.patch                  |   64 ++
 0093-RHBZ-677449-dont-remove-map-on-enomem.patch   |   18 +
 0094-RHBZ-707560-check-return-value.patch          |   18 +
 0095-RHBZ-678673-no-path-groups.patch              |   30 +
 0096-RHBZ-683616-ioship-support.patch              |  151 +++++
 0097-RHBZ-697386-fix-shutdown-crash.patch          |   17 +
 0098-RHBZ-706555-dont-update-pgs-in-manual.patch   |   18 +
 0099-RHBZ-705854-warn-on-bad-dev-loss-tmo.patch    |   17 +
 0100-RHBZ-710478-deprecate-uid-gid-mode.patch      |  162 +++++
 ...-631009-disable-udev-disk-rules-on-reload.patch |  173 ++++++
 0102-RHBZ-690828-systemd-unit-file.patch           |   58 ++
 device-mapper-multipath.spec                       |  222 +++++++-
 81 files changed, 6741 insertions(+), 61 deletions(-)
---
diff --git a/0012-RH-udev-sync-support.patch b/0012-RH-udev-sync-support.patch
index b30828c..6450985 100644
--- a/0012-RH-udev-sync-support.patch
+++ b/0012-RH-udev-sync-support.patch
@@ -1,14 +1,14 @@
 ---
  kpartx/devmapper.c       |   10 ++++++++--
  kpartx/devmapper.h       |    4 ++--
- kpartx/kpartx.c          |   22 ++++++++++++++++------
+ kpartx/kpartx.c          |   28 ++++++++++++++++++++--------
  libmultipath/config.h    |    2 ++
  libmultipath/configure.c |    2 +-
  libmultipath/devmapper.c |   29 +++++++++++++++++++----------
  libmultipath/devmapper.h |    8 +++++---
  multipath/main.c         |    1 +
  multipathd/main.c        |    1 +
- 9 files changed, 55 insertions(+), 24 deletions(-)
+ 9 files changed, 59 insertions(+), 26 deletions(-)
 
 Index: multipath-tools/kpartx/devmapper.c
 ===================================================================
@@ -131,7 +131,23 @@ Index: multipath-tools/kpartx/kpartx.c
  					fprintf(stderr, "resume failed on %s\n",
  						partname);
  					r++;
-@@ -557,6 +566,7 @@ main(int argc, char **argv){
+@@ -529,11 +538,13 @@ main(int argc, char **argv){
+ 					dm_addmap(op, partname, DM_TARGET, params,
+ 						  slices[j].size, uuid, j+1,
+ 						  buf.st_mode & 0777,
+-						  buf.st_uid, buf.st_gid);
++						  buf.st_uid, buf.st_gid,
++						  &cookie);
+ 
+ 					if (op == DM_DEVICE_RELOAD)
+ 						dm_simplecmd(DM_DEVICE_RESUME,
+-							     partname, 1);
++							     partname, 1,
++							     &cookie);
+ 
+ 					dm_devn(partname, &slices[j].major,
+ 						&slices[j].minor);
+@@ -557,6 +568,7 @@ main(int argc, char **argv){
  		if (n > 0)
  			break;
  	}
diff --git a/0021-RHBZ-548874-add-find-multipaths.patch b/0021-RHBZ-548874-add-find-multipaths.patch
index 12ec02c..e1229a7 100644
--- a/0021-RHBZ-548874-add-find-multipaths.patch
+++ b/0021-RHBZ-548874-add-find-multipaths.patch
@@ -4,18 +4,18 @@
  libmultipath/alias.h     |    1 
  libmultipath/config.c    |    5 -
  libmultipath/config.h    |    1 
- libmultipath/configure.c |   23 ++++
+ libmultipath/configure.c |   22 ++++
  libmultipath/defaults.h  |    2 
  libmultipath/dict.c      |   34 ++++++
  libmultipath/file.c      |  178 +++++++++++++++++++++++++++++++++++
  libmultipath/file.h      |   11 ++
- libmultipath/finder.c    |  150 ++++++++++++++++++++++++++++++
+ libmultipath/finder.c    |  165 +++++++++++++++++++++++++++++++++
  libmultipath/finder.h    |   18 +++
  multipath/Makefile       |    2 
  multipath/main.c         |    2 
  multipath/mpathconf      |  234 +++++++++++++++++++++++++++++++++++++++++++++++
- multipathd/main.c        |   27 +++--
- 16 files changed, 679 insertions(+), 163 deletions(-)
+ multipathd/main.c        |   24 +++-
+ 16 files changed, 690 insertions(+), 163 deletions(-)
 
 Index: multipath-tools/libmultipath/alias.c
 ===================================================================
@@ -240,7 +240,7 @@ Index: multipath-tools/libmultipath/config.c
  		condlog(0,
  "/usr/share/doc/device-mapper-multipath-%d.%d.%d/multipath.conf",
  			MULTIPATH_VERSION(VERSION_CODE));
-+		condlog(0, 
++		condlog(0,
 +"You can run /sbin/mpathconf to create or modify /etc/multipath.conf");
  		conf->blist_devnode = vector_alloc();
  		if (!conf->blist_devnode) {
@@ -269,7 +269,16 @@ Index: multipath-tools/libmultipath/configure.c
  
  extern int
  setup_map (struct multipath * mpp)
-@@ -462,6 +463,10 @@ coalesce_paths (struct vectors * vecs, v
+@@ -403,6 +404,8 @@ domap (struct multipath * mpp)
+ 		 * DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
+ 		 * succeeded
+ 		 */
++		if (mpp->action == ACT_CREATE)
++			remember_wwid(mpp->wwid);
+ 		if (!conf->daemon) {
+ 			/* multipath client mode */
+ 			dm_switchgroup(mpp->alias, mpp->bestpg);
+@@ -462,6 +465,10 @@ coalesce_paths (struct vectors * vecs, v
  
  	memset(empty_buff, 0, WWID_SIZE);
  
@@ -280,7 +289,7 @@ Index: multipath-tools/libmultipath/configure.c
  	if (force_reload) {
  		vector_foreach_slot (pathvec, pp1, k) {
  			pp1->mpp = NULL;
-@@ -472,21 +477,35 @@ coalesce_paths (struct vectors * vecs, v
+@@ -472,21 +479,32 @@ coalesce_paths (struct vectors * vecs, v
  
  		/* 1. if path has no unique id or wwid blacklisted */
  		if (memcmp(empty_buff, pp1->wwid, WWID_SIZE) == 0 ||
@@ -306,13 +315,10 @@ Index: multipath-tools/libmultipath/configure.c
  			continue;
  
 +		/* If find_multipaths was selected check if the path is valid */
-+		if (conf->find_multipaths){
-+			if (refwwid || should_multipath(pp1, pathvec))
-+				remember_wwid(pp1->wwid);
-+			else {
-+				orphan_path(pp1);
-+				continue;
-+			}
++		if (conf->find_multipaths && !refwwid &&
++		    !should_multipath(pp1, pathvec)){
++			orphan_path(pp1);
++			continue;
 +		}
 +
  		/*
@@ -599,7 +605,7 @@ Index: multipath-tools/libmultipath/finder.c
 ===================================================================
 --- /dev/null
 +++ multipath-tools/libmultipath/finder.c
-@@ -0,0 +1,150 @@
+@@ -0,0 +1,165 @@
 +#include <stdlib.h>
 +#include <errno.h>
 +#include <unistd.h>
@@ -622,18 +628,33 @@ Index: multipath-tools/libmultipath/finder.c
 +
 +static int
 +lookup_wwid(FILE *f, char *wwid) {
++	int c;
 +	char buf[LINE_MAX];
++	int count;
 +
-+	while (fgets(buf, LINE_MAX, f)) {
-+		char *c;
-+
-+		c = strpbrk(buf, "#\n\r");
-+		if (c)
-+			*c = '\0';
-+		if (*buf == '\0')
-+			continue;
-+		if (strncmp(wwid, buf, WWID_SIZE) == 0)
++	while ((c = fgetc(f)) != EOF){
++		if (c != '/') {
++			if (fgets(buf, LINE_MAX, f) == NULL)
++				return 0;
++			else
++				continue;
++		}
++		count = 0;
++		while ((c = fgetc(f)) != '/') {
++			if (c == EOF)
++				return 0;
++			if (count >= WWID_SIZE - 1)
++				goto next;
++			if (wwid[count] == '\0')
++				goto next;
++			if (c != wwid[count++])
++				goto next;
++		}
++		if (wwid[count] == '\0')
 +			return 1;
++next:
++		if (fgets(buf, LINE_MAX, f) == NULL)
++			return 0;
 +	}
 +	return 0;
 +}
@@ -642,10 +663,10 @@ Index: multipath-tools/libmultipath/finder.c
 +write_out_wwid(int fd, char *wwid) {
 +	int ret;
 +	off_t offset;
-+	char buf[WWID_SIZE + 1];
++	char buf[WWID_SIZE + 3];
 +
-+	ret = snprintf(buf, WWID_SIZE + 1, "%s\n", wwid);
-+	if (ret > WWID_SIZE || ret < 0){
++	ret = snprintf(buf, WWID_SIZE + 3, "/%s/\n", wwid);
++	if (ret >= (WWID_SIZE + 3) || ret < 0){
 +		condlog(0, "can't format wwid for writing (%d) : %s",
 +			ret, strerror(errno));
 +		return -1;
@@ -807,7 +828,7 @@ Index: multipath-tools/multipathd/main.c
  	}
  	if (filter_path(conf, pp) > 0){
  		int i = find_slot(vecs->pathvec, (void *)pp);
-@@ -412,18 +413,26 @@ rescan:
+@@ -412,18 +413,23 @@ rescan:
  		condlog(4,"%s: adopting all paths for path %s",
  			mpp->alias, pp->dev);
  		if (adopt_paths(vecs->pathvec, mpp))
@@ -819,13 +840,10 @@ Index: multipath-tools/multipathd/main.c
  		mpp->action = ACT_RELOAD;
  	}
  	else {
-+		if (conf->find_multipaths) {
-+			if (should_multipath(pp, vecs->pathvec))
-+				remember_wwid(pp->wwid);
-+			else {
-+				orphan_path(pp);
-+				return 0;
-+			}
++		if (conf->find_multipaths &&
++		    !should_multipath(pp, vecs->pathvec)) {
++			orphan_path(pp);
++			return 0;
 +		}
  		condlog(4,"%s: creating new map", pp->dev);
  		if ((mpp = add_map_with_path(vecs, pp, 1)))
@@ -836,7 +854,7 @@ Index: multipath-tools/multipathd/main.c
  	}
  
  	/*
-@@ -432,7 +441,7 @@ rescan:
+@@ -432,7 +438,7 @@ rescan:
  	if (setup_map(mpp)) {
  		condlog(0, "%s: failed to setup map for addition of new "
  			"path %s", mpp->alias, devname);
@@ -845,7 +863,7 @@ Index: multipath-tools/multipathd/main.c
  	}
  	/*
  	 * reload the map for the multipath mapped device
-@@ -450,7 +459,7 @@ rescan:
+@@ -450,7 +456,7 @@ rescan:
  			goto rescan;
  		}
  		else
@@ -854,7 +872,7 @@ Index: multipath-tools/multipathd/main.c
  	}
  	dm_lib_release();
  
-@@ -458,19 +467,21 @@ rescan:
+@@ -458,19 +464,21 @@ rescan:
  	 * update our state from kernel regardless of create or reload
  	 */
  	if (setup_multipath(vecs, mpp))
diff --git a/0022-RHBZ-557845-RHEL5-style-partitions.patch b/0022-RHBZ-557845-RHEL5-style-partitions.patch
index 95488b8..8c87256 100644
--- a/0022-RHBZ-557845-RHEL5-style-partitions.patch
+++ b/0022-RHBZ-557845-RHEL5-style-partitions.patch
@@ -187,7 +187,7 @@ Index: multipath-tools/kpartx/kpartx.c
  				if (safe_sprintf(partname, "%s%s%d",
  					     mapname, delim, j+1)) {
  					fprintf(stderr, "partname too small\n");
-@@ -493,70 +468,6 @@ main(int argc, char **argv){
+@@ -493,72 +468,6 @@ main(int argc, char **argv){
  					       slices[j].minor, slices[j].size,
  					       DM_TARGET, params);
  			}
@@ -236,11 +236,13 @@ Index: multipath-tools/kpartx/kpartx.c
 -					dm_addmap(op, partname, DM_TARGET, params,
 -						  slices[j].size, uuid, j+1,
 -						  buf.st_mode & 0777,
--						  buf.st_uid, buf.st_gid);
+-						  buf.st_uid, buf.st_gid,
+-						  &cookie);
 -
 -					if (op == DM_DEVICE_RELOAD)
 -						dm_simplecmd(DM_DEVICE_RESUME,
--							     partname, 1);
+-							     partname, 1,
+-							     &cookie);
 -
 -					dm_devn(partname, &slices[j].major,
 -						&slices[j].minor);
diff --git a/0025-RHBZ-508827-update-multipathd-manpage.patch b/0025-RHBZ-508827-update-multipathd-manpage.patch
new file mode 100644
index 0000000..27d787a
--- /dev/null
+++ b/0025-RHBZ-508827-update-multipathd-manpage.patch
@@ -0,0 +1,68 @@
+Index: multipath-tools/multipathd/multipathd.8
+===================================================================
+--- multipath-tools.orig/multipathd/multipathd.8
++++ multipath-tools/multipathd/multipathd.8
+@@ -35,9 +35,20 @@ The following commands can be used in in
+ .B list|show paths
+ Show the paths that multipathd is monitoring, and their state. 
+ .TP
++.B list|show paths format $format
++Show the paths that multipathd is monitoring, using a format string with path
++format wildcards.
++.TP
++.B list|show status
++Show the number of monitored paths in each path checker state.
++.TP
+ .B list|show maps|multipaths
+ Show the multipath devices that the multipathd is monitoring. 
+ .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.
++.TP
+ .B list|show maps|multipaths status
+ Show the status of all multipath devices that the multipathd is monitoring.
+ .TP
+@@ -54,6 +65,9 @@ Show the current multipath topology. Sam
+ Show topology of a single multipath device specified by $map, e.g. 36005076303ffc56200000000000010aa.
+ This map could be obtained from "list maps".
+ .TP
++.B list|show wildcards
++Show the format wildcards used in interactive commands taking $format
++.TP
+ .B list|show config
+ Show the currently used configuration, derived from default values and values specified within the configuration file /etc/multipath.conf.
+ .TP
+@@ -69,6 +83,10 @@ 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 paths count
++Show the number of monitored paths, and whether multipathd is currently
++handeling a uevent.
++.TP
+ .B add map $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
+@@ -96,11 +114,20 @@ Sets path $path into failed state.
+ .B reinstate path $path
+ Resumes path $path from failed state.
+ .TP
++.B disablequeueing maps|multipaths
++Disable queueing on all multipath devices.
++.TP
++.B restorequeueing maps|multipaths
++Restore queueing on all multipath devices.
++.TP
+ .B disablequeueing map|multipath $map
+-Disabled queuing on multipathed map $map
++Disable queuing on multipathed map $map
+ .TP
+ .B restorequeueing map|multipath $map
+ Restore queuing on multipahted map $map
++.TP
++.B quit|exit
++End interactive session.
+ 
+ .SH "SEE ALSO"
+ .BR multipath (8)
diff --git a/0026-RHBZ-549636-default-path-selector.patch b/0026-RHBZ-549636-default-path-selector.patch
new file mode 100644
index 0000000..4b7b460
--- /dev/null
+++ b/0026-RHBZ-549636-default-path-selector.patch
@@ -0,0 +1,98 @@
+---
+ libmultipath/dict.c        |    2 +-
+ multipath.conf.annotated   |    4 ++--
+ multipath.conf.defaults    |    2 +-
+ multipath.conf.synthetic   |    2 +-
+ multipath/multipath.conf.5 |   18 +++++++++++++++---
+ 5 files changed, 20 insertions(+), 8 deletions(-)
+
+Index: multipath-tools/libmultipath/dict.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dict.c
++++ multipath-tools/libmultipath/dict.c
+@@ -2181,7 +2181,7 @@ init_keywords(void)
+ 	install_keyword("polling_interval", &polling_interval_handler, &snprint_def_polling_interval);
+ 	install_keyword("udev_dir", &udev_dir_handler, &snprint_def_udev_dir);
+ 	install_keyword("multipath_dir", &multipath_dir_handler, &snprint_def_multipath_dir);
+-	install_keyword("selector", &def_selector_handler, &snprint_def_selector);
++	install_keyword("path_selector", &def_selector_handler, &snprint_def_selector);
+ 	install_keyword("path_grouping_policy", &def_pgpolicy_handler, &snprint_def_path_grouping_policy);
+ 	install_keyword("getuid_callout", &def_getuid_callout_handler, &snprint_def_getuid_callout);
+ 	install_keyword("prio", &def_prio_handler, &snprint_def_prio);
+Index: multipath-tools/multipath.conf.annotated
+===================================================================
+--- multipath-tools.orig/multipath.conf.annotated
++++ multipath-tools/multipath.conf.annotated
+@@ -27,14 +27,14 @@
+ #	polling_interval 10
+ #
+ #	#
+-#	# name    : selector
++#	# name    : path_selector
+ #	# scope   : multipath
+ #	# desc    : the default path selector algorithm to use
+ #	#           these algorithms are offered by the kernel multipath target
+ #	# values  : "round-robin 0"
+ #	# default : "round-robin 0"
+ #	#
+-#	selector	"round-robin 0"
++#	path_selector	"round-robin 0"
+ #
+ #	#
+ #	# name    : path_grouping_policy
+Index: multipath-tools/multipath.conf.defaults
+===================================================================
+--- multipath-tools.orig/multipath.conf.defaults
++++ multipath-tools/multipath.conf.defaults
+@@ -4,7 +4,7 @@
+ #defaults {
+ #	udev_dir		/dev
+ #	polling_interval	5
+-#	selector		"round-robin 0"
++#	path_selector		"round-robin 0"
+ #	path_grouping_policy	failover
+ #	getuid_callout		"/lib/udev/scsi_id --whitelisted --device=/dev/%n"
+ #	prio			const
+Index: multipath-tools/multipath.conf.synthetic
+===================================================================
+--- multipath-tools.orig/multipath.conf.synthetic
++++ multipath-tools/multipath.conf.synthetic
+@@ -5,7 +5,7 @@
+ #defaults {
+ #	udev_dir		/dev
+ #	polling_interval 	10
+-#	selector		"round-robin 0"
++#	path_selector		"round-robin 0"
+ #	path_grouping_policy	multibus
+ #	getuid_callout		"/lib/udev/scsi_id --whitelisted --device=/dev/%n"
+ #	prio			const
+Index: multipath-tools/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools.orig/multipath/multipath.conf.5
++++ multipath-tools/multipath/multipath.conf.5
+@@ -81,10 +81,22 @@ default verbosity. Higher values increas
+ levels are between 0 and 6; default is
+ .I 2
+ .TP
+-.B selector
++.B path_selector
+ The default path selector algorithm to use; they are offered by the
+-kernel multipath target. The only currently implemented is
+-.I "round-robin 0"
++kernel multipath target. There are three selector algorithms.
++.RS
++.TP 12
++.B "round-robin 0"
++Loop through every path in the path group, sending the same amount of IO to
++each.
++.TP
++.B "queue-length 0"
++Send the next bunch of IO down the path with the least amount of outstanding IO.
++.TP
++.B "service-time 0"
++Choose the path for the next bunch of IO based on the amount of outstanding IO
++to the path and its relative throughput.
++.RE
+ .TP
+ .B path_grouping_policy
+ The default path grouping policy to apply to unspecified
diff --git a/0027-RHBZ-509443-enhance-show-config.patch b/0027-RHBZ-509443-enhance-show-config.patch
new file mode 100644
index 0000000..df93d36
--- /dev/null
+++ b/0027-RHBZ-509443-enhance-show-config.patch
@@ -0,0 +1,442 @@
+---
+ libmultipath/dict.c |  137 ++++++++++++++--------------------------------------
+ 1 file changed, 39 insertions(+), 98 deletions(-)
+
+Index: multipath-tools/libmultipath/dict.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dict.c
++++ multipath-tools/libmultipath/dict.c
+@@ -328,6 +328,10 @@ def_weight_handler(vector strvec)
+ 	    !strcmp(buff, "priorities"))
+ 		conf->rr_weight = RR_WEIGHT_PRIO;
+ 
++	if (strlen(buff) == strlen("uniform") &&
++	    !strcmp(buff, "uniform"))
++		conf->rr_weight = RR_WEIGHT_NONE;
++
+ 	FREE(buff);
+ 
+ 	return 0;
+@@ -923,6 +927,10 @@ hw_weight_handler(vector strvec)
+ 	    !strcmp(buff, "priorities"))
+ 		hwe->rr_weight = RR_WEIGHT_PRIO;
+ 
++	if (strlen(buff) == strlen("uniform") &&
++	    !strcmp(buff, "uniform"))
++		hwe->rr_weight = RR_WEIGHT_NONE;
++
+ 	FREE(buff);
+ 
+ 	return 0;
+@@ -1251,6 +1259,10 @@ mp_weight_handler(vector strvec)
+ 	    !strcmp(buff, "priorities"))
+ 		mpe->rr_weight = RR_WEIGHT_PRIO;
+ 
++	if (strlen(buff) == strlen("uniform") &&
++	    !strcmp(buff, "uniform"))
++		mpe->rr_weight = RR_WEIGHT_NONE;
++
+ 	FREE(buff);
+ 
+ 	return 0;
+@@ -1402,11 +1414,6 @@ snprint_mp_alias (char * buff, int len, 
+ 	if (!mpe->alias)
+ 		return 0;
+ 
+-	if (conf->user_friendly_names &&
+-	    (strlen(mpe->alias) == strlen("mpath")) &&
+-	    !strcmp(mpe->alias, "mpath"))
+-		return 0;
+-
+ 	return snprintf(buff, len, "%s", mpe->alias);
+ }
+ 
+@@ -1431,7 +1438,7 @@ snprint_mp_selector (char * buff, int le
+ 	if (!mpe->selector)
+ 		return 0;
+ 
+-	return snprintf(buff, len, "%s", mpe->selector);
++	return snprintf(buff, len, "\"%s\"", mpe->selector);
+ }
+ 
+ static int
+@@ -1494,6 +1501,8 @@ snprint_mp_rr_weight (char * buff, int l
+ 		return 0;
+ 	if (mpe->rr_weight == RR_WEIGHT_PRIO)
+ 		return snprintf(buff, len, "priorities");
++	if (mpe->rr_weight == RR_WEIGHT_NONE)
++		return snprintf(buff, len, "uniform");
+ 
+ 	return 0;
+ }
+@@ -1568,8 +1577,6 @@ snprint_mp_prio (char * buff, int len, v
+ 
+ 	if (!mpe->prio_name)
+ 		return 0;
+-	if (!strcmp(mpe->prio_name, conf->prio_name) && !mpe->prio_args)
+-		return 0;
+ 	if (!mpe->prio_args)
+ 		return snprintf(buff, len, "%s", mpe->prio_name);
+ 	return snprintf(buff, len, "%s %s", mpe->prio_name, mpe->prio_args);
+@@ -1635,9 +1642,6 @@ snprint_hw_getuid_callout (char * buff, 
+ 
+ 	if (!hwe->getuid)
+ 		return 0;
+-	if (strlen(hwe->getuid) == strlen(conf->getuid) &&
+-	    !strcmp(hwe->getuid, conf->getuid))
+-		return 0;
+ 
+ 	return snprintf(buff, len, "\"%s\"", hwe->getuid);
+ }
+@@ -1649,8 +1653,6 @@ snprint_hw_prio (char * buff, int len, v
+ 
+ 	if (!hwe->prio_name)
+ 		return 0;
+-	if (!strcmp(hwe->prio_name, conf->prio_name) && !hwe->prio_args)
+-		return 0;
+ 	if (!hwe->prio_args)
+ 		return snprintf(buff, len, "%s", hwe->prio_name);
+ 	return snprintf(buff, len, "%s %s", hwe->prio_name, hwe->prio_args);
+@@ -1663,9 +1665,6 @@ snprint_hw_features (char * buff, int le
+ 
+ 	if (!hwe->features)
+ 		return 0;
+-	if (strlen(hwe->features) == strlen(conf->features) &&
+-	    !strcmp(hwe->features, conf->features))
+-		return 0;
+ 
+ 	return snprintf(buff, len, "\"%s\"", hwe->features);
+ }
+@@ -1677,9 +1676,6 @@ snprint_hw_hardware_handler (char * buff
+ 
+ 	if (!hwe->hwhandler)
+ 		return 0;
+-	if (strlen(hwe->hwhandler) == strlen(conf->hwhandler) &&
+-	    !strcmp(hwe->hwhandler, conf->hwhandler))
+-		return 0;
+ 
+ 	return snprintf(buff, len, "\"%s\"", hwe->hwhandler);
+ }
+@@ -1691,11 +1687,8 @@ snprint_hw_selector (char * buff, int le
+ 
+ 	if (!hwe->selector)
+ 		return 0;
+-	if (strlen(hwe->selector) == strlen(conf->selector) &&
+-	    !strcmp(hwe->selector, conf->selector))
+-		return 0;
+ 
+-	return snprintf(buff, len, "%s", hwe->selector);
++	return snprintf(buff, len, "\"%s\"", hwe->selector);
+ }
+ 
+ static int
+@@ -1707,8 +1700,6 @@ snprint_hw_path_grouping_policy (char * 
+ 
+ 	if (!hwe->pgpolicy)
+ 		return 0;
+-	if (hwe->pgpolicy == conf->pgpolicy)
+-		return 0;
+ 
+ 	get_pgpolicy_name(str, POLICY_NAME_SIZE, hwe->pgpolicy);
+ 
+@@ -1722,8 +1713,6 @@ snprint_hw_failback (char * buff, int le
+ 
+ 	if (!hwe->pgfailback)
+ 		return 0;
+-	if (hwe->pgfailback == conf->pgfailback)
+-		return 0;
+ 
+ 	switch(hwe->pgfailback) {
+ 	case  FAILBACK_UNDEF:
+@@ -1745,10 +1734,10 @@ snprint_hw_rr_weight (char * buff, int l
+ 
+ 	if (!hwe->rr_weight)
+ 		return 0;
+-	if (hwe->rr_weight == conf->rr_weight)
+-		return 0;
+ 	if (hwe->rr_weight == RR_WEIGHT_PRIO)
+ 		return snprintf(buff, len, "priorities");
++	if (hwe->rr_weight == RR_WEIGHT_NONE)
++		return snprintf(buff, len, "uniform");
+ 
+ 	return 0;
+ }
+@@ -1760,8 +1749,6 @@ snprint_hw_no_path_retry (char * buff, i
+ 
+ 	if (!hwe->no_path_retry)
+ 		return 0;
+-	if (hwe->no_path_retry == conf->no_path_retry)
+-		return 0;
+ 
+ 	switch(hwe->no_path_retry) {
+ 	case NO_PATH_RETRY_UNDEF:
+@@ -1784,8 +1771,6 @@ snprint_hw_rr_min_io (char * buff, int l
+ 
+ 	if (!hwe->minio)
+ 		return 0;
+-	if (hwe->minio == conf->minio)
+-		return 0;
+ 
+ 	return snprintf(buff, len, "%u", hwe->minio);
+ }
+@@ -1797,8 +1782,6 @@ snprint_hw_pg_timeout (char * buff, int 
+ 
+ 	if (!hwe->pg_timeout)
+ 		return 0;
+-	if (hwe->pg_timeout == conf->pg_timeout)
+-		return 0;
+ 
+ 	switch (hwe->pg_timeout) {
+ 	case PGTIMEOUT_UNDEF:
+@@ -1832,8 +1815,6 @@ snprint_hw_path_checker (char * buff, in
+ 
+ 	if (!hwe->checker_name)
+ 		return 0;
+-	if (!strcmp(hwe->checker_name, conf->checker_name))
+-		return 0;
+ 	
+ 	return snprintf(buff, len, "%s", hwe->checker_name);
+ }
+@@ -1841,8 +1822,6 @@ snprint_hw_path_checker (char * buff, in
+ static int
+ snprint_def_polling_interval (char * buff, int len, void * data)
+ {
+-	if (conf->checkint == DEFAULT_CHECKINT)
+-		return 0;
+ 	return snprintf(buff, len, "%i", conf->checkint);
+ }
+ 
+@@ -1867,8 +1846,6 @@ snprint_def_dev_loss(char * buff, int le
+ static int
+ snprint_def_verbosity (char * buff, int len, void * data)
+ {
+-	if (conf->checkint == DEFAULT_VERBOSITY)
+-		return 0;
+ 	return snprintf(buff, len, "%i", conf->verbosity);
+ }
+ 
+@@ -1877,9 +1854,6 @@ snprint_def_udev_dir (char * buff, int l
+ {
+ 	if (!conf->udev_dir)
+ 		return 0;
+-	if (strlen(DEFAULT_UDEVDIR) == strlen(conf->udev_dir) &&
+-	    !strcmp(conf->udev_dir, DEFAULT_UDEVDIR))
+-		return 0;
+ 
+ 	return snprintf(buff, len, "\"%s\"", conf->udev_dir);
+ }
+@@ -1887,10 +1861,7 @@ snprint_def_udev_dir (char * buff, int l
+ static int
+ snprint_def_multipath_dir (char * buff, int len, void * data)
+ {
+-	if (!conf->udev_dir)
+-		return 0;
+-	if (strlen(DEFAULT_MULTIPATHDIR) == strlen(conf->multipath_dir) &&
+-	    !strcmp(conf->multipath_dir, DEFAULT_MULTIPATHDIR))
++	if (!conf->multipath_dir)
+ 		return 0;
+ 
+ 	return snprintf(buff, len, "\"%s\"", conf->multipath_dir);
+@@ -1901,11 +1872,8 @@ snprint_def_selector (char * buff, int l
+ {
+ 	if (!conf->selector)
+ 		return 0;
+-	if (strlen(conf->selector) == strlen(DEFAULT_SELECTOR) &&
+-	    !strcmp(conf->selector, DEFAULT_SELECTOR))
+-		return 0;
+ 
+-	return snprintf(buff, len, "%s", conf->selector);
++	return snprintf(buff, len, "\"%s\"", conf->selector);
+ }
+ 
+ static int
+@@ -1913,12 +1881,10 @@ snprint_def_path_grouping_policy (char *
+ {
+ 	char str[POLICY_NAME_SIZE];
+ 
+-	if (!conf->pgpolicy)
+-		return 0;
+-	if (conf->pgpolicy == DEFAULT_PGPOLICY)
+-		return 0;
+-
+-	get_pgpolicy_name(str, POLICY_NAME_SIZE, conf->pgpolicy);
++	if (conf->pgpolicy)
++		get_pgpolicy_name(str, POLICY_NAME_SIZE, conf->pgpolicy);
++	else
++		get_pgpolicy_name(str, POLICY_NAME_SIZE, DEFAULT_PGPOLICY);
+ 
+ 	return snprintf(buff, len, "%s", str);
+ }
+@@ -1928,9 +1894,6 @@ snprint_def_getuid_callout (char * buff,
+ {
+ 	if (!conf->getuid)
+ 		return 0;
+-	if (strlen(conf->getuid) == strlen(DEFAULT_GETUID) &&
+-	    !strcmp(conf->getuid, DEFAULT_GETUID))
+-		return 0;
+ 
+ 	return snprintf(buff, len, "\"%s\"", conf->getuid);
+ }
+@@ -1941,10 +1904,6 @@ snprint_def_prio (char * buff, int len, 
+ 	if (!conf->prio_name)
+ 		return 0;
+ 
+-	if (strlen(conf->prio_name) == strlen(DEFAULT_PRIO) &&
+-	    !strcmp(conf->prio_name, DEFAULT_PRIO) && !conf->prio_args)
+-		return 0;
+-
+ 	if (!conf->prio_args)
+ 		return snprintf(buff, len, "%s", conf->prio_name);
+ 	else
+@@ -1957,9 +1916,6 @@ snprint_def_features (char * buff, int l
+ {
+ 	if (!conf->features)
+ 		return 0;
+-	if (strlen(conf->features) == strlen(DEFAULT_FEATURES) &&
+-	    !strcmp(conf->features, DEFAULT_FEATURES))
+-		return 0;
+ 
+ 	return snprintf(buff, len, "\"%s\"", conf->features);
+ }
+@@ -1969,9 +1925,6 @@ snprint_def_path_checker (char * buff, i
+ {
+ 	if (!conf->checker_name)
+ 		return 0;
+-	if (strlen(conf->checker_name) == strlen(DEFAULT_CHECKER) &&
+-	    !strcmp(conf->checker_name, DEFAULT_CHECKER))
+-		return 0;
+ 	
+ 	return snprintf(buff, len, "%s", conf->checker_name);
+ }
+@@ -1979,12 +1932,11 @@ snprint_def_path_checker (char * buff, i
+ static int
+ snprint_def_failback (char * buff, int len, void * data)
+ {
++	int pgfailback = conf->pgfailback;
+ 	if (!conf->pgfailback)
+-		return 0;
+-	if (conf->pgfailback == DEFAULT_FAILBACK)
+-		return 0;
++		pgfailback = DEFAULT_FAILBACK;
+ 
+-	switch(conf->pgfailback) {
++	switch(pgfailback) {
+ 	case  FAILBACK_UNDEF:
+ 		break;
+ 	case -FAILBACK_MANUAL:
+@@ -1992,7 +1944,7 @@ snprint_def_failback (char * buff, int l
+ 	case -FAILBACK_IMMEDIATE:
+ 		return snprintf(buff, len, "immediate");
+ 	default:
+-		return snprintf(buff, len, "%i", conf->pgfailback);
++		return snprintf(buff, len, "%i", pgfailback);
+ 	}
+ 	return 0;
+ }
+@@ -2000,12 +1952,10 @@ snprint_def_failback (char * buff, int l
+ static int
+ snprint_def_rr_min_io (char * buff, int len, void * data)
+ {
+-	if (!conf->minio)
+-		return 0;
+-	if (conf->minio == DEFAULT_MINIO)
+-		return 0;
+-
+-	return snprintf(buff, len, "%u", conf->minio);
++	if (conf->minio)
++		return snprintf(buff, len, "%u", conf->minio);
++	else
++		return snprintf(buff, len, "%u", DEFAULT_MINIO);
+ }
+ 
+ static int
+@@ -2045,11 +1995,11 @@ static int
+ snprint_def_rr_weight (char * buff, int len, void * data)
+ {
+ 	if (!conf->rr_weight)
+-		return 0;
+-	if (conf->rr_weight == DEFAULT_RR_WEIGHT)
+-		return 0;
++		return snprintf(buff, len, "uniform");
+ 	if (conf->rr_weight == RR_WEIGHT_PRIO)
+ 		return snprintf(buff, len, "priorities");
++	if (conf->rr_weight == RR_WEIGHT_NONE)
++		return snprintf(buff, len, "uniform");
+ 
+ 	return 0;
+ }
+@@ -2057,9 +2007,6 @@ snprint_def_rr_weight (char * buff, int 
+ static int
+ snprint_def_no_path_retry (char * buff, int len, void * data)
+ {
+-	if (conf->no_path_retry == DEFAULT_NO_PATH_RETRY)
+-		return 0;
+-
+ 	switch(conf->no_path_retry) {
+ 	case NO_PATH_RETRY_UNDEF:
+ 		break;
+@@ -2081,6 +2028,7 @@ snprint_def_queue_without_daemon (char *
+ 	case QUE_NO_DAEMON_OFF:
+ 		return snprintf(buff, len, "no");
+ 	case QUE_NO_DAEMON_ON:
++	case QUE_NO_DAEMON_UNDEF:
+ 		return snprintf(buff, len, "yes");
+ 	}
+ 	return 0;
+@@ -2098,12 +2046,8 @@ snprint_def_checker_timeout (char *buff,
+ static int
+ snprint_def_pg_timeout (char * buff, int len, void * data)
+ {
+-	if (conf->pg_timeout == DEFAULT_PGTIMEOUT)
+-		return 0;
+-
+ 	switch (conf->pg_timeout) {
+ 	case PGTIMEOUT_UNDEF:
+-		break;
+ 	case -PGTIMEOUT_NONE:
+ 		return snprintf(buff, len, "none");
+ 	default:
+@@ -2117,6 +2061,7 @@ snprint_def_flush_on_last_del (char * bu
+ {
+ 	switch (conf->flush_on_last_del) {
+ 	case FLUSH_DISABLED:
++	case FLUSH_UNDEF:
+ 		return snprintf(buff, len, "no");
+ 	case FLUSH_ENABLED:
+ 		return snprintf(buff, len, "yes");
+@@ -2127,8 +2072,6 @@ snprint_def_flush_on_last_del (char * bu
+ static int
+ snprint_def_find_multipaths (char * buff, int len, void * data)
+ {
+-	if (conf->find_multipaths == DEFAULT_FIND_MULTIPATHS)
+-		return 0;
+ 	if (!conf->find_multipaths)
+ 		return snprintf(buff, len, "no");
+ 
+@@ -2139,8 +2082,6 @@ snprint_def_find_multipaths (char * buff
+ static int
+ snprint_def_user_friendly_names (char * buff, int len, void * data)
+ {
+-	if (conf->user_friendly_names == DEFAULT_USER_FRIENDLY_NAMES)
+-		return 0;
+ 	if (!conf->user_friendly_names)
+ 		return snprintf(buff, len, "no");
+ 
+@@ -2187,7 +2128,7 @@ init_keywords(void)
+ 	install_keyword("prio", &def_prio_handler, &snprint_def_prio);
+ 	install_keyword("features", &def_features_handler, &snprint_def_features);
+ 	install_keyword("path_checker", &def_path_checker_handler, &snprint_def_path_checker);
+-	install_keyword("checker", &def_path_checker_handler, &snprint_def_path_checker);
++	install_keyword("checker", &def_path_checker_handler, NULL);
+ 	install_keyword("failback", &default_failback_handler, &snprint_def_failback);
+ 	install_keyword("rr_min_io", &def_minio_handler, &snprint_def_rr_min_io);
+ 	install_keyword("max_fds", &max_fds_handler, &snprint_max_fds);
+@@ -2248,7 +2189,7 @@ init_keywords(void)
+ 	install_keyword("getuid_callout", &hw_getuid_callout_handler, &snprint_hw_getuid_callout);
+ 	install_keyword("path_selector", &hw_selector_handler, &snprint_hw_selector);
+ 	install_keyword("path_checker", &hw_path_checker_handler, &snprint_hw_path_checker);
+-	install_keyword("checker", &hw_path_checker_handler, &snprint_hw_path_checker);
++	install_keyword("checker", &hw_path_checker_handler, NULL);
+ 	install_keyword("features", &hw_features_handler, &snprint_hw_features);
+ 	install_keyword("hardware_handler", &hw_handler_handler, &snprint_hw_hardware_handler);
+ 	install_keyword("prio", &hw_prio_handler, &snprint_hw_prio);
diff --git a/0028-RHBZ-452617-add-revision-parameter.patch b/0028-RHBZ-452617-add-revision-parameter.patch
new file mode 100644
index 0000000..fa244be
--- /dev/null
+++ b/0028-RHBZ-452617-add-revision-parameter.patch
@@ -0,0 +1,57 @@
+---
+ libmultipath/dict.c |   28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+Index: multipath-tools/libmultipath/dict.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dict.c
++++ multipath-tools/libmultipath/dict.c
+@@ -720,6 +720,22 @@ product_handler(vector strvec)
+ }
+ 
+ static int
++revision_handler(vector strvec)
++{
++	struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
++
++	if (!hwe)
++		return 1;
++
++	hwe->revision = set_value(strvec);
++
++	if (!hwe->revision)
++		return 1;
++
++	return 0;
++}
++
++static int
+ bl_product_handler(vector strvec)
+ {
+ 	struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
+@@ -1625,6 +1641,17 @@ snprint_hw_product (char * buff, int len
+ }
+ 
+ static int
++snprint_hw_revision (char * buff, int len, void * data)
++{
++	struct hwentry * hwe = (struct hwentry *)data;
++
++	if (!hwe->revision)
++		return 0;
++
++	return snprintf(buff, len, "\"%s\"", hwe->revision);
++}
++
++static int
+ snprint_hw_bl_product (char * buff, int len, void * data)
+ {
+ 	struct hwentry * hwe = (struct hwentry *)data;
+@@ -2184,6 +2211,7 @@ init_keywords(void)
+ 	install_sublevel();
+ 	install_keyword("vendor", &vendor_handler, &snprint_hw_vendor);
+ 	install_keyword("product", &product_handler, &snprint_hw_product);
++	install_keyword("revision", &revision_handler, &snprint_hw_revision);
+ 	install_keyword("product_blacklist", &bl_product_handler, &snprint_hw_bl_product);
+ 	install_keyword("path_grouping_policy", &hw_pgpolicy_handler, &snprint_hw_path_grouping_policy);
+ 	install_keyword("getuid_callout", &hw_getuid_callout_handler, &snprint_hw_getuid_callout);
diff --git a/0029-RHBZ-567219-recalculate-pgs-in-checkerloop.patch b/0029-RHBZ-567219-recalculate-pgs-in-checkerloop.patch
new file mode 100644
index 0000000..f7ec7b0
--- /dev/null
+++ b/0029-RHBZ-567219-recalculate-pgs-in-checkerloop.patch
@@ -0,0 +1,68 @@
+---
+ multipathd/main.c |   34 +++++++++++++++++++++++++++++-----
+ 1 file changed, 29 insertions(+), 5 deletions(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -48,6 +48,7 @@
+ #include <configure.h>
+ #include <prio.h>
+ #include <finder.h>
++#include <pgpolicies.h>
+ 
+ #include "main.h"
+ #include "pidfile.h"
+@@ -911,10 +912,33 @@ retry_count_tick(vector mpvec)
+ 	}
+ }
+ 
++int update_path_groups(struct multipath *mpp, struct vectors *vecs)
++{
++	int i;
++	struct path * pp;
++
++	update_mpp_paths(mpp, vecs->pathvec);
++	vector_foreach_slot (mpp->paths, pp, i)
++		pathinfo(pp, conf->hwtable, DI_PRIO);
++	setup_map(mpp);
++	mpp->action = ACT_RELOAD;
++	if (domap(mpp) <= 0) {
++		condlog(0, "%s: failed to update map : %s", mpp->alias,
++			strerror(errno));
++		return 1;
++	}
++	dm_lib_release();
++	setup_multipath(vecs, mpp);
++	sync_map_state(mpp);
++
++	return 0;
++}
++
+ void
+ check_path (struct vectors * vecs, struct path * pp)
+ {
+ 	int newstate;
++	int oldpriority;
+ 
+ 	if (!pp->mpp)
+ 		return;
+@@ -1024,12 +1048,12 @@ check_path (struct vectors * vecs, struc
+ 	 * path prio refreshing
+ 	 */
+ 	condlog(4, "path prio refresh");
++	oldpriority = pp->priority;
+ 	pathinfo(pp, conf->hwtable, DI_PRIO);
+-
+-	/*
+-	 * pathgroup failback policy
+-	 */
+-	if (need_switch_pathgroup(pp->mpp, 0)) {
++	if (pp->priority != oldpriority &&
++	    pp->mpp->pgpolicyfn == (pgpolicyfn *)group_by_prio)
++		update_path_groups(pp->mpp, vecs);
++	else if (need_switch_pathgroup(pp->mpp, 0)) {
+ 		if (pp->mpp->pgfailback > 0 &&
+ 		    pp->mpp->failback_tick <= 0)
+ 			pp->mpp->failback_tick =
diff --git a/0030-RHBZ-558636-check-if-multipath-owns-path.patch b/0030-RHBZ-558636-check-if-multipath-owns-path.patch
new file mode 100644
index 0000000..94d4c12
--- /dev/null
+++ b/0030-RHBZ-558636-check-if-multipath-owns-path.patch
@@ -0,0 +1,146 @@
+---
+ libmultipath/finder.c     |    2 +-
+ libmultipath/finder.h     |    1 +
+ multipath/main.c          |   35 ++++++++++++++++++++++++++++-------
+ multipath/multipath.rules |    8 ++++++++
+ 4 files changed, 38 insertions(+), 8 deletions(-)
+
+Index: multipath-tools/libmultipath/finder.c
+===================================================================
+--- multipath-tools.orig/libmultipath/finder.c
++++ multipath-tools/libmultipath/finder.c
+@@ -78,7 +78,7 @@ write_out_wwid(int fd, char *wwid) {
+ 	return 1;
+ }
+ 
+-static int
++int
+ check_wwids_file(char *wwid, int write_wwid)
+ {
+ 	int scan_fd, fd, can_write, found, ret;
+Index: multipath-tools/libmultipath/finder.h
+===================================================================
+--- multipath-tools.orig/libmultipath/finder.h
++++ multipath-tools/libmultipath/finder.h
+@@ -14,5 +14,6 @@
+ 
+ int should_multipath(struct path *pp, vector pathvec);
+ int remember_wwid(char *wwid);
++int check_wwids_file(char *wwid, int write_wwid);
+ 
+ #endif /* _FINDER_H */
+Index: multipath-tools/multipath/main.c
+===================================================================
+--- multipath-tools.orig/multipath/main.c
++++ multipath-tools/multipath/main.c
+@@ -51,6 +51,7 @@
+ #include <errno.h>
+ #include <sys/time.h>
+ #include <sys/resource.h>
++#include <finder.h>
+ 
+ int logsink;
+ 
+@@ -79,7 +80,7 @@ usage (char * progname)
+ {
+ 	fprintf (stderr, VERSION_STRING);
+ 	fprintf (stderr, "Usage:\n");
+-	fprintf (stderr, "  %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [dev]\n", progname);
++	fprintf (stderr, "  %s [-c] [-d] [-r] [-v lvl] [-p pol] [-b fil] [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 -h\n", progname);
+@@ -91,6 +92,7 @@ usage (char * progname)
+ 		"  -ll     show multipath topology (maximum info)\n" \
+ 		"  -f      flush a multipath device map\n" \
+ 		"  -F      flush all multipath device maps\n" \
++		"  -c      check if a device should be a path in a multipath device\n" \
+ 		"  -d      dry run, do not create or update devmaps\n" \
+ 		"  -r      force devmap reload\n" \
+ 		"  -p      policy failover|multibus|group_by_serial|group_by_prio\n" \
+@@ -249,10 +251,11 @@ configure (void)
+ 	/*
+ 	 * if we have a blacklisted device parameter, exit early
+ 	 */
+-	if (dev && 
+-	    (filter_devnode(conf->blist_devnode, conf->elist_devnode, dev) > 0))
+-			goto out;
+-	
++	if (dev && (filter_devnode(conf->blist_devnode, conf->elist_devnode, dev) > 0)) {
++		if (conf->dry_run == 2)
++			printf("%s is not a valid multipath device path\n", conf->dev);
++		goto out;
++	}
+ 	/*
+ 	 * scope limiting must be translated into a wwid
+ 	 * failing the translation is fatal (by policy)
+@@ -268,6 +271,15 @@ configure (void)
+ 		if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
+ 				refwwid) > 0)
+ 			goto out;
++		if (conf->dry_run == 2) {
++			if (check_wwids_file(refwwid, 0) == 0){
++				printf("%s is a valid multipath device path\n", conf->dev);
++				r = 0;
++			}
++			else
++				printf("%s is not a valid multipath device path\n", conf->dev);
++			goto out;
++		}
+ 	}
+ 
+ 	/*
+@@ -350,7 +362,7 @@ main (int argc, char *argv[])
+ 		condlog(0, "multipath tools need sysfs mounted");
+ 		exit(1);
+ 	}
+-	while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:r")) != EOF ) {
++	while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:r")) != EOF ) {
+ 		switch(arg) {
+ 		case 1: printf("optarg : %s\n",optarg);
+ 			break;
+@@ -364,8 +376,12 @@ main (int argc, char *argv[])
+ 		case 'b':
+ 			conf->bindings_file = optarg;
+ 			break;
++		case 'c':
++			conf->dry_run = 2;
++			break;
+ 		case 'd':
+-			conf->dry_run = 1;
++			if (!conf->dry_run)
++				conf->dry_run = 1;
+ 			break;
+ 		case 'f':
+ 			conf->remove = FLUSH_ONE;
+@@ -438,6 +454,11 @@ main (int argc, char *argv[])
+ 
+ 	dm_init();
+ 
++	if (conf->dry_run == 2 &&
++	    (!conf->dev || conf->dev_type == DEV_DEVMAP)) {
++		condlog(0, "the -c option requires a path to check");
++		goto out;
++	}
+ 	if (conf->remove == FLUSH_ONE) {
+ 		if (conf->dev_type == DEV_DEVMAP)
+ 			r = dm_flush_map(conf->dev);
+Index: multipath-tools/multipath/multipath.rules
+===================================================================
+--- multipath-tools.orig/multipath/multipath.rules
++++ multipath-tools/multipath/multipath.rules
+@@ -1,6 +1,14 @@
+ # multipath wants the devmaps presented as meaninglful device names
+ # so name them after their devmap name
+ SUBSYSTEM!="block", GOTO="end_mpath"
++TEST!="/sbin/multipath", GOTO="check_usr"
++ENV{MPATH_GOT_HERE}="$env{DEVNAME}"
++PROGRAM=="/sbin/multipath -c /dev/$env{DEVNAME}", ENV{DM_MULTIPATH_DEVICE_PATH}="1"
++GOTO="skip_usr"
++LABEL="check_usr"
++ENV{MPATH_GOT_HERE} = "2"
++PROGRAM=="/usr/sbin/multipath -c /dev/$env{DEVNAME}", ENV{DM_MULTIPATH_DEVICE_PATH}="1"
++LABEL="skip_usr"
+ RUN+="socket:/org/kernel/dm/multipath_event"
+ KERNEL!="dm-*", GOTO="end_mpath"
+ ACTION!="change", GOTO="end_mpath"
diff --git a/0031-RHBZ-570546-display-avg-pg-prio.patch b/0031-RHBZ-570546-display-avg-pg-prio.patch
new file mode 100644
index 0000000..4643ad5
--- /dev/null
+++ b/0031-RHBZ-570546-display-avg-pg-prio.patch
@@ -0,0 +1,23 @@
+diff --git a/libmultipath/print.c b/libmultipath/print.c
+index 10e5ce5..9753fe2 100644
+--- a/libmultipath/print.c
++++ b/libmultipath/print.c
+@@ -378,6 +378,7 @@ snprint_pg_selector (char * buff, size_t len, struct pathgroup * pgp)
+ static int
+ snprint_pg_pri (char * buff, size_t len, struct pathgroup * pgp)
+ {
++	int avg_priority = 0;
+ 	/*
+ 	 * path group priority is not updated for every path prio change,
+ 	 * but only on switch group code path.
+@@ -385,7 +386,9 @@ snprint_pg_pri (char * buff, size_t len, struct pathgroup * pgp)
+ 	 * Printing is another reason to update.
+ 	 */
+ 	path_group_prio_update(pgp);
+-	return snprint_int(buff, len, pgp->priority);
++	if (pgp->enabled_paths)
++		avg_priority = pgp->priority / pgp->enabled_paths;
++	return snprint_int(buff, len, avg_priority);
+ }
+ 
+ static int
diff --git a/0032-RHBZ-575767-ontap_prio.patch b/0032-RHBZ-575767-ontap_prio.patch
new file mode 100644
index 0000000..d06f042
--- /dev/null
+++ b/0032-RHBZ-575767-ontap_prio.patch
@@ -0,0 +1,617 @@
+---
+ libmultipath/hwtable.c             |    4 
+ libmultipath/prio.h                |    2 
+ libmultipath/prioritizers/Makefile |    2 
+ libmultipath/prioritizers/netapp.c |  243 ------------------------------------
+ libmultipath/prioritizers/netapp.h |    7 -
+ libmultipath/prioritizers/ontap.c  |  245 +++++++++++++++++++++++++++++++++++++
+ libmultipath/prioritizers/ontap.h  |    7 +
+ multipath.conf.defaults            |    4 
+ multipath/multipath.conf.5         |    2 
+ 9 files changed, 259 insertions(+), 257 deletions(-)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -769,7 +769,7 @@ static struct hwentry default_hw[] = {
+ 		.no_path_retry = NO_PATH_RETRY_UNDEF,
+ 		.minio         = 128,
+ 		.checker_name  = DIRECTIO,
+-		.prio_name     = PRIO_NETAPP,
++		.prio_name     = PRIO_ONTAP,
+ 	},
+ 	/*
+ 	 * IBM NSeries (NETAPP) controller family
+@@ -790,7 +790,7 @@ static struct hwentry default_hw[] = {
+ 		.no_path_retry = NO_PATH_RETRY_UNDEF,
+ 		.minio         = 128,
+ 		.checker_name  = DIRECTIO,
+-		.prio_name     = PRIO_NETAPP,
++		.prio_name     = PRIO_ONTAP,
+ 	},
+ 	/*
+ 	 * Pillar Data controller family
+Index: multipath-tools/libmultipath/prio.h
+===================================================================
+--- multipath-tools.orig/libmultipath/prio.h
++++ multipath-tools/libmultipath/prio.h
+@@ -21,7 +21,7 @@
+ #define PRIO_EMC "emc"
+ #define PRIO_HDS "hds"
+ #define PRIO_HP_SW "hp_sw"
+-#define PRIO_NETAPP "netapp"
++#define PRIO_ONTAP "ontap"
+ #define PRIO_RANDOM "random"
+ #define PRIO_RDAC "rdac"
+ #define PRIO_WEIGHTED "weighted"
+Index: multipath-tools/libmultipath/prioritizers/Makefile
+===================================================================
+--- multipath-tools.orig/libmultipath/prioritizers/Makefile
++++ multipath-tools/libmultipath/prioritizers/Makefile
+@@ -12,7 +12,7 @@ LIBS = \
+ 	libpriordac.so \
+ 	libprioalua.so \
+ 	libpriotpg_pref.so \
+-	libprionetapp.so \
++	libprioontap.so \
+ 	libpriohds.so \
+ 	libprioweighted.so \
+ 
+Index: multipath-tools/libmultipath/prioritizers/netapp.c
+===================================================================
+--- multipath-tools.orig/libmultipath/prioritizers/netapp.c
++++ /dev/null
+@@ -1,243 +0,0 @@
+-/* 
+- * Copyright 2005 Network Appliance, Inc., All Rights Reserved
+- * Author:  David Wysochanski available at davidw at netapp.com
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of 
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License v2 for more details.
+- */
+-
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <sys/ioctl.h>
+-#include <errno.h>
+-#include <assert.h>
+-
+-#include <sg_include.h>
+-#include <debug.h>
+-#include <prio.h>
+-
+-#define INQUIRY_CMD	0x12
+-#define INQUIRY_CMDLEN	6
+-#define DEFAULT_PRIOVAL	10
+-#define RESULTS_MAX	256
+-#define SG_TIMEOUT	30000
+-
+-#define pp_netapp_log(prio, fmt, args...) \
+-        condlog(prio, "%s: netapp prio: " fmt, dev, ##args)
+-
+-static void dump_cdb(unsigned char *cdb, int size)
+-{
+-	int i;
+-	char buf[10*5+1];
+-	char * p = &buf[0];
+-	
+-	condlog(0, "- SCSI CDB: ");
+-	for (i=0; i<size; i++) {
+-		p += snprintf(p, 10*(size-i), "0x%02x ", cdb[i]);
+-	}
+-	condlog(0, "%s", buf);
+-}
+-
+-static void process_sg_error(struct sg_io_hdr *io_hdr)
+-{
+-	int i;
+-	char buf[128*5+1];
+-	char * p = &buf[0];
+-	
+-	condlog(0, "- masked_status=0x%02x, host_status=0x%02x, "
+-		"driver_status=0x%02x", io_hdr->masked_status,
+-		io_hdr->host_status, io_hdr->driver_status);
+-	if (io_hdr->sb_len_wr > 0) {
+-		condlog(0, "- SCSI sense data: ");
+-		for (i=0; i<io_hdr->sb_len_wr; i++) {
+-			p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ",
+-				      io_hdr->sbp[i]);
+-		}
+-		condlog(0, "%s", buf);
+-	}
+-}
+-
+-/*
+- * Returns:
+- * -1: error, errno set
+- *  0: success
+- */
+-static int send_gva(const char *dev, int fd, unsigned char pg,
+-		    unsigned char *results, int *results_size)
+-{
+-	unsigned char sb[128];
+-	unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa,
+-				 pg, sizeof(sb), 0, 0};
+-	struct sg_io_hdr io_hdr;
+-	int ret = -1;
+-
+-	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
+-	io_hdr.interface_id = 'S';
+-	io_hdr.cmd_len = sizeof (cdb);
+-	io_hdr.mx_sb_len = sizeof (sb);
+-	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+-	io_hdr.dxfer_len = *results_size;
+-	io_hdr.dxferp = results;
+-	io_hdr.cmdp = cdb;
+-	io_hdr.sbp = sb;
+-	io_hdr.timeout = SG_TIMEOUT;
+-	io_hdr.pack_id = 0;
+-	if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+-		pp_netapp_log(0, "SG_IO ioctl failed, errno=%d", errno);
+-		dump_cdb(cdb, sizeof(cdb));
+-		goto out;
+-	}
+-	if (io_hdr.info & SG_INFO_OK_MASK) {
+-		pp_netapp_log(0, "SCSI error");
+-		dump_cdb(cdb, sizeof(cdb));
+-		process_sg_error(&io_hdr);
+-		goto out;
+-	}
+-
+-	if (results[4] != 0x0a || results[5] != 0x98 ||
+-	    results[6] != 0x0a ||results[7] != 0x01) {
+-		dump_cdb(cdb, sizeof(cdb));
+-		pp_netapp_log(0, "GVA return wrong format ");
+-		pp_netapp_log(0, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x",
+-			results[4], results[5], results[6], results[7]);
+-		goto out;
+-	}
+-	ret = 0;
+- out:
+-	return(ret);
+-}
+-
+-/*
+- * Retuns:
+- * -1: Unable to obtain proxy info
+- *  0: Device _not_ proxy path
+- *  1: Device _is_ proxy path
+- */
+-static int get_proxy(const char *dev, int fd)
+-{
+-	unsigned char results[256];
+-	unsigned char sb[128];
+-	unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0,
+-						   sizeof(sb), 0};
+-	struct sg_io_hdr io_hdr;
+-	int ret = -1;
+-
+-	memset(&results, 0, sizeof (results));
+-	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
+-	io_hdr.interface_id = 'S';
+-	io_hdr.cmd_len = sizeof (cdb);
+-	io_hdr.mx_sb_len = sizeof (sb);
+-	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+-	io_hdr.dxfer_len = sizeof (results);
+-	io_hdr.dxferp = results;
+-	io_hdr.cmdp = cdb;
+-	io_hdr.sbp = sb;
+-	io_hdr.timeout = SG_TIMEOUT;
+-	io_hdr.pack_id = 0;
+-	if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+-		pp_netapp_log(0, "ioctl sending inquiry command failed, "
+-			"errno=%d", errno);
+-		dump_cdb(cdb, sizeof(cdb));
+-		goto out;
+-	}
+-	if (io_hdr.info & SG_INFO_OK_MASK) {
+-		pp_netapp_log(0, "SCSI error");
+-		dump_cdb(cdb, sizeof(cdb));
+-		process_sg_error(&io_hdr);
+-		goto out;
+-	}
+-
+-	if (results[1] != 0xc1 || results[8] != 0x0a ||
+-	    results[9] != 0x98 || results[10] != 0x0a ||
+-	    results[11] != 0x0 || results[12] != 0xc1 ||
+-	    results[13] != 0x0) {
+-		pp_netapp_log(0,"proxy info page in unknown format - ");
+-		pp_netapp_log(0,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x "
+-			"0x%02x 0x%02x",
+-			results[8], results[9], results[10],
+-			results[11], results[12], results[13]);
+-		dump_cdb(cdb, sizeof(cdb));
+-		goto out;
+-	}
+-	ret = (results[19] & 0x02) >> 1;
+-
+- out:
+-	return(ret);
+-}
+-
+-/*
+- * Returns priority of device based on device info.
+- *
+- * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol
+- * 3: iSCSI HBA
+- * 2: iSCSI software
+- * 1: FCP proxy
+- */
+-static int netapp_prio(const char *dev, int fd)
+-{
+-	unsigned char results[RESULTS_MAX];
+-	int results_size=RESULTS_MAX;
+-	int rc;
+-	int is_proxy;
+-	int is_iscsi_software;
+-	int is_iscsi_hardware;
+-	int tot_len;
+-
+-	is_iscsi_software = is_iscsi_hardware = is_proxy = 0;
+-
+-	memset(&results, 0, sizeof (results));
+-	rc = send_gva(dev, fd, 0x41, results, &results_size);
+-	if (rc == 0) {
+-		tot_len = results[0] << 24 | results[1] << 16 |
+-			  results[2] << 8 | results[3];
+-		if (tot_len <= 8) {
+-			goto try_fcp_proxy;
+-		}
+-		if (results[8] != 0x41) {
+-			pp_netapp_log(0, "GVA page 0x41 error - "
+-				"results[8] = 0x%x", results[8]);
+-			goto try_fcp_proxy;
+-		}
+-		if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) ||
+-		    (strncmp((char *)&results[12], "iswt", 4) == 0)) {
+-			is_iscsi_software = 1;
+-			goto prio_select;
+-		}
+-		else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) {
+-			is_iscsi_hardware = 1;
+-			goto prio_select;
+-		}
+-	}
+-	
+- try_fcp_proxy:	
+-	rc = get_proxy(dev, fd);
+-	if (rc >= 0) {
+-		is_proxy = rc;
+-	}
+-
+- prio_select:
+-	if (is_iscsi_hardware) {
+-		return 3;
+-	} else if (is_iscsi_software) {
+-		return 2;
+-	} else {
+-		if (is_proxy) {
+-			return 1;
+-		} else {
+-			/* Either non-proxy, or couldn't get proxy info */
+-			return 4;
+-		}
+-	}
+-}
+-
+-int getprio (struct path * pp)
+-{
+-	return netapp_prio(pp->dev, pp->fd);
+-}
+Index: multipath-tools/libmultipath/prioritizers/netapp.h
+===================================================================
+--- multipath-tools.orig/libmultipath/prioritizers/netapp.h
++++ /dev/null
+@@ -1,7 +0,0 @@
+-#ifndef _NETAPP_H
+-#define _NETAPP_H
+-
+-#define PRIO_NETAPP "netapp"
+-int prio_netapp(struct path * pp);
+-
+-#endif
+Index: multipath-tools/libmultipath/prioritizers/ontap.c
+===================================================================
+--- /dev/null
++++ multipath-tools/libmultipath/prioritizers/ontap.c
+@@ -0,0 +1,245 @@
++/*
++ * Copyright 2005 Network Appliance, Inc., All Rights Reserved
++ * Author:  David Wysochanski available at davidw at netapp.com
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License v2 for more details.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/ioctl.h>
++#include <errno.h>
++#include <assert.h>
++
++#include <sg_include.h>
++#include <debug.h>
++#include <prio.h>
++
++#define INQUIRY_CMD	0x12
++#define INQUIRY_CMDLEN	6
++#define DEFAULT_PRIOVAL	10
++#define RESULTS_MAX	256
++#define SG_TIMEOUT	60000
++
++#define pp_ontap_log(prio, fmt, args...) \
++        condlog(prio, "%s: ontap prio: " fmt, dev, ##args)
++
++static void dump_cdb(unsigned char *cdb, int size)
++{
++	int i;
++	char buf[10*5+1];
++	char * p = &buf[0];
++
++	condlog(0, "- SCSI CDB: ");
++	for (i=0; i<size; i++) {
++		p += snprintf(p, 10*(size-i), "0x%02x ", cdb[i]);
++	}
++	condlog(0, "%s", buf);
++}
++
++static void process_sg_error(struct sg_io_hdr *io_hdr)
++{
++	int i;
++	char buf[128*5+1];
++	char * p = &buf[0];
++
++	condlog(0, "- masked_status=0x%02x, host_status=0x%02x, "
++		"driver_status=0x%02x", io_hdr->masked_status,
++		io_hdr->host_status, io_hdr->driver_status);
++	if (io_hdr->sb_len_wr > 0) {
++		condlog(0, "- SCSI sense data: ");
++		for (i=0; i<io_hdr->sb_len_wr; i++) {
++			p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ",
++				      io_hdr->sbp[i]);
++		}
++		condlog(0, "%s", buf);
++	}
++}
++
++/*
++ * Returns:
++ * -1: error, errno set
++ *  0: success
++ */
++static int send_gva(const char *dev, int fd, unsigned char pg,
++		    unsigned char *results, int *results_size)
++{
++	unsigned char sb[128];
++	unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa,
++				 pg, sizeof(sb), 0, 0};
++	struct sg_io_hdr io_hdr;
++	int ret = -1;
++
++	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
++	io_hdr.interface_id = 'S';
++	io_hdr.cmd_len = sizeof (cdb);
++	io_hdr.mx_sb_len = sizeof (sb);
++	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
++	io_hdr.dxfer_len = *results_size;
++	io_hdr.dxferp = results;
++	io_hdr.cmdp = cdb;
++	io_hdr.sbp = sb;
++	io_hdr.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);
++		dump_cdb(cdb, sizeof(cdb));
++		goto out;
++	}
++	if (io_hdr.info & SG_INFO_OK_MASK) {
++		pp_ontap_log(0, "SCSI error");
++		dump_cdb(cdb, sizeof(cdb));
++		process_sg_error(&io_hdr);
++		goto out;
++	}
++
++	if (results[4] != 0x0a || results[5] != 0x98 ||
++	    results[6] != 0x0a ||results[7] != 0x01) {
++		dump_cdb(cdb, sizeof(cdb));
++		pp_ontap_log(0, "GVA return wrong format ");
++		pp_ontap_log(0, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x",
++			results[4], results[5], results[6], results[7]);
++		goto out;
++	}
++	ret = 0;
++ out:
++	return(ret);
++}
++
++/*
++ * Retuns:
++ * -1: Unable to obtain proxy info
++ *  0: Device _not_ proxy path
++ *  1: Device _is_ proxy path
++ */
++static int get_proxy(const char *dev, int fd)
++{
++	unsigned char results[256];
++	unsigned char sb[128];
++	unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0,
++						   sizeof(sb), 0};
++	struct sg_io_hdr io_hdr;
++	int ret = -1;
++
++	memset(&results, 0, sizeof (results));
++	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
++	io_hdr.interface_id = 'S';
++	io_hdr.cmd_len = sizeof (cdb);
++	io_hdr.mx_sb_len = sizeof (sb);
++	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
++	io_hdr.dxfer_len = sizeof (results);
++	io_hdr.dxferp = results;
++	io_hdr.cmdp = cdb;
++	io_hdr.sbp = sb;
++	io_hdr.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, "
++			"errno=%d", errno);
++		dump_cdb(cdb, sizeof(cdb));
++		goto out;
++	}
++	if (io_hdr.info & SG_INFO_OK_MASK) {
++		pp_ontap_log(0, "SCSI error");
++		dump_cdb(cdb, sizeof(cdb));
++		process_sg_error(&io_hdr);
++		goto out;
++	}
++
++	if (results[1] != 0xc1 || results[8] != 0x0a ||
++	    results[9] != 0x98 || results[10] != 0x0a ||
++	    results[11] != 0x0 || results[12] != 0xc1 ||
++	    results[13] != 0x0) {
++		pp_ontap_log(0,"proxy info page in unknown format - ");
++		pp_ontap_log(0,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x "
++			"0x%02x 0x%02x",
++			results[8], results[9], results[10],
++			results[11], results[12], results[13]);
++		dump_cdb(cdb, sizeof(cdb));
++		goto out;
++	}
++	ret = (results[19] & 0x02) >> 1;
++
++ out:
++	return(ret);
++}
++
++/*
++ * Returns priority of device based on device info.
++ *
++ * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol
++ * 3: iSCSI HBA
++ * 2: iSCSI software
++ * 1: FCP proxy
++ */
++static int ontap_prio(const char *dev, int fd)
++{
++	unsigned char results[RESULTS_MAX];
++	int results_size=RESULTS_MAX;
++	int rc;
++	int is_proxy;
++	int is_iscsi_software;
++	int is_iscsi_hardware;
++	int tot_len;
++
++	is_iscsi_software = is_iscsi_hardware = is_proxy = 0;
++
++	memset(&results, 0, sizeof (results));
++	rc = send_gva(dev, fd, 0x41, results, &results_size);
++	if (rc >= 0) {
++		tot_len = results[0] << 24 | results[1] << 16 |
++			  results[2] << 8 | results[3];
++		if (tot_len <= 8) {
++			goto try_fcp_proxy;
++		}
++		if (results[8] != 0x41) {
++			pp_ontap_log(0, "GVA page 0x41 error - "
++				"results[8] = 0x%x", results[8]);
++			goto try_fcp_proxy;
++		}
++		if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) ||
++		    (strncmp((char *)&results[12], "iswt", 4) == 0)) {
++			is_iscsi_software = 1;
++			goto prio_select;
++		}
++		else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) {
++			is_iscsi_hardware = 1;
++			goto prio_select;
++		}
++	} else {
++		return 0;
++	}
++
++ try_fcp_proxy:
++	rc = get_proxy(dev, fd);
++	if (rc >= 0) {
++		is_proxy = rc;
++	}
++
++ prio_select:
++	if (is_iscsi_hardware) {
++		return 3;
++	} else if (is_iscsi_software) {
++		return 2;
++	} else {
++		if (is_proxy) {
++			return 1;
++		} else {
++			/* Either non-proxy, or couldn't get proxy info */
++			return 4;
++		}
++	}
++}
++
++int getprio (struct path * pp)
++{
++	return ontap_prio(pp->dev, pp->fd);
++}
+Index: multipath-tools/libmultipath/prioritizers/ontap.h
+===================================================================
+--- /dev/null
++++ multipath-tools/libmultipath/prioritizers/ontap.h
+@@ -0,0 +1,7 @@
++#ifndef _ONTAP_H
++#define _ONTAP_H
++
++#define PRIO_ONTAP "ontap"
++int prio_ontap(struct path * pp);
++
++#endif
+Index: multipath-tools/multipath.conf.defaults
+===================================================================
+--- multipath-tools.orig/multipath.conf.defaults
++++ multipath-tools/multipath.conf.defaults
+@@ -444,7 +444,7 @@
+ #		rr_weight		uniform
+ #		rr_min_io		128
+ #		path_checker		directio
+-#		prio			netapp
++#		prio			ontap
+ #	}
+ #	device {
+ #		vendor			"IBM"
+@@ -458,7 +458,7 @@
+ #		rr_weight		uniform
+ #		rr_min_io		128
+ #		path_checker		directio
+-#		prio			netapp
++#		prio			ontap
+ #	}
+ #	device {
+ #		vendor			"Pillar"
+Index: multipath-tools/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools.orig/multipath/multipath.conf.5
++++ multipath-tools/multipath/multipath.conf.5
+@@ -149,7 +149,7 @@ Generate the path priority for EMC array
+ .B mpath_prio_alua /dev/%n
+ Generate the path priority based on the SCSI-3 ALUA settings.
+ .TP
+-.B mpath_prio_netapp /dev/%n
++.B mpath_prio_ontap /dev/%n
+ Generate the path priority for NetApp arrays.
+ .TP
+ .B mpath_prio_rdac /dev/%n
diff --git a/0033-RHBZ-573715-eurologic-config.patch b/0033-RHBZ-573715-eurologic-config.patch
new file mode 100644
index 0000000..fc6b65d
--- /dev/null
+++ b/0033-RHBZ-573715-eurologic-config.patch
@@ -0,0 +1,53 @@
+---
+ libmultipath/hwtable.c  |   15 +++++++++++++++
+ multipath.conf.defaults |   13 +++++++++++++
+ 2 files changed, 28 insertions(+)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -990,6 +990,21 @@ static struct hwentry default_hw[] = {
+ 		.checker_name  = RDAC,
+ 		.prio_name     = PRIO_RDAC,
+ 	},
++	{
++		.vendor        = "EUROLOGC",
++		.product       = "FC2502",
++		.getuid        ="/lib/udev/scsi_id --page=0x80 --whitelisted --device=/dev/%n",
++		.features      = DEFAULT_FEATURES,
++		.hwhandler     = DEFAULT_HWHANDLER,
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = GROUP_BY_PRIO,
++		.pgfailback    = FAILBACK_UNDEF,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = NO_PATH_RETRY_UNDEF,
++		.minio         = DEFAULT_MINIO,
++		.checker_name  = DEFAULT_CHECKER,
++		.prio_name     = DEFAULT_PRIO,
++	},
+ 	/*
+ 	 * EOL
+ 	 */
+Index: multipath-tools/multipath.conf.defaults
+===================================================================
+--- multipath-tools.orig/multipath.conf.defaults
++++ multipath-tools/multipath.conf.defaults
+@@ -602,4 +602,17 @@
+ #		path_checker		rdac
+ #		prio			rdac
+ #	}
++#	device {
++#		vendor			"EUROLOGC"
++#		product			"FC2502"
++#		getuid_callout		"/lib/udev/scsi_id --page=0x80 --whitelisted --device=/dev/%n"
++#		features                "0"
++#		hardware_handler        "0"
++#		path_selector           "round-robin 0"
++#		path_grouping_policy    group_by_prio
++#		rr_weight               uniform
++#		rr_min_io               1000
++#		path_checker		directio
++#		prio			const
++#	}
+ #}
diff --git a/0034-RHBZ-579575-add-q-multipath-option.patch b/0034-RHBZ-579575-add-q-multipath-option.patch
new file mode 100644
index 0000000..7d85678
--- /dev/null
+++ b/0034-RHBZ-579575-add-q-multipath-option.patch
@@ -0,0 +1,135 @@
+---
+ libmultipath/config.h    |    1 +
+ libmultipath/configure.c |    6 +++++-
+ libmultipath/file.c      |   32 ++++++++++++++++++++++++++++++++
+ libmultipath/file.h      |    1 +
+ multipath/main.c         |    8 ++++++--
+ 5 files changed, 45 insertions(+), 3 deletions(-)
+
+Index: multipath-tools/libmultipath/config.h
+===================================================================
+--- multipath-tools.orig/libmultipath/config.h
++++ multipath-tools/libmultipath/config.h
+@@ -87,6 +87,7 @@ struct config {
+ 	int fast_io_fail;
+ 	unsigned int dev_loss;
+ 	int find_multipaths;
++	int allow_queueing;
+ 	uid_t uid;
+ 	gid_t gid;
+ 	mode_t mode;
+Index: multipath-tools/libmultipath/configure.c
+===================================================================
+--- multipath-tools.orig/libmultipath/configure.c
++++ multipath-tools/libmultipath/configure.c
+@@ -36,6 +36,7 @@
+ #include "prio.h"
+ #include "util.h"
+ #include "finder.h"
++#include "file.h"
+ 
+ extern int
+ setup_map (struct multipath * mpp)
+@@ -567,7 +568,10 @@ coalesce_paths (struct vectors * vecs, v
+ 		if (r == DOMAP_DRY)
+ 			continue;
+ 
+-		if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
++		if (!conf->daemon && !conf->allow_queueing &&
++		    !pidfile_check(DEFAULT_PIDFILE))
++			dm_queue_if_no_path(mpp->alias, 0);
++		else if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF) {
+ 			if (mpp->no_path_retry == NO_PATH_RETRY_FAIL)
+ 				dm_queue_if_no_path(mpp->alias, 0);
+ 			else
+Index: multipath-tools/multipath/main.c
+===================================================================
+--- multipath-tools.orig/multipath/main.c
++++ multipath-tools/multipath/main.c
+@@ -80,7 +80,7 @@ usage (char * progname)
+ {
+ 	fprintf (stderr, VERSION_STRING);
+ 	fprintf (stderr, "Usage:\n");
+-	fprintf (stderr, "  %s [-c] [-d] [-r] [-v lvl] [-p pol] [-b fil] [dev]\n", progname);
++	fprintf (stderr, "  %s [-c] [-d] [-r] [-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 -h\n", progname);
+@@ -93,6 +93,7 @@ usage (char * progname)
+ 		"  -f      flush a multipath device map\n" \
+ 		"  -F      flush all multipath device maps\n" \
+ 		"  -c      check if a device should be a path in a multipath device\n" \
++		"  -q      allow queue_if_no_path when multipathd is not running\n"\
+ 		"  -d      dry run, do not create or update devmaps\n" \
+ 		"  -r      force devmap reload\n" \
+ 		"  -p      policy failover|multibus|group_by_serial|group_by_prio\n" \
+@@ -362,7 +363,7 @@ main (int argc, char *argv[])
+ 		condlog(0, "multipath tools need sysfs mounted");
+ 		exit(1);
+ 	}
+-	while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:r")) != EOF ) {
++	while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:rq")) != EOF ) {
+ 		switch(arg) {
+ 		case 1: printf("optarg : %s\n",optarg);
+ 			break;
+@@ -379,6 +380,9 @@ main (int argc, char *argv[])
+ 		case 'c':
+ 			conf->dry_run = 2;
+ 			break;
++		case 'q':
++			conf->allow_queueing = 1;
++			break;
+ 		case 'd':
+ 			if (!conf->dry_run)
+ 				conf->dry_run = 1;
+Index: multipath-tools/libmultipath/file.c
+===================================================================
+--- multipath-tools.orig/libmultipath/file.c
++++ multipath-tools/libmultipath/file.c
+@@ -176,3 +176,35 @@ fail:
+ 	close(fd);
+ 	return -1;
+ }
++
++int pidfile_check(const char *file)
++{
++	int fd;
++	struct flock lock;
++
++	fd = open(file, O_RDONLY);
++	if (fd < 0) {
++		if (errno == ENOENT)
++			return 0;
++		condlog(0, "Cannot open pidfile, %s : %s", file,
++			strerror(errno));
++		return -1;
++	}
++	lock.l_type = F_WRLCK;
++	lock.l_start = 0;
++	lock.l_whence = SEEK_SET;
++	lock.l_len = 0;
++
++	if (fcntl(fd, F_GETLK, &lock) < 0) {
++		condlog(0, "Cannot check lock on pidfile, %s : %s", file,
++			strerror(errno));
++		return -1;
++	}
++	close(fd);
++	if (lock.l_type == F_UNLCK)
++		return 0;
++	return 1;
++}
++
++
++
+Index: multipath-tools/libmultipath/file.h
+===================================================================
+--- multipath-tools.orig/libmultipath/file.h
++++ multipath-tools/libmultipath/file.h
+@@ -7,5 +7,6 @@
+ 
+ #define FILE_TIMEOUT 30
+ int open_file(char *file, int *can_write, char *header);
++int pidfile_check(const char *file);
+ 
+ #endif /* _FILE_H */
diff --git a/0035-RHBZ-467709-add-followover.patch b/0035-RHBZ-467709-add-followover.patch
new file mode 100644
index 0000000..0d79c3a
--- /dev/null
+++ b/0035-RHBZ-467709-add-followover.patch
@@ -0,0 +1,141 @@
+---
+ libmultipath/dict.c    |   12 ++++++++++++
+ libmultipath/print.c   |    2 ++
+ libmultipath/structs.h |    3 ++-
+ multipathd/main.c      |   31 +++++++++++++++++++++++++++++--
+ 4 files changed, 45 insertions(+), 3 deletions(-)
+
+Index: multipath-tools/libmultipath/dict.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dict.c
++++ multipath-tools/libmultipath/dict.c
+@@ -348,6 +348,8 @@ default_failback_handler(vector strvec)
+ 		conf->pgfailback = -FAILBACK_MANUAL;
+ 	else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
+ 		conf->pgfailback = -FAILBACK_IMMEDIATE;
++	else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
++		conf->pgfailback = -FAILBACK_FOLLOWOVER;
+ 	else
+ 		conf->pgfailback = atoi(buff);
+ 
+@@ -917,6 +919,8 @@ hw_failback_handler(vector strvec)
+ 		hwe->pgfailback = -FAILBACK_MANUAL;
+ 	else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
+ 		hwe->pgfailback = -FAILBACK_IMMEDIATE;
++	else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
++		hwe->pgfailback = -FAILBACK_FOLLOWOVER;
+ 	else
+ 		hwe->pgfailback = atoi(buff);
+ 
+@@ -1169,6 +1173,8 @@ mp_failback_handler(vector strvec)
+ 		mpe->pgfailback = -FAILBACK_MANUAL;
+ 	else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
+ 		mpe->pgfailback = -FAILBACK_IMMEDIATE;
++	else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
++		mpe->pgfailback = -FAILBACK_FOLLOWOVER;
+ 	else
+ 		mpe->pgfailback = atoi(buff);
+ 
+@@ -1472,6 +1478,8 @@ snprint_mp_failback (char * buff, int le
+ 		return snprintf(buff, len, "manual");
+ 	case -FAILBACK_IMMEDIATE:
+ 		return snprintf(buff, len, "immediate");
++	case -FAILBACK_FOLLOWOVER:
++		return snprintf(buff, len, "followover");
+ 	default:
+ 		return snprintf(buff, len, "%i", mpe->pgfailback);
+ 	}
+@@ -1748,6 +1756,8 @@ snprint_hw_failback (char * buff, int le
+ 		return snprintf(buff, len, "manual");
+ 	case -FAILBACK_IMMEDIATE:
+ 		return snprintf(buff, len, "immediate");
++	case -FAILBACK_FOLLOWOVER:
++		return snprintf(buff, len, "followover");
+ 	default:
+ 		return snprintf(buff, len, "%i", hwe->pgfailback);
+ 	}
+@@ -1970,6 +1980,8 @@ snprint_def_failback (char * buff, int l
+ 		return snprintf(buff, len, "manual");
+ 	case -FAILBACK_IMMEDIATE:
+ 		return snprintf(buff, len, "immediate");
++	case -FAILBACK_FOLLOWOVER:
++		return snprintf(buff, len, "followover");
+ 	default:
+ 		return snprintf(buff, len, "%i", pgfailback);
+ 	}
+Index: multipath-tools/libmultipath/print.c
+===================================================================
+--- multipath-tools.orig/libmultipath/print.c
++++ multipath-tools/libmultipath/print.c
+@@ -142,6 +142,8 @@ snprint_failback (char * buff, size_t le
+ {
+ 	if (mpp->pgfailback == -FAILBACK_IMMEDIATE)
+ 		return snprintf(buff, len, "immediate");
++	if (mpp->pgfailback == -FAILBACK_FOLLOWOVER)
++		return snprintf(buff, len, "followover");
+ 
+ 	if (!mpp->failback_tick)
+ 		return snprintf(buff, len, "-");
+Index: multipath-tools/libmultipath/structs.h
+===================================================================
+--- multipath-tools.orig/libmultipath/structs.h
++++ multipath-tools/libmultipath/structs.h
+@@ -39,7 +39,8 @@ enum rr_weight_mode {
+ enum failback_mode {
+ 	FAILBACK_UNDEF,
+ 	FAILBACK_MANUAL,
+-	FAILBACK_IMMEDIATE
++	FAILBACK_IMMEDIATE,
++	FAILBACK_FOLLOWOVER
+ };
+ 
+ enum sysfs_buses {
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -875,6 +875,32 @@ mpvec_garbage_collector (struct vectors 
+ 	}
+ }
+ 
++/* This is called after a path has started working again. It the multipath
++ * device for this path uses the followover failback type, and this is the
++ * best pathgroup, and this is the first path in the pathgroup to come back
++ * up, then switch to this pathgroup */
++static int
++followover_should_failback(struct path * pp)
++{
++	struct pathgroup * pgp;
++	struct path *pp1;
++	int i;
++
++	if (pp->mpp->pgfailback != -FAILBACK_FOLLOWOVER ||
++	    !pp->mpp->pg || !pp->pgindex ||
++	    pp->pgindex != pp->mpp->bestpg)
++		return 0;
++
++	pgp = VECTOR_SLOT(pp->mpp->pg, pp->pgindex - 1);
++	vector_foreach_slot(pgp->paths, pp1, i) {
++		if (pp1 == pp)
++			continue;
++		if (pp1->state != PATH_DOWN && pp1->state != PATH_SHAKY)
++			return 0;
++	}
++	return 1;
++}
++
+ static void
+ defered_failback_tick (vector mpvec)
+ {
+@@ -1013,8 +1039,9 @@ check_path (struct vectors * vecs, struc
+ 		if (pp->mpp->pgfailback > 0)
+ 			pp->mpp->failback_tick =
+ 				pp->mpp->pgfailback + 1;
+-		else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE &&
+-		    need_switch_pathgroup(pp->mpp, 1))
++		else if (need_switch_pathgroup(pp->mpp, 1) &&
++			 (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE ||
++			  followover_should_failback(pp)))
+ 			switch_pathgroup(pp->mpp);
+ 
+ 		/*
diff --git a/0036-RH-clear-messages.patch b/0036-RH-clear-messages.patch
new file mode 100644
index 0000000..fdae141
--- /dev/null
+++ b/0036-RH-clear-messages.patch
@@ -0,0 +1,46 @@
+---
+ libmultipath/checkers.c  |    5 +++++
+ libmultipath/checkers.h  |    1 +
+ libmultipath/discovery.c |    1 +
+ 3 files changed, 7 insertions(+)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -807,6 +807,7 @@ get_state (struct path * pp, int daemon)
+ 			return PATH_UNCHECKED;
+ 		}
+ 	}
++	checker_clear_message(c);
+ 	if (path_offline(pp)) {
+ 		condlog(3, "%s: path offline", pp->dev);
+ 		return PATH_DOWN;
+Index: multipath-tools/libmultipath/checkers.c
+===================================================================
+--- multipath-tools.orig/libmultipath/checkers.c
++++ multipath-tools/libmultipath/checkers.c
+@@ -183,6 +183,11 @@ char * checker_message (struct checker *
+ 	return c->message;
+ }
+ 
++void checker_clear_message (struct checker *c)
++{
++	c->message[0] = '\0';
++}
++
+ void checker_get (struct checker * dst, char * name)
+ {
+ 	struct checker * src = checker_lookup(name);
+Index: multipath-tools/libmultipath/checkers.h
+===================================================================
+--- multipath-tools.orig/libmultipath/checkers.h
++++ multipath-tools/libmultipath/checkers.h
+@@ -117,6 +117,7 @@ int checker_check (struct checker *);
+ int checker_selected (struct checker *);
+ char * checker_name (struct checker *);
+ char * checker_message (struct checker *);
++void checker_clear_message (struct checker *c);
+ void checker_get (struct checker *, char *);
+ 
+ #endif /* _CHECKERS_H */
diff --git a/0037-RH-adopt-paths.patch b/0037-RH-adopt-paths.patch
new file mode 100644
index 0000000..279487e
--- /dev/null
+++ b/0037-RH-adopt-paths.patch
@@ -0,0 +1,31 @@
+---
+ libmultipath/structs_vec.c |    2 +-
+ multipathd/main.c          |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -1178,7 +1178,7 @@ configure (struct vectors * vecs, int st
+ 	/*
+ 	 * create new set of maps & push changed ones into dm
+ 	 */
+-	if (coalesce_paths(vecs, mpvec, NULL, 0))
++	if (coalesce_paths(vecs, mpvec, NULL, 1))
+ 		return 1;
+ 
+ 	/*
+Index: multipath-tools/libmultipath/structs_vec.c
+===================================================================
+--- multipath-tools.orig/libmultipath/structs_vec.c
++++ multipath-tools/libmultipath/structs_vec.c
+@@ -355,7 +355,7 @@ retry:
+ 		goto out;
+ 	}
+ 
+-	//adopt_paths(vecs->pathvec, mpp);
++	adopt_paths(vecs->pathvec, mpp);
+ 	if (!mpp->hwe)
+ 		mpp->hwe = extract_hwe_from_path(mpp);
+ 	if (!mpp->hwe) {
diff --git a/0038-RHBZ-587201-IBM-SGI.patch b/0038-RHBZ-587201-IBM-SGI.patch
new file mode 100644
index 0000000..49f53a7
--- /dev/null
+++ b/0038-RHBZ-587201-IBM-SGI.patch
@@ -0,0 +1,61 @@
+---
+ libmultipath/hwtable.c |   34 ++++++++++++++++++++++++++++++++--
+ 1 file changed, 32 insertions(+), 2 deletions(-)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -455,6 +455,36 @@ static struct hwentry default_hw[] = {
+ 		.prio_name     = PRIO_RDAC,
+ 	},
+ 	{
++		.vendor        = "IBM",
++		.product       = "1745",
++		.getuid        = DEFAULT_GETUID,
++		.features      = "2 pg_init_retries 50",
++		.hwhandler     = "1 rdac",
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = GROUP_BY_PRIO,
++		.pgfailback    = -FAILBACK_IMMEDIATE,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = 15,
++		.minio         = DEFAULT_MINIO,
++		.checker_name  = RDAC,
++		.prio_name     = PRIO_RDAC,
++	},
++	{
++		.vendor        = "IBM",
++		.product       = "1746",
++		.getuid        = DEFAULT_GETUID,
++		.features      = "2 pg_init_retries 50",
++		.hwhandler     = "1 rdac",
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = GROUP_BY_PRIO,
++		.pgfailback    = -FAILBACK_IMMEDIATE,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = 15,
++		.minio         = DEFAULT_MINIO,
++		.checker_name  = RDAC,
++		.prio_name     = PRIO_RDAC,
++	},
++	{
+ 	    /* IBM DS4700 */
+ 		.vendor        = "IBM",
+ 		.product       = "1814",
+@@ -853,13 +883,13 @@ static struct hwentry default_hw[] = {
+ 		.vendor        = "SGI",
+ 		.product       = "IS.*",
+ 		.getuid        = DEFAULT_GETUID,
+-		.features      = DEFAULT_FEATURES,
++		.features      = "2 pg_init_retries 50",
+ 		.hwhandler     = "1 rdac",
+ 		.selector      = DEFAULT_SELECTOR,
+ 		.pgpolicy      = GROUP_BY_PRIO,
+ 		.pgfailback    = -FAILBACK_IMMEDIATE,
+ 		.rr_weight     = RR_WEIGHT_NONE,
+-		.no_path_retry = NO_PATH_RETRY_QUEUE,
++		.no_path_retry = 15,
+ 		.minio         = DEFAULT_MINIO,
+ 		.checker_name  = RDAC,
+ 		.prio_name     = PRIO_RDAC,
diff --git a/0039-RHBZ-589153-manpage-update.patch b/0039-RHBZ-589153-manpage-update.patch
new file mode 100644
index 0000000..93e63b2
--- /dev/null
+++ b/0039-RHBZ-589153-manpage-update.patch
@@ -0,0 +1,251 @@
+---
+ multipath/multipath.conf.5 |  148 +++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 122 insertions(+), 26 deletions(-)
+
+Index: multipath-tools/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools.orig/multipath/multipath.conf.5
++++ multipath-tools/multipath/multipath.conf.5
+@@ -76,6 +76,33 @@ default is
+ directory where udev creates its device nodes; default is
+ .I /dev
+ .TP
++.B multipath_dir
++directory where the dynamic shared objects are stored; default is system
++dependent, commonly
++.I /lib/multipath
++.TP
++.B find_multipaths
++If set to
++.I yes
++, instead of trying to create a multipath device for every non-blacklisted
++path, multipath will only create a device if one of three condidions are
++met.
++.I 1
++There are at least two non-blacklisted paths with the same wwid,
++.I 2
++the user manually forces the creation, by specifying a device with the multipath
++command, or
++.I 3
++a path has the same WWID as a multipath device that was previously created
++while find_multipaths was set (even if that multipath device doesn't currently
++exist).
++Whenever a multipath device is created with find_multipaths set, multipath will
++remeber the WWID of the device, so that it will automatically create the
++device again, as soon as it sees a path with that WWID. This should allow most
++users to have multipath automatically choose the correct paths to make into
++multipath devices, without having to edit the blacklist; Default is
++.I no
++.TP
+ .B verbosity
+ default verbosity. Higher values increase the verbosity level. Valid
+ levels are between 0 and 6; default is
+@@ -130,39 +157,38 @@ identifier. Should be specified with an 
+ is
+ .I /lib/udev/scsi_id --whitelisted --device=/dev/%n
+ .TP
+-.B prio_callout
+-The default program and args to callout to obtain a path priority
+-value. The specified program will be executed and should return a
+-numeric value specifying the relative priority of this path. Higher
+-number have a higher priority. A '%n' in the command line will be expanded
+-to the device name, a '%b' will be expanded to the device number in
+-.I major:minor
+-format.
+-.I "none"
+-is a valid value. Currently the following path priority programs are
+-implemented:
++.B prio
++The default method used to obtain a path priority value. Possible
++values are
+ .RS
+ .TP 12
+-.B mpath_prio_emc /dev/%n
++.B const
++Set a priority of one to all paths
++.TP
++.B emc
+ Generate the path priority for EMC arrays
+ .TP
+-.B mpath_prio_alua /dev/%n
++.B alua
+ Generate the path priority based on the SCSI-3 ALUA settings.
+ .TP
+-.B mpath_prio_ontap /dev/%n
++.B tpg_pref
++Generate the path prority based on the SCSI-3 ALUA settings, using
++the preferred port bit.
++.TP
++.B ontap
+ Generate the path priority for NetApp arrays.
+ .TP
+-.B mpath_prio_rdac /dev/%n
++.B rdac
+ Generate the path priority for LSI/Engenio RDAC controller.
+ .TP
+-.B mpath_prio_hp_sw /dev/%n
++.B hp_sw
+ Generate the path priority for Compaq/HP controller in
+ active/standby mode.
+ .TP
+-.B mpath_prio_hds_modular %b
++.B hds
+ Generate the path priority for Hitachi HDS Modular storage arrays.
+ .TP
+-Default value is \fBnone\fR.
++Default value is \fBconst\fR.
+ .RE
+ .TP
+ .B features
+@@ -203,13 +229,26 @@ Default value is \fIreadsector0\fR.
+ .RE
+ .TP
+ .B failback
+-Tell the daemon to manage path group failback, or not to. 0 or
+-.I immediate
+-means immediate failback, values >0 means deferred failback (in
+-seconds).
+-.I manual
+-means no failback. Default value is
+-.I manual
++Tell multipathd how to manage path group failback.
++.RS
++.TP 12
++.B immediate
++Immediately failback to the highest priority pathgroup that contains
++active paths.
++.TP
++.B manual
++Do not perform automatic failback.
++.TP
++.B followover
++Only perform automatic failback when the first path of a pathgroup
++becomes active. This keeps a node from automatically failing back when
++another node requested the failover.
++.TP
++.B values > 0
++deferred failback (time to defer in seconds)
++.TP
++Default value is \fImanual\fR.
++.RE
+ .TP
+ .B  rr_min_io
+ The number of IO to route to a path before switching to the next in
+@@ -245,6 +284,20 @@ be overriden by any specific aliases in 
+ Default is
+ .I no
+ .TP
++.B queue_without_daemon
++If set to
++.I no
++, multipathd will disable queueing for all devices when it is shut down.
++Default is
++.I yes
++.TP
++.B flush_on_last_del
++If set to
++.I yes
++, multipathd will disable queueing when the last path to a device has been
++deleted. Default is
++.I no
++.TP
+ .B max_fds
+ Specify the maximum number of file descriptors that can be opened by multipath
+ and multipathd.  This is equivalent to ulimit -n. A value of \fImax\fR will set
+@@ -253,6 +306,11 @@ maximum number of open fds is taken from
+ 1024. To be safe, this should be set to the maximum number of paths plus 32,
+ 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
++explict timeout, in seconds; default taken from
++.I /sys/block/sd<x>/device/timeout
++.TP
+ .B fast_io_fail_tmo
+ Specify the number of seconds the scsi layer will wait after a problem has been
+ detected on a FC remote port before failing IO to devices on that remote port.
+@@ -263,6 +321,18 @@ will disable the timeout.
+ .B dev_loss_tmo
+ Specify the number of seconds the scsi layer will wait after a problem has
+ been detected on a FC remote port before removing it from the system.
++.TP
++.B mode
++The mode to use for the multipath device nodes, in octal; default determined
++by the process
++.TP
++.B uid
++The user id to use for the multipath device nodes. You may use either the
++numeric or symbolic uid; default determined by the process.
++.TP
++.B gid
++The group id to use for the mutipath device nodes. You may use either the
++numeric or symbolic gid; default determined by the process.
+ .
+ .SH "blacklist section"
+ The
+@@ -345,9 +415,21 @@ section:
+ .TP
+ .B failback
+ .TP
++.B prio
++.TP
+ .B no_path_retry
+ .TP
+ .B rr_min_io
++.TP
++.B rr_weight
++.TP
++.B flush_on_last_del
++.TP
++.B mode
++.TP
++.B uid
++.TP
++.B gid
+ .RE
+ .PD
+ .LP
+@@ -368,6 +450,9 @@ subsection recognizes the following attr
+ .B product
+ (Mandatory) Product identifier
+ .TP
++.B revision
++Revision identifier
++.TP
+ .B product_blacklist
+ Product strings to blacklist for this vendor
+ .TP
+@@ -378,6 +463,15 @@ The following hardware handler are imple
+ .TP 12
+ .B 1 emc
+ Hardware handler for EMC storage arrays.
++.TP
++.B 1 alua
++Hardware handler for SCSI-3 ALUA arrays.
++.TP
++.B 1 hp_sw
++Hardware handler for Compaq/HP controllers.
++.TP
++.B 1 rdac
++Hardware handler for the LSI/Engenio RDAC controllers.
+ .RE
+ .LP
+ The following attributes are optional; if not set the default values
+@@ -398,7 +492,7 @@ section:
+ .TP
+ .B features
+ .TP
+-.B prio_callout
++.B prio
+ .TP
+ .B failback
+ .TP
+@@ -411,6 +505,8 @@ section:
+ .B fast_io_fail_tmo
+ .TP
+ .B dev_loss_tmo
++.TP
++.B flush_on_last_del
+ .RE
+ .PD
+ .LP
diff --git a/0040-RHBZ-587695-add-checker-msg-alias.patch b/0040-RHBZ-587695-add-checker-msg-alias.patch
new file mode 100644
index 0000000..42544c0
--- /dev/null
+++ b/0040-RHBZ-587695-add-checker-msg-alias.patch
@@ -0,0 +1,17 @@
+---
+ multipathd/main.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -63,7 +63,7 @@
+ #define CMDSIZE 160
+ 
+ #define LOG_MSG(a,b) \
+-	if (strlen(b)) condlog(a, "%s: %s", pp->dev, b);
++	if (strlen(b)) condlog(a, "%s: %s - %s", pp->mpp->alias, pp->dev, b);
+ 
+ pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER;
+ pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
diff --git a/0041-RHBZ-587695-add-rdac-message.patch b/0041-RHBZ-587695-add-rdac-message.patch
new file mode 100644
index 0000000..880dee0
--- /dev/null
+++ b/0041-RHBZ-587695-add-rdac-message.patch
@@ -0,0 +1,54 @@
+---
+ libmultipath/checkers/rdac.c |   32 ++++++++++++++++++++------------
+ 1 file changed, 20 insertions(+), 12 deletions(-)
+
+Index: multipath-tools/libmultipath/checkers/rdac.c
+===================================================================
+--- multipath-tools.orig/libmultipath/checkers/rdac.c
++++ multipath-tools/libmultipath/checkers/rdac.c
+@@ -101,25 +101,33 @@ extern int
+ libcheck_check (struct checker * c)
+ {
+ 	struct volume_access_inq inq;
++	int ret;
+ 
+ 	memset(&inq, 0, sizeof(struct volume_access_inq));
+ 	if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq),
+ 			c->timeout)) {
+-		MSG(c, MSG_RDAC_DOWN);
+-		return PATH_DOWN;
+-	} else {
+-		if ((inq.PQ_PDT & 0x20) || (inq.PQ_PDT & 0x7f)) {
+-			/* LUN not connected*/
+-			return PATH_DOWN;
+-		}
++		ret = PATH_DOWN;
++		goto done;
++	} else if ((inq.PQ_PDT & 0x20) || (inq.PQ_PDT & 0x7f)) {
++		/* LUN not connected*/
++		ret = PATH_DOWN;
++		goto done;
+ 	}
+ 
+-	if (inq.avtcvp & 0x1) {
++	ret = ((inq.avtcvp & 0x1) ? PATH_UP : PATH_GHOST);
++
++done:
++	switch (ret) {
++	case PATH_DOWN:
++		MSG(c, MSG_RDAC_DOWN);
++		break;
++	case PATH_UP:
+ 		MSG(c, MSG_RDAC_UP);
+-		return PATH_UP;
+-	}
+-	else {
++		break;
++	case PATH_GHOST:
+ 		MSG(c, MSG_RDAC_GHOST);
+-		return PATH_GHOST;
++		break;
+ 	}
++
++	return ret;
+ }
diff --git a/0042-RHBZ-590038-fix-fast-io-fail-tmo.patch b/0042-RHBZ-590038-fix-fast-io-fail-tmo.patch
new file mode 100644
index 0000000..f3ea001
--- /dev/null
+++ b/0042-RHBZ-590038-fix-fast-io-fail-tmo.patch
@@ -0,0 +1,17 @@
+---
+ libmultipath/discovery.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -258,7 +258,7 @@ sysfs_set_scsi_tmo (struct multipath *mp
+ 				sprintf(value, "off");
+ 			else
+ 				snprintf(value, 11, "%u", mpp->fast_io_fail);
+-			if (sysfs_attr_set_value(attr_path, "fast_io_fail",
++			if (sysfs_attr_set_value(attr_path, "fast_io_fail_tmo",
+ 						 value))
+ 				return 1;
+ 		}
diff --git a/0043-RHBZ-590028-close-sysfs_attr_fd.patch b/0043-RHBZ-590028-close-sysfs_attr_fd.patch
new file mode 100644
index 0000000..890436f
--- /dev/null
+++ b/0043-RHBZ-590028-close-sysfs_attr_fd.patch
@@ -0,0 +1,16 @@
+---
+ libmultipath/sysfs.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+Index: multipath-tools/libmultipath/sysfs.c
+===================================================================
+--- multipath-tools.orig/libmultipath/sysfs.c
++++ multipath-tools/libmultipath/sysfs.c
+@@ -407,6 +407,7 @@ sysfs_attr_set_value(const char *devpath
+ 		    path_full, ret);
+ 		ret = -1;
+ 	}
++	close(fd);
+ out:
+ 	return ret;
+ }
diff --git a/0044-RHBZ-591940-dont-clear-daemon.patch b/0044-RHBZ-591940-dont-clear-daemon.patch
new file mode 100644
index 0000000..761e38a
--- /dev/null
+++ b/0044-RHBZ-591940-dont-clear-daemon.patch
@@ -0,0 +1,16 @@
+---
+ multipathd/main.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -1242,6 +1242,7 @@ reconfigure (struct vectors * vecs)
+ 		conf->checkint = DEFAULT_CHECKINT;
+ 		conf->max_checkint = MAX_CHECKINT(conf->checkint);
+ 	}
++	conf->daemon = 1;
+ 	configure(vecs, 1);
+ 	free_config(old);
+ 	return 0;
diff --git a/0045-RHBZ-593379-dont-add-unknown-paths.patch b/0045-RHBZ-593379-dont-add-unknown-paths.patch
new file mode 100644
index 0000000..629f315
--- /dev/null
+++ b/0045-RHBZ-593379-dont-add-unknown-paths.patch
@@ -0,0 +1,25 @@
+---
+ libmultipath/dmparser.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/dmparser.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dmparser.c
++++ multipath-tools/libmultipath/dmparser.c
+@@ -13,6 +13,7 @@
+ #include "structs.h"
+ #include "util.h"
+ #include "debug.h"
++#include "config.h"
+ 
+ #define WORD_SIZE 64
+ 
+@@ -286,7 +287,7 @@ disassemble_map (vector pathvec, char * 
+ 				strncpy(pp->dev_t, word, BLK_DEV_SIZE);
+ 
+ 				/* Only call this in multipath client mode */
+-				if (!mpp->waiter && store_path(pathvec, pp))
++				if (!conf->daemon && store_path(pathvec, pp))
+ 					goto out1;
+ 			}
+ 			FREE(word);
diff --git a/0046-RHBZ-593426-move-adopt-path.patch b/0046-RHBZ-593426-move-adopt-path.patch
new file mode 100644
index 0000000..5a3c7b6
--- /dev/null
+++ b/0046-RHBZ-593426-move-adopt-path.patch
@@ -0,0 +1,24 @@
+---
+ libmultipath/structs_vec.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/structs_vec.c
+===================================================================
+--- multipath-tools.orig/libmultipath/structs_vec.c
++++ multipath-tools/libmultipath/structs_vec.c
+@@ -355,7 +355,6 @@ retry:
+ 		goto out;
+ 	}
+ 
+-	adopt_paths(vecs->pathvec, mpp);
+ 	if (!mpp->hwe)
+ 		mpp->hwe = extract_hwe_from_path(mpp);
+ 	if (!mpp->hwe) {
+@@ -498,6 +497,7 @@ int update_multipath (struct vectors *ve
+ 	if (setup_multipath(vecs, mpp))
+ 		return 1; /* mpp freed in setup_multipath */
+ 
++	adopt_paths(vecs->pathvec, mpp);
+ 	/*
+ 	 * compare checkers states with DM states
+ 	 */
diff --git a/0047-RHBZ-591608-only-switch-pgs-once.patch b/0047-RHBZ-591608-only-switch-pgs-once.patch
new file mode 100644
index 0000000..001226a
--- /dev/null
+++ b/0047-RHBZ-591608-only-switch-pgs-once.patch
@@ -0,0 +1,52 @@
+---
+ multipathd/main.c |   20 ++++++--------------
+ 1 file changed, 6 insertions(+), 14 deletions(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -965,6 +965,7 @@ check_path (struct vectors * vecs, struc
+ {
+ 	int newstate;
+ 	int oldpriority;
++	int new_path_up = 0;
+ 
+ 	if (!pp->mpp)
+ 		return;
+@@ -1033,16 +1034,7 @@ check_path (struct vectors * vecs, struc
+ 		else
+ 			reinstate_path(pp, 0);
+ 
+-		/*
+-		 * schedule [defered] failback
+-		 */
+-		if (pp->mpp->pgfailback > 0)
+-			pp->mpp->failback_tick =
+-				pp->mpp->pgfailback + 1;
+-		else if (need_switch_pathgroup(pp->mpp, 1) &&
+-			 (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE ||
+-			  followover_should_failback(pp)))
+-			switch_pathgroup(pp->mpp);
++		new_path_up = 1;
+ 
+ 		/*
+ 		 * if at least one path is up in a group, and
+@@ -1080,13 +1072,13 @@ check_path (struct vectors * vecs, struc
+ 	if (pp->priority != oldpriority &&
+ 	    pp->mpp->pgpolicyfn == (pgpolicyfn *)group_by_prio)
+ 		update_path_groups(pp->mpp, vecs);
+-	else if (need_switch_pathgroup(pp->mpp, 0)) {
++	else if (need_switch_pathgroup(pp->mpp, new_path_up)) {
+ 		if (pp->mpp->pgfailback > 0 &&
+-		    pp->mpp->failback_tick <= 0)
++		    (new_path_up || pp->mpp->failback_tick <= 0))
+ 			pp->mpp->failback_tick =
+ 				pp->mpp->pgfailback + 1;
+-		else if (pp->mpp->pgfailback ==
+-				-FAILBACK_IMMEDIATE)
++		else if (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE ||
++			 (new_path_up && followover_should_failback(pp)))
+ 			switch_pathgroup(pp->mpp);
+ 	}
+ }
diff --git a/0048-RHBZ-592494-fix-user-configs.patch b/0048-RHBZ-592494-fix-user-configs.patch
new file mode 100644
index 0000000..1f89d1f
--- /dev/null
+++ b/0048-RHBZ-592494-fix-user-configs.patch
@@ -0,0 +1,114 @@
+---
+ libmultipath/config.c |   50 +++++++++++++++++++++++---------------------------
+ 1 file changed, 23 insertions(+), 27 deletions(-)
+
+Index: multipath-tools/libmultipath/config.c
+===================================================================
+--- multipath-tools.orig/libmultipath/config.c
++++ multipath-tools/libmultipath/config.c
+@@ -24,33 +24,30 @@
+ static int
+ hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2)
+ {
+-	if (hwe1->vendor && hwe2->vendor && strcmp(hwe1->vendor, hwe2->vendor))
++	if (hwe1->vendor) {
++		if (!hwe2->vendor || strcmp(hwe1->vendor, hwe2->vendor))
++			return 1;
++	}
++	else if (hwe2->vendor)
+ 		return 1;
+ 
+-	if (hwe1->product && hwe2->product && strcmp(hwe1->product, hwe2->product))
++	if (hwe1->product) {
++		if (!hwe2->product || strcmp(hwe1->product, hwe2->product))
++			return 1;
++	}
++	else if (hwe2->product)
+ 		return 1;
+ 
+-	if (hwe1->revision && hwe2->revision && strcmp(hwe1->revision, hwe2->revision))
++	if (hwe1->revision) {
++ 		if (!hwe2->revision || strcmp(hwe1->revision, hwe2->revision))
++			return 1;
++	}
++	else if (hwe2->revision)
+ 		return 1;
+ 
+ 	return 0;
+ }
+ 
+-static struct hwentry *
+-find_hwe_strmatch (vector hwtable, struct hwentry *hwe)
+-{
+-	int i;
+-	struct hwentry *tmp, *ret = NULL;
+-
+-	vector_foreach_slot (hwtable, tmp, i) {
+-		if (hwe_strmatch(tmp, hwe))
+-			continue;
+-		ret = tmp;
+-		break;
+-	}
+-	return ret;
+-}
+-
+ struct hwentry *
+ find_hwe (vector hwtable, char * vendor, char * product, char * revision)
+ {
+@@ -264,15 +261,13 @@ set_param_str(char * str)
+ }
+ 
+ #define merge_str(s) \
+-	if (hwe2->s) { \
+-		if (hwe1->s) \
+-			FREE(hwe1->s); \
++	if (!hwe1->s && hwe2->s) { \
+ 		if (!(hwe1->s = set_param_str(hwe2->s))) \
+ 			return 1; \
+ 	}
+ 
+ #define merge_num(s) \
+-	if (hwe2->s) \
++	if (!hwe1->s && hwe2->s) \
+ 		hwe1->s = hwe2->s
+ 
+ 
+@@ -295,6 +290,10 @@ merge_hwe (struct hwentry * hwe1, struct
+ 	merge_num(rr_weight);
+ 	merge_num(no_path_retry);
+ 	merge_num(minio);
++	merge_num(pg_timeout);
++	merge_num(flush_on_last_del);
++	merge_num(fast_io_fail);
++	merge_num(dev_loss);
+ 
+ 	return 0;
+ }
+@@ -304,9 +303,6 @@ store_hwe (vector hwtable, struct hwentr
+ {
+ 	struct hwentry * hwe;
+ 
+-	if (find_hwe_strmatch(hwtable, dhwe))
+-		return 0;
+-
+ 	if (!(hwe = alloc_hwe()))
+ 		return 1;
+ 
+@@ -463,8 +459,6 @@ load_config (char * file)
+ 		if (!conf->hwtable)
+ 			goto out;
+ 	}
+-	if (setup_default_hwtable(conf->hwtable))
+-		goto out;
+ 
+ 	/*
+ 	 * read the config file
+@@ -494,6 +488,8 @@ load_config (char * file)
+ 			goto out;
+ 		}
+ 	}
++	if (setup_default_hwtable(conf->hwtable))
++		goto out;
+ 	/*
+ 	 * remove duplica in hwtable. config file takes precedence
+ 	 * over build-in hwtable
diff --git a/0049-RHBZ-591644-enhance-mpathconf.patch b/0049-RHBZ-591644-enhance-mpathconf.patch
new file mode 100644
index 0000000..e028456
--- /dev/null
+++ b/0049-RHBZ-591644-enhance-mpathconf.patch
@@ -0,0 +1,228 @@
+---
+ multipath/main.c    |    4 -
+ multipath/mpathconf |  123 ++++++++++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 121 insertions(+), 6 deletions(-)
+
+Index: multipath-tools/multipath/mpathconf
+===================================================================
+--- multipath-tools.orig/multipath/mpathconf
++++ multipath-tools/multipath/mpathconf
+@@ -27,10 +27,13 @@ function usage
+ 	echo "usage: $0 <command>"
+ 	echo ""
+ 	echo "Commands:"
+-	echo "Enable: --enable [--user_friendly_names <y|n>] [--find_multipaths <y|n>"
++	echo "Enable: --enable "
+ 	echo "Disable: --disable"
+-	echo "Set user_friendly_names: --user_friendly_names <y|n>"
+-	echo "Set find_multipaths: --find_multipaths <y|n>"
++	echo "Set user_friendly_names (Default n): --user_friendly_names <y|n>"
++	echo "Set find_multipaths (Default n): --find_multipaths <y|n>"
++	echo "Load the dm-multipath modules on enable (Default y): --with_module <y|n>"
++	echo "start/stop/reload multipathd (Default n): --with_multipathd <y|n>"
++	echo "chkconfig on/off multipathd (Default y): --with_chkconfig <y|n>"
+ 	echo ""
+ }
+ 
+@@ -64,6 +67,33 @@ function parse_args
+ 					exit 1
+ 				fi
+ 				;;
++			--with_module)
++				if [ -n "$2" ]; then
++					MODULE=$2
++					shift 2
++				else
++					usage
++					exit 1
++				fi
++				;;
++			--with_multipathd)
++				if [ -n "$2" ]; then
++					MULTIPATHD=$2
++					shift 2
++				else
++					usage
++					exit 1
++				fi
++				;;
++			--with_chkconfig)
++				if [ -n "$2" ]; then
++					CHKCONFIG=$2
++					shift 2
++				else
++					usage
++					exit 1
++				fi
++				;;
+ 			*)
+ 				usage
+ 				exit
+@@ -73,10 +103,11 @@ function parse_args
+ 
+ function validate_args
+ {
+-	if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" ]; then
++	if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$MODULE" ]; then
+ 		echo "ignoring extra parameters on disable"
+ 		FRIENDLY=""
+ 		FIND=""
++		MODULE=""
+ 	fi
+ 	if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then
+ 		echo "--user_friendly_names must be either 'y' or 'n'"
+@@ -89,6 +120,18 @@ function validate_args
+ 	if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" ]; then
+ 		DISPLAY=1
+ 	fi
++	if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
++		echo "--with_module must be either 'y' or 'n'"
++		exit 1
++	fi
++	if [ -n "$MULTIPATHD" ] && [ "$MULTIPATHD" != "y" -a "$MULTIPATHD" != "n" ]; then
++		echo "--with_multipathd must be either 'y' or 'n'"
++		exit 1
++	fi
++	if [ -n "$CHKCONFIG" ] && [ "$CHKCONFIG" != "y" -a "$CHKCONFIG" != "n" ]; then
++		echo "--with_chkconfig must be either 'y' or 'n'"
++		exit 1
++	fi
+ }
+ 
+ umask 0077
+@@ -119,6 +162,34 @@ if grep -q "^defaults[[:space:]]*{" $TMP
+ 	HAVE_DEFAULTS=1
+ fi
+ 
++if [ -z "$MODULE" -o "$MODULE" = "y" ]; then
++	if lsmod | grep -q "dm_multipath" ; then
++		HAVE_MODULE=1
++	else
++		HAVE_MODULE=0
++	fi
++fi
++
++if [ "$MULTIPATHD" = "y" ]; then
++	if service multipathd status > /dev/null ; then
++		HAVE_MULTIPATHD=1
++	else
++		HAVE_MULTIPATHD=0
++	fi
++fi
++
++if [ -z "$CHKCONFIG" -o "$CHKCONFIG" = "y" ]; then
++	chkconfig --list multipathd > /dev/null 2>&1
++	if [ $? != 0 ]; then
++		chkconfig --add multipathd
++	fi
++	if chkconfig --list multipathd | grep -q "on" ; then
++		HAVE_CHKCONFIG=1
++	else
++		HAVE_CHKCONFIG=0
++	fi
++fi
++
+ if [ "$HAVE_BLACKLIST" = "1" ]; then
+ 	if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then
+ 		HAVE_DISABLE=1
+@@ -156,6 +227,23 @@ if [ -n "$DISPLAY" ]; then
+ 	else
+ 		echo "user_friendly_names is enabled"
+ 	fi
++	if [ -n "$HAVE_MODULE" ]; then
++		if [ "$HAVE_MODULE" = 1 ]; then
++			echo "dm_multipath module is loaded"
++		else
++			echo "dm_multipath module is not loaded"
++		fi
++	fi
++	if [ -n "$HAVE_MULTIPATHD" ]; then
++		service multipathd status
++	fi
++	if [ -n "$HAVE_CHKCONFIG" ]; then
++		if [ "$HAVE_CHKCONFIG" = 1 ]; then
++			echo "multipathd is chkconfiged on"
++		else
++			echo "multipathd is chkconfiged off"
++		fi
++	fi
+ 	exit 0
+ fi
+ 
+@@ -192,28 +280,34 @@ fi
+ if [ "$FIND" = "n" ]; then
+ 	if [ "$HAVE_FIND" = 1 ]; then
+ 		sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/	find_multipaths no/' $TMPFILE
++		CHANGED_CONFIG=1
+ 	fi
+ elif [ "$FIND" = "y" ]; then
+ 	if [ -z "$HAVE_FIND" ]; then
+ 		sed -i '/^defaults[[:space:]]*{/ a\
+ 	find_multipaths yes
+ ' $TMPFILE
++		CHANGED_CONFIG=1
+ 	elif [ "$HAVE_FIND" = 0 ]; then
+ 		sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/	find_multipaths yes/' $TMPFILE
++		CHANGED_CONFIG=1
+ 	fi
+ fi
+ 
+ if [ "$FRIENDLY" = "n" ]; then
+ 	if [ "$HAVE_FRIENDLY" = 1 ]; then
+ 		sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/	user_friendly_names no/' $TMPFILE
++		CHANGED_CONFIG=1
+ 	fi
+ elif [ "$FRIENDLY" = "y" ]; then
+ 	if [ -z "$HAVE_FRIENDLY" ]; then
+ 		sed -i '/^defaults[[:space:]]*{/ a\
+ 	user_friendly_names yes
+ ' $TMPFILE
++		CHANGED_CONFIG=1
+ 	elif [ "$HAVE_FRIENDLY" = 0 ]; then
+ 		sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/	user_friendly_names yes/' $TMPFILE
++		CHANGED_CONFIG=1
+ 	fi
+ fi
+ 
+@@ -232,3 +326,24 @@ if [ $? != 0 ]; then
+ fi
+ 
+ rm -f $TMPFILE
++
++if [ "$ENABLE" = 1 ]; then
++	if [ "$HAVE_MODULE" = 0 ]; then
++		modprobe dm_multipath
++	fi
++	if [ "$HAVE_MULTIPATHD" = 0 ]; then
++		service multipathd start
++	fi
++	if [ "$HAVE_CHKCONFIG" = 0 ]; then
++		chkconfig multipathd on
++	fi
++elif [ "$ENABLE" = 0 ]; then
++	if [ "$HAVE_MULTIPATHD" = 1 ]; then
++		service multipathd stop
++	fi
++	if [ "$HAVE_CHKCONFIG" = 1 ]; then
++		chkconfig multipathd off
++	fi
++elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then
++	service multipathd reload
++fi
+Index: multipath-tools/multipath/main.c
+===================================================================
+--- multipath-tools.orig/multipath/main.c
++++ multipath-tools/multipath/main.c
+@@ -345,10 +345,10 @@ main (int argc, char *argv[])
+ 		exit(1);
+ 	}
+ 
+-	if (dm_prereq())
++	if (load_config(DEFAULT_CONFIGFILE))
+ 		exit(1);
+ 
+-	if (load_config(DEFAULT_CONFIGFILE))
++	if (dm_prereq())
+ 		exit(1);
+ 
+ 	if (init_checkers()) {
diff --git a/0050-RHBZ-595400-fix-checker-tmo.patch b/0050-RHBZ-595400-fix-checker-tmo.patch
new file mode 100644
index 0000000..d0c7308
--- /dev/null
+++ b/0050-RHBZ-595400-fix-checker-tmo.patch
@@ -0,0 +1,17 @@
+---
+ libmultipath/discovery.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -174,7 +174,7 @@ sysfs_get_timeout(struct sysfs_device *d
+ 	if (safe_sprintf(attr_path, "%s/device", dev->devpath))
+ 		return 1;
+ 
+-	attr = sysfs_attr_get_value(dev->devpath, "timeout");
++	attr = sysfs_attr_get_value(attr_path, "timeout");
+ 	if (!attr)
+ 		return 1;
+ 
diff --git a/0051-RHBZ-596156-mpathconf-man-page.patch b/0051-RHBZ-596156-mpathconf-man-page.patch
new file mode 100644
index 0000000..a758035
--- /dev/null
+++ b/0051-RHBZ-596156-mpathconf-man-page.patch
@@ -0,0 +1,154 @@
+---
+ multipath/Makefile    |    3 +
+ multipath/mpathconf.8 |  116 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 119 insertions(+)
+
+Index: multipath-tools/multipath/mpathconf.8
+===================================================================
+--- /dev/null
++++ multipath-tools/multipath/mpathconf.8
+@@ -0,0 +1,116 @@
++.TH MPATHCONF 8 "June 2010" "" "Linux Administrator's Manual"
++.SH NAME
++mpathconf - A tool for configuring device-mapper-multipath
++.SH SYNOPSIS
++.B mpathconf
++.RB [\| commands \|]
++.RB [\| options \|]
++.SH DESCRIPTION
++.B mpathconf
++is a utility that creates or modifies
++.B /etc/multipath.conf.
++It can enable or disable multipathing and configure some common options.
++.B mpathconf
++can also load the
++.B dm_multipath
++module, start and stop the
++.B multipathd
++daemon, and configure the
++.B multipathd
++service to start automatically or not. If
++.B mpathconf
++is called with no commands, it will display the current configuration.
++
++The default options for mpathconf are
++.B --with_module
++and
++.B --with_chkconfig.
++The
++.B --with_multipathd
++option is not set by default.  Enabling multipathing will load the
++.B dm_multipath
++module and chkconfig
++.B multipathd
++to start on the next boot, but it will not immediately start it. This is so
++that users can manually edit their config file if necessary, before starting
++.B multipathd.
++
++If
++.B /etc/multipath.conf
++already exists, mpathconf will edit it. If it does not exist, mpathconf will
++use
++.B /usr/share/doc/device-mapper-multipath-0.4.9/multipath.conf
++as the starting file. This file has
++.B user_friendly_names
++set. If this file does not exist, mpathconf will create
++.B /etc/multipath.conf
++from scratch.  For most users, this means that
++.B user_friendly_names
++will be set by default, unless they use the
++.B --user_friendly_names n
++command.
++.SH COMMANDS
++.TP
++.B --enable
++Removes any line that blacklists all device nodes from the
++.B /etc/multipath.conf
++blacklist section.
++.TP
++.B --disable
++Adds a line that blacklists all device nodes to the
++.B /etc/multipath.conf
++blacklist section. If no blacklist section exists, it will create one.
++.TP
++.B --user_friendly_name \fP { \fBy\fP | \fBn\fP }
++If set to \fBy\fP, this adds the line
++.B user_friendly_names yes
++to the
++.B /etc/multipath.conf
++defaults section. If set to \fBn\fP, this removes the line, if present. This
++command can be used along with any other command.
++.TP
++.B --find_multipaths\fP { \fBy\fP | \fBn\fP }
++If set to \fBy\fP, this adds the line
++.B find_multipaths yes
++to the
++.B /etc/multipath.conf
++defaults section. If set to \fBn\fP, this removes the line, if present. This
++command can be used aldong with any other command.
++.SH OPTIONS
++.TP
++.B --with_module\fP { \fBy\fP | \fBn\fP }
++If set to \fBy\fP, this runs
++.B modprobe dm_multipath
++to install the multipath modules. This option only works with the
++.B --enable
++command. This option is set to \fBy\fP by default.
++.TP
++.B --with_multipathd { \fBy\fP | \fBn\fP }
++If set to \fBy\fP, this runs
++.B service multipathd start
++to start the multipathd daemon on \fB--enable\fP,
++.B service multipathd stop
++to start the multipathd daemon on \fB--disable\fP, and
++.B service multipathd reload
++to reconfigure multipathd on \fB--user_frindly_names\fP and
++\fB--find_multipaths\fP.
++This option is set to \fBn\fP by default.
++.TP
++.B --with_chkconfig { \fBy\fP | \fBn\fP }
++If set to \fBy\fP, this runs
++.B chkconfig multipathd on
++to set multipathd to start automatically on \fB--enable\fP and
++.B chkconfig multipathd off
++to stop multipathd for starting automatically on \fB--disable\fP.
++This option is set to \fBy\fP by default.
++.SH FILES
++.BR /etc/multipath.conf
++.SH "SEE ALSO"
++.BR multipath.conf (5),
++.BR chkconfig (8),
++.BR modprobe (8),
++.BR multipath (8),
++.BR multipathd (8),
++.BR service (8),
++.SH AUTHOR
++Benjamin Marzinski <bmarzins at redhat.com>
+Index: multipath-tools/multipath/Makefile
+===================================================================
+--- multipath-tools.orig/multipath/Makefile
++++ multipath-tools/multipath/Makefile
+@@ -17,6 +17,7 @@ $(EXEC): $(OBJS)
+ 	$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS)
+ 	$(GZIP) $(EXEC).8 > $(EXEC).8.gz
+ 	$(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
++	$(GZIP) mpathconf.8 > mpathconf.8.gz
+ 
+ install:
+ 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
+@@ -28,6 +29,7 @@ install:
+ 	$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
+ 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
+ 	$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
++	$(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(mandir)
+ 
+ uninstall:
+ 	rm $(DESTDIR)/lib/udev/rules.d/multipath.rules
+@@ -35,6 +37,7 @@ uninstall:
+ 	rm $(DESTDIR)$(bindir)/mpathconf
+ 	rm $(DESTDIR)$(mandir)/$(EXEC).8.gz
+ 	rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
++	rm $(DESTDIR)$(mandir)/mpathconf.8.gz
+ 
+ clean:
+ 	rm -f core *.o $(EXEC) *.gz
diff --git a/0052-RHBZ-601247-fix-path-adoption.patch b/0052-RHBZ-601247-fix-path-adoption.patch
new file mode 100644
index 0000000..12fe73d
--- /dev/null
+++ b/0052-RHBZ-601247-fix-path-adoption.patch
@@ -0,0 +1,115 @@
+---
+ libmultipath/structs_vec.c |   42 ++++++++++++++++++++++++++----------------
+ libmultipath/structs_vec.h |    2 +-
+ multipathd/main.c          |    2 +-
+ 3 files changed, 28 insertions(+), 18 deletions(-)
+
+Index: multipath-tools/libmultipath/structs_vec.c
+===================================================================
+--- multipath-tools.orig/libmultipath/structs_vec.c
++++ multipath-tools/libmultipath/structs_vec.c
+@@ -45,8 +45,15 @@ update_mpp_paths(struct multipath * mpp,
+ 	return 0;
+ }
+ 
++/* Getting the pathinfo for paths we already have seems like a hack.
++ * It's necessary since sometimes a multipath device we get from the
++ * kernel conatains paths that aren't in our pathvector.  In this case
++ * we need to add the paths just like any other, making sure
++ * that we only accept paths that are allowed by our configuration.
++ */
++
+ extern int
+-adopt_paths (vector pathvec, struct multipath * mpp)
++adopt_paths (vector pathvec, struct multipath * mpp, int verify_all)
+ {
+ 	int i;
+ 	struct path * pp;
+@@ -58,19 +65,22 @@ adopt_paths (vector pathvec, struct mult
+ 		return 1;
+ 
+ 	vector_foreach_slot (pathvec, pp, i) {
+-		if (!strncmp(mpp->wwid, pp->wwid, WWID_SIZE)) {
+-			condlog(3, "%s: ownership set to %s",
+-				pp->dev, mpp->alias);
+-			pp->mpp = mpp;
+-
+-			if (!mpp->paths && !(mpp->paths = vector_alloc()))
+-				return 1;
+-
+-			if (!find_path_by_dev(mpp->paths, pp->dev) &&
+-			    store_path(mpp->paths, pp))
+-					return 1;
+-			pathinfo(pp, conf->hwtable, DI_PRIO | DI_CHECKER);
++		if (strncmp(mpp->wwid, pp->wwid, WWID_SIZE))
++			continue;
++		condlog(3, "%s: ownership set to %s", pp->dev, mpp->alias);
++		pp->mpp = mpp;
++
++		if (!mpp->paths && !(mpp->paths = vector_alloc()))
++			return 1;
++
++		if (find_path_by_dev(mpp->paths, pp->dev)) {
++			if (!verify_all)
++				continue;
+ 		}
++		else if (store_path(mpp->paths, pp))
++			return 1;
++
++		pathinfo(pp, conf->hwtable, DI_PRIO | DI_CHECKER);
+ 	}
+ 	return 0;
+ }
+@@ -389,7 +399,7 @@ add_map_without_path (struct vectors * v
+ 		return NULL; /* mpp freed in setup_multipath */
+ 	}
+ 
+-	if (adopt_paths(vecs->pathvec, mpp))
++	if (adopt_paths(vecs->pathvec, mpp, 1))
+ 		goto out;
+ 
+ 	if (!vector_alloc_slot(vecs->mpvec))
+@@ -422,7 +432,7 @@ add_map_with_path (struct vectors * vecs
+ 	select_alias(mpp);
+ 	mpp->size = pp->size;
+ 
+-	if (adopt_paths(vecs->pathvec, mpp))
++	if (adopt_paths(vecs->pathvec, mpp, 1))
+ 		goto out;
+ 
+ 	if (add_vec) {
+@@ -497,7 +507,7 @@ int update_multipath (struct vectors *ve
+ 	if (setup_multipath(vecs, mpp))
+ 		return 1; /* mpp freed in setup_multipath */
+ 
+-	adopt_paths(vecs->pathvec, mpp);
++	adopt_paths(vecs->pathvec, mpp, 0);
+ 	/*
+ 	 * compare checkers states with DM states
+ 	 */
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -413,7 +413,7 @@ rescan:
+ 	if (mpp) {
+ 		condlog(4,"%s: adopting all paths for path %s",
+ 			mpp->alias, pp->dev);
+-		if (adopt_paths(vecs->pathvec, mpp))
++		if (adopt_paths(vecs->pathvec, mpp, 1))
+ 			goto fail; /* leave path added to pathvec */
+ 
+ 		verify_paths(mpp, vecs, NULL);
+Index: multipath-tools/libmultipath/structs_vec.h
+===================================================================
+--- multipath-tools.orig/libmultipath/structs_vec.h
++++ multipath-tools/libmultipath/structs_vec.h
+@@ -15,7 +15,7 @@ struct vectors {
+ 
+ void set_no_path_retry(struct multipath *mpp);
+ 
+-int adopt_paths (vector pathvec, struct multipath * mpp);
++int adopt_paths (vector pathvec, struct multipath * mpp, int verify_all);
+ void orphan_paths (vector pathvec, struct multipath * mpp);
+ void orphan_path (struct path * pp);
+ 
diff --git a/0053-RHBZ-596323-remember_more_wwids.patch b/0053-RHBZ-596323-remember_more_wwids.patch
new file mode 100644
index 0000000..ecf8952
--- /dev/null
+++ b/0053-RHBZ-596323-remember_more_wwids.patch
@@ -0,0 +1,16 @@
+---
+ multipath/main.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+Index: multipath-tools/multipath/main.c
+===================================================================
+--- multipath-tools.orig/multipath/main.c
++++ multipath-tools/multipath/main.c
+@@ -203,6 +203,7 @@ get_dm_mpvec (vector curmp, vector pathv
+ 
+ 		if (!conf->dry_run)
+ 			reinstate_paths(mpp);
++		remember_wwid(mpp->wwid);
+ 	}
+ 	return 0;
+ }
diff --git a/0054-RHBZ-596319-rules-cleanup.patch b/0054-RHBZ-596319-rules-cleanup.patch
new file mode 100644
index 0000000..adf45c1
--- /dev/null
+++ b/0054-RHBZ-596319-rules-cleanup.patch
@@ -0,0 +1,41 @@
+---
+ multipath/multipath.rules |   22 +++++++++++++---------
+ 1 file changed, 13 insertions(+), 9 deletions(-)
+
+Index: multipath-tools/multipath/multipath.rules
+===================================================================
+--- multipath-tools.orig/multipath/multipath.rules
++++ multipath-tools/multipath/multipath.rules
+@@ -1,19 +1,23 @@
+ # multipath wants the devmaps presented as meaninglful device names
+ # so name them after their devmap name
+ SUBSYSTEM!="block", GOTO="end_mpath"
+-TEST!="/sbin/multipath", GOTO="check_usr"
+-ENV{MPATH_GOT_HERE}="$env{DEVNAME}"
+-PROGRAM=="/sbin/multipath -c /dev/$env{DEVNAME}", ENV{DM_MULTIPATH_DEVICE_PATH}="1"
+-GOTO="skip_usr"
+-LABEL="check_usr"
+-ENV{MPATH_GOT_HERE} = "2"
+-PROGRAM=="/usr/sbin/multipath -c /dev/$env{DEVNAME}", ENV{DM_MULTIPATH_DEVICE_PATH}="1"
+-LABEL="skip_usr"
++
++ENV{MPATH_SBIN_PATH}="/sbin"
++TEST!="$env{MPATH_SBIN_PATH}/multipath", ENV{MPATH_SBIN_PATH}="/usr/sbin"
++
++ACTION=="add", ENV{DEVTYPE}!="partition", \
++	ENV{DM_MULTIPATH_DEVICE_PATH}!="1", \
++	PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -c $tempnode", \
++	ENV{DM_MULTIPATH_DEVICE_PATH}="1"
++
++ENV{DM_MULTIPATH_DEVICE_PATH}=="1", ENV{DEVTYPE}!="partition", \
++	RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}"
++
+ RUN+="socket:/org/kernel/dm/multipath_event"
+ KERNEL!="dm-*", GOTO="end_mpath"
+ ACTION!="change", GOTO="end_mpath"
+ ENV{DM_SUSPENDED}=="1", GOTO="end_mpath"
+ ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath"
+ ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath"
+-RUN+="$env{DM_SBIN_PATH}/kpartx -a -p p $tempnode"
++RUN+="$env{MPATH_SBIN_PATH}/kpartx -a -p p $tempnode"
+ LABEL="end_mpath"
diff --git a/0055-RHBZ-602257-update-on-show-topology.patch b/0055-RHBZ-602257-update-on-show-topology.patch
new file mode 100644
index 0000000..6fe45fb
--- /dev/null
+++ b/0055-RHBZ-602257-update-on-show-topology.patch
@@ -0,0 +1,142 @@
+---
+ libmultipath/structs_vec.c |   18 ++++++++++--------
+ libmultipath/structs_vec.h |    6 ++++--
+ libmultipath/waiter.c      |    2 +-
+ multipathd/cli_handlers.c  |   14 +++++++++++---
+ 4 files changed, 26 insertions(+), 14 deletions(-)
+
+Index: multipath-tools/multipathd/cli_handlers.c
+===================================================================
+--- multipath-tools.orig/multipathd/cli_handlers.c
++++ multipath-tools/multipathd/cli_handlers.c
+@@ -81,7 +81,8 @@ show_paths (char ** r, int * len, struct
+ }
+ 
+ int
+-show_map_topology (char ** r, int * len, struct multipath * mpp)
++show_map_topology (char ** r, int * len, struct multipath * mpp,
++		   struct vectors * vecs)
+ {
+ 	char * c;
+ 	char * reply;
+@@ -90,6 +91,8 @@ show_map_topology (char ** r, int * len,
+ 
+ 	reply = MALLOC(maxlen);
+ 
++	if (update_multipath(vecs, mpp->alias, 0))
++		return 1;
+ 	while (again) {
+ 		if (!reply)
+ 			return 1;
+@@ -127,9 +130,14 @@ show_maps_topology (char ** r, int * len
+ 
+ 		c = reply;
+ 
+-		vector_foreach_slot(vecs->mpvec, mpp, i)
++		vector_foreach_slot(vecs->mpvec, mpp, i) {
++			if (update_multipath(vecs, mpp->alias, 0)) {
++				i--;
++				continue;
++			}
+ 			c += snprint_multipath_topology(c, reply + maxlen - c,
+ 							mpp, 2);
++		}
+ 
+ 		again = ((c - reply) == (maxlen - 1));
+ 
+@@ -244,7 +252,7 @@ cli_list_map_topology (void * v, char **
+ 
+ 	condlog(3, "list multipath %s (operator)", param);
+ 
+-	return show_map_topology(reply, len, mpp);
++	return show_map_topology(reply, len, mpp, vecs);
+ }
+ 
+ int
+Index: multipath-tools/libmultipath/structs_vec.c
+===================================================================
+--- multipath-tools.orig/libmultipath/structs_vec.c
++++ multipath-tools/libmultipath/structs_vec.c
+@@ -325,7 +325,7 @@ set_no_path_retry(struct multipath *mpp)
+ }
+ 
+ extern int
+-setup_multipath (struct vectors * vecs, struct multipath * mpp)
++__setup_multipath (struct vectors * vecs, struct multipath * mpp, int reset)
+ {
+ retry:
+ 	if (dm_get_info(mpp->alias, &mpp->dmi)) {
+@@ -371,11 +371,13 @@ retry:
+ 		condlog(3, "%s: no hardware entry found, using defaults",
+ 			mpp->alias);
+ 	}
+-	select_rr_weight(mpp);
+-	select_pgfailback(mpp);
+-	set_no_path_retry(mpp);
+-	select_pg_timeout(mpp);
+-	select_flush_on_last_del(mpp);
++	if (reset) {
++		select_rr_weight(mpp);
++		select_pgfailback(mpp);
++		set_no_path_retry(mpp);
++		select_pg_timeout(mpp);
++		select_flush_on_last_del(mpp);
++	}
+ 
+ 	return 0;
+ out:
+@@ -487,7 +489,7 @@ verify_paths(struct multipath * mpp, str
+ 	return count;
+ }
+ 
+-int update_multipath (struct vectors *vecs, char *mapname)
++int update_multipath (struct vectors *vecs, char *mapname, int reset)
+ {
+ 	struct multipath *mpp;
+ 	struct pathgroup  *pgp;
+@@ -504,7 +506,7 @@ int update_multipath (struct vectors *ve
+ 	free_pgvec(mpp->pg, KEEP_PATHS);
+ 	mpp->pg = NULL;
+ 
+-	if (setup_multipath(vecs, mpp))
++	if (__setup_multipath(vecs, mpp, reset))
+ 		return 1; /* mpp freed in setup_multipath */
+ 
+ 	adopt_paths(vecs->pathvec, mpp, 0);
+Index: multipath-tools/libmultipath/structs_vec.h
+===================================================================
+--- multipath-tools.orig/libmultipath/structs_vec.h
++++ multipath-tools/libmultipath/structs_vec.h
+@@ -21,7 +21,9 @@ void orphan_path (struct path * pp);
+ 
+ int verify_paths(struct multipath * mpp, struct vectors * vecs, vector rpvec);
+ int update_mpp_paths(struct multipath * mpp, vector pathvec);
+-int setup_multipath (struct vectors * vecs, struct multipath * mpp);
++int __setup_multipath (struct vectors * vecs, struct multipath * mpp,
++		       int reset);
++#define setup_multipath(vecs, mpp) __setup_multipath(vecs, mpp, 1)
+ int update_multipath_strings (struct multipath *mpp, vector pathvec);
+ 	
+ void remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec);
+@@ -33,7 +35,7 @@ struct multipath * add_map_without_path 
+ 				int minor, char * alias);
+ struct multipath * add_map_with_path (struct vectors * vecs,
+ 				struct path * pp, int add_vec);
+-int update_multipath (struct vectors *vecs, char *mapname);
++int update_multipath (struct vectors *vecs, char *mapname, int reset);
+ void update_queue_mode_del_path(struct multipath *mpp);
+ void update_queue_mode_add_path(struct multipath *mpp);
+ 
+Index: multipath-tools/libmultipath/waiter.c
+===================================================================
+--- multipath-tools.orig/libmultipath/waiter.c
++++ multipath-tools/libmultipath/waiter.c
+@@ -161,7 +161,7 @@ int waiteventloop (struct event_thread *
+ 		 */
+ 		pthread_cleanup_push(cleanup_lock, &waiter->vecs->lock);
+ 		lock(waiter->vecs->lock);
+-		r = update_multipath(waiter->vecs, waiter->mapname);
++		r = update_multipath(waiter->vecs, waiter->mapname, 1);
+ 		lock_cleanup_pop(waiter->vecs->lock);
+ 
+ 		if (r) {
diff --git a/0056-RHBZ-603812-better-type-check.patch b/0056-RHBZ-603812-better-type-check.patch
new file mode 100644
index 0000000..239058a
--- /dev/null
+++ b/0056-RHBZ-603812-better-type-check.patch
@@ -0,0 +1,91 @@
+Index: multipath-tools/multipath/main.c
+===================================================================
+--- multipath-tools.orig/multipath/main.c
++++ multipath-tools/multipath/main.c
+@@ -22,6 +22,8 @@
+  * Copyright (c) 2005 Edward Goggin, EMC
+  */
+ 
++#include <sys/types.h>
++#include <sys/stat.h>
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <ctype.h>
+@@ -52,6 +54,7 @@
+ #include <sys/time.h>
+ #include <sys/resource.h>
+ #include <finder.h>
++#include "dev_t.h"
+ 
+ int logsink;
+ 
+@@ -333,13 +336,29 @@ out:
+ 	return r;
+ }
+ 
++static int
++get_dev_type(char *dev) {
++	struct stat buf;
++	int i;
++
++	if (stat(dev, &buf) == 0 && S_ISBLK(buf.st_mode)) {
++		if (dm_is_dm_major(MAJOR(buf.st_rdev)))
++			return DEV_DEVMAP;
++		return DEV_DEVNODE;
++	}
++	else if (sscanf(dev, "%d:%d", &i, &i) == 2)
++		return DEV_DEVT;
++	else
++		return DEV_DEVMAP;
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+ 	int arg;
+ 	extern char *optarg;
+ 	extern int optind;
+-	int i, r = 1;
++	int r = 1;
+ 
+ 	if (getuid() != 0) {
+ 		fprintf(stderr, "need to be root\n");
+@@ -436,14 +455,7 @@ main (int argc, char *argv[])
+ 			goto out;
+ 
+ 		strncpy(conf->dev, argv[optind], FILE_NAME_SIZE);
+-
+-		if (filepresent(conf->dev))
+-			conf->dev_type = DEV_DEVNODE;
+-		else if (sscanf(conf->dev, "%d:%d", &i, &i) == 2)
+-			conf->dev_type = DEV_DEVT;
+-		else
+-			conf->dev_type = DEV_DEVMAP;
+-
++		conf->dev_type = get_dev_type(conf->dev);
+ 	}
+ 	conf->daemon = 0;
+ 
+Index: multipath-tools/multipath/dev_t.h
+===================================================================
+--- multipath-tools.orig/multipath/dev_t.h
++++ multipath-tools/multipath/dev_t.h
+@@ -1,15 +1,3 @@
+-#define MINORBITS       20
+-#define MINORMASK       ((1U << MINORBITS) - 1)
+-
+-#define MAJOR(dev)      ((unsigned int) ((dev) >> MINORBITS))
+-#define MINOR(dev)      ((unsigned int) ((dev) & MINORMASK))
+-#define MKDEV(ma,mi)    (((ma) << MINORBITS) | (mi))
+-
+-#define print_dev_t(buffer, dev)                                        \
+-	sprintf((buffer), "%u:%u\n", MAJOR(dev), MINOR(dev))
+-
+-#define format_dev_t(buffer, dev)                                       \
+-	({                                                              \
+-		sprintf(buffer, "%u:%u", MAJOR(dev), MINOR(dev));       \
+-		buffer;                                                 \
+-	})
++#define MAJOR(dev)      ((dev & 0xfff00) >> 8)
++#define MINOR(dev)      ((dev & 0xff) | ((dev >> 12) & 0xfff00))
++#define MKDEV(ma,mi)    ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
diff --git a/0057-RHBZ-607869-fix-resize.patch b/0057-RHBZ-607869-fix-resize.patch
new file mode 100644
index 0000000..2180cf7
--- /dev/null
+++ b/0057-RHBZ-607869-fix-resize.patch
@@ -0,0 +1,35 @@
+---
+ libmultipath/configure.c |    4 ++--
+ libmultipath/log.h       |    4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+Index: multipath-tools/libmultipath/configure.c
+===================================================================
+--- multipath-tools.orig/libmultipath/configure.c
++++ multipath-tools/libmultipath/configure.c
+@@ -193,8 +193,8 @@ select_action (struct multipath * mpp, v
+ 		return;
+ 	}
+ 	if (cmpp->size != mpp->size) {
+-		mpp->action = ACT_RELOAD;
+-		condlog(3, "%s: set ACT_RELOAD (size change)",
++		mpp->action = ACT_RESIZE;
++		condlog(3, "%s: set ACT_RESIZE (size change)",
+ 			mpp->alias);
+ 		return;
+ 	}
+Index: multipath-tools/libmultipath/log.h
+===================================================================
+--- multipath-tools.orig/libmultipath/log.h
++++ multipath-tools/libmultipath/log.h
+@@ -1,8 +1,8 @@
+ #ifndef LOG_H
+ #define LOG_H
+ 
+-#define DEFAULT_AREA_SIZE 8192
+-#define MAX_MSG_SIZE 128
++#define DEFAULT_AREA_SIZE 16384
++#define MAX_MSG_SIZE 256
+ 
+ #ifndef LOGLEVEL
+ #define LOGLEVEL 5
diff --git a/0058-RHBZ-601665-assemble-features.patch b/0058-RHBZ-601665-assemble-features.patch
new file mode 100644
index 0000000..aecd845
--- /dev/null
+++ b/0058-RHBZ-601665-assemble-features.patch
@@ -0,0 +1,66 @@
+---
+ libmultipath/dmparser.c |   37 ++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 36 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/dmparser.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dmparser.c
++++ multipath-tools/libmultipath/dmparser.c
+@@ -6,6 +6,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <ctype.h>
+ 
+ #include "checkers.h"
+ #include "vector.h"
+@@ -44,6 +45,40 @@ merge_words (char ** dst, char * word, i
+ 	return 0;
+ }
+ 
++char *
++assemble_features (struct multipath *mp)
++{
++	static char features[PARAMS_SIZE];
++	unsigned int nr_features;
++	char *ptr;
++
++	if (!conf->daemon || mp->no_path_retry == NO_PATH_RETRY_UNDEF ||
++	    mp->no_path_retry == NO_PATH_RETRY_FAIL ||
++	    strstr(mp->features, "queue_if_no_path"))
++		return mp->features;
++	if (18 > PARAMS_SIZE - 1 - strlen(mp->features)) {
++		fprintf(stderr, "not enough size to modify features\n");
++		return mp->features;
++	}
++	if (sscanf(mp->features, "%u", &nr_features) != 1) {
++		fprintf(stderr, "can't find number of features\n");
++		return mp->features;
++	}
++	ptr = mp->features;
++	while (isspace(*ptr))
++		ptr++;
++	if (*ptr == '\0') {
++		fprintf(stderr, "features is empty\n");
++		return mp->features;
++	}
++	while(*ptr != '\0' && !isspace(*ptr))
++		ptr++;
++
++	snprintf(features, PARAMS_SIZE, "%u%s queue_if_no_path",
++		 nr_features + 1, ptr);
++	return features;
++}
++
+ /*
+  * Transforms the path group vector into a proper device map string
+  */
+@@ -62,7 +97,7 @@ assemble_map (struct multipath * mp)
+ 	freechar = sizeof(mp->params);
+ 
+ 	shift = snprintf(p, freechar, "%s %s %i %i",
+-			 mp->features, mp->hwhandler,
++			 assemble_features(mp), mp->hwhandler,
+ 			 VECTOR_SIZE(mp->pg), mp->bestpg);
+ 
+ 	if (shift >= freechar) {
diff --git a/0059-RHBZ-607874-handle-offlined-paths.patch b/0059-RHBZ-607874-handle-offlined-paths.patch
new file mode 100644
index 0000000..75bf35a
--- /dev/null
+++ b/0059-RHBZ-607874-handle-offlined-paths.patch
@@ -0,0 +1,68 @@
+---
+ libmultipath/discovery.c |    9 +++++++--
+ multipathd/main.c        |   13 ++++++++++---
+ 2 files changed, 17 insertions(+), 5 deletions(-)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -794,8 +794,13 @@ get_state (struct path * pp, int daemon)
+ 	condlog(3, "%s: get_state", pp->dev);
+ 
+ 	if (!checker_selected(c)) {
+-		if (daemon)
+-			pathinfo(pp, conf->hwtable, DI_SYSFS);
++		if (daemon || pp->sysdev == NULL) {
++			if (pathinfo(pp, conf->hwtable, DI_SYSFS) != 0) {
++				condlog(3, "%s: couldn't get sysfs pathinfo",
++					pp->dev);
++				return PATH_UNCHECKED;
++			}
++		}
+ 		select_checker(pp);
+ 		if (!checker_selected(c)) {
+ 			condlog(3, "%s: No checker selected", pp->dev);
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -365,6 +365,7 @@ ev_add_path (char * devname, struct vect
+ 	struct multipath * mpp;
+ 	struct path * pp;
+ 	char empty_buff[WWID_SIZE] = {0};
++	int retries = 3;
+ 
+ 	if (strstr(devname, "..") != NULL) {
+ 		/*
+@@ -450,12 +451,14 @@ rescan:
+ 		/*
+ 		 * deal with asynchronous uevents :((
+ 		 */
+-		if (mpp->action == ACT_RELOAD) {
++		if (mpp->action == ACT_RELOAD && retries-- > 0) {
+ 			condlog(0, "%s: uev_add_path sleep", mpp->alias);
+ 			sleep(1);
+ 			update_mpp_paths(mpp, vecs->pathvec);
+ 			goto rescan;
+ 		}
++		else if (mpp->action == ACT_RELOAD)
++			condlog(0, "%s: giving up reload", mpp->alias);
+ 		else
+ 			goto fail_map;
+ 	}
+@@ -473,8 +476,12 @@ rescan:
+ 	    start_waiter_thread(mpp, vecs))
+ 			goto fail_map;
+ 
+-	condlog(2, "%s path added to devmap %s", devname, mpp->alias);
+-	return 0;
++	if (retries > 0) {
++		condlog(2, "%s path added to devmap %s", devname, mpp->alias);
++		return 0;
++	}
++	else
++		return 1;
+ 
+ fail_map:
+ 	remove_map(mpp, vecs, 1);
diff --git a/0060-RHBZ-606420-fix-remove-map.patch b/0060-RHBZ-606420-fix-remove-map.patch
new file mode 100644
index 0000000..5670011
--- /dev/null
+++ b/0060-RHBZ-606420-fix-remove-map.patch
@@ -0,0 +1,16 @@
+--- multipath-tools/multipathd/main.c	2010-06-18 09:44:59.000000000 +0200
++++ multipath-tools.new/multipathd/main.c	2010-06-18 10:21:41.000000000 +0200
+@@ -317,11 +317,9 @@ ev_remove_map (char * devname, struct ve
+ 	if (!mpp) {
+ 		condlog(2, "%s: devmap not registered, can't remove",
+ 			devname);
+-		return 0;
++		return 1;
+ 	}
+-	flush_map(mpp, vecs);
+-
+-	return 0;
++	return flush_map(mpp, vecs);
+ }
+ 
+ static int
diff --git a/0061-RHBZ-620479-find-rport.patch b/0061-RHBZ-620479-find-rport.patch
new file mode 100644
index 0000000..e238dae
--- /dev/null
+++ b/0061-RHBZ-620479-find-rport.patch
@@ -0,0 +1,77 @@
+diff -urp multipath-tools-0.4.9-23.el6-Snapshot8/libmultipath/discovery.c multipath-tools-0.4.9-23.el6-findrport/libmultipath/discovery.c
+--- multipath-tools-0.4.9-23.el6-Snapshot8/libmultipath/discovery.c	2010-07-30 15:06:10.000000000 +0900
++++ multipath-tools-0.4.9-23.el6-findrport/libmultipath/discovery.c	2010-07-30 18:02:47.000000000 +0900
+@@ -10,6 +10,7 @@
+ #include <sys/stat.h>
+ #include <dirent.h>
+ #include <errno.h>
++#include <libgen.h>
+ 
+ #include "checkers.h"
+ #include "vector.h"
+@@ -229,6 +230,41 @@ sysfs_get_fc_nodename (struct sysfs_devi
+ 	return 1;
+ }
+ 
++static int
++find_rport_id(struct path *pp)
++{
++	char attr_path[SYSFS_PATH_SIZE];
++	char *dir, *base;
++	int host, channel, rport_id = -1;
++
++	if (safe_sprintf(attr_path,
++			 "/class/fc_transport/target%i:%i:%i",
++			 pp->sg_id.host_no, pp->sg_id.channel,
++			 pp->sg_id.scsi_id)) {
++		condlog(0, "attr_path too small for target");
++		return 1;
++	}
++
++	if (sysfs_resolve_link(attr_path, SYSFS_PATH_SIZE))
++		return -1;
++
++	condlog(4, "target%d:%d:%d -> path %s", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id, attr_path);
++	dir = attr_path;
++	do {
++		base = basename(dir);
++		dir = dirname(dir);
++
++		if (sscanf((const char *)base, "rport-%d:%d-%d", &host, &channel, &rport_id) == 3)
++			break;
++	} while (strcmp((const char *)dir, "/"));
++
++	if (rport_id < 0)
++		return -1;
++
++	condlog(4, "target%d:%d:%d -> rport_id %d", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id, rport_id);
++	return rport_id;
++}
++
+ int
+ sysfs_set_scsi_tmo (struct multipath *mpp)
+ {
+@@ -236,15 +272,21 @@ sysfs_set_scsi_tmo (struct multipath *mp
+ 	struct path *pp;
+ 	int i;
+ 	char value[11];
++	int rport_id;
+ 
+ 	if (!mpp->dev_loss && !mpp->fast_io_fail)
+ 		return 0;
+ 	vector_foreach_slot(mpp->paths, pp, i) {
++		rport_id = find_rport_id(pp);
++		if (rport_id < 0) {
++			condlog(0, "failed to find rport_id for target%d:%d:%d", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id);
++			return 1;
++		}
+ 		if (safe_snprintf(attr_path, SYSFS_PATH_SIZE,
+ 	        	          "/class/fc_remote_ports/rport-%d:%d-%d",
+ 				  pp->sg_id.host_no, pp->sg_id.channel,
+-				  pp->sg_id.scsi_id)) {
+-			condlog(0, "attr_path '/class/fc_remote_ports/rport-%d:%d-%d' too large", pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.scsi_id);
++				  rport_id)) {
++			condlog(0, "attr_path '/class/fc_remote_ports/rport-%d:%d-%d' too large", pp->sg_id.host_no, pp->sg_id.channel, rport_id);
+ 			return 1;
+ 		}
+ 		if (mpp->dev_loss){
diff --git a/0062-RHBZ-592998-hpsc-config.patch b/0062-RHBZ-592998-hpsc-config.patch
new file mode 100644
index 0000000..d6bfb20
--- /dev/null
+++ b/0062-RHBZ-592998-hpsc-config.patch
@@ -0,0 +1,17 @@
+---
+ libmultipath/hwtable.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -221,7 +221,7 @@ static struct hwentry default_hw[] = {
+ 		.rr_weight     = RR_WEIGHT_NONE,
+ 		.no_path_retry = 12,
+ 		.minio         = DEFAULT_MINIO,
+-		.checker_name  = CCISS_TUR,
++		.checker_name  = TUR,
+ 		.prio_name     = DEFAULT_PRIO,
+ 	},
+ 	/*
diff --git a/0063-RHBZ-595719-udev_link_priority.patch b/0063-RHBZ-595719-udev_link_priority.patch
new file mode 100644
index 0000000..06a5849
--- /dev/null
+++ b/0063-RHBZ-595719-udev_link_priority.patch
@@ -0,0 +1,19 @@
+---
+ multipath/multipath.rules |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/multipath/multipath.rules
+===================================================================
+--- multipath-tools.orig/multipath/multipath.rules
++++ multipath-tools/multipath/multipath.rules
+@@ -16,8 +16,9 @@ ENV{DM_MULTIPATH_DEVICE_PATH}=="1", ENV{
+ RUN+="socket:/org/kernel/dm/multipath_event"
+ KERNEL!="dm-*", GOTO="end_mpath"
+ ACTION!="change", GOTO="end_mpath"
+-ENV{DM_SUSPENDED}=="1", GOTO="end_mpath"
++ENV{DM_UUID}=="mpath-?*|part[0-9]*-mpath-?*", OPTIONS+="link_priority=10"
+ ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath"
++ENV{DM_SUSPENDED}=="1", GOTO="end_mpath"
+ ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath"
+ RUN+="$env{MPATH_SBIN_PATH}/kpartx -a -p p $tempnode"
+ LABEL="end_mpath"
diff --git a/0064-RHBZ-612173-fix-reverse-lookup.patch b/0064-RHBZ-612173-fix-reverse-lookup.patch
new file mode 100644
index 0000000..7799dee
--- /dev/null
+++ b/0064-RHBZ-612173-fix-reverse-lookup.patch
@@ -0,0 +1,13 @@
+Index: multipath-tools/libmultipath/alias.c
+===================================================================
+--- multipath-tools.orig/libmultipath/alias.c
++++ multipath-tools/libmultipath/alias.c
+@@ -141,7 +141,7 @@ rlookup_binding(FILE *f, char **map_wwid
+ 		curr_id = scan_devname(alias);
+ 		if (curr_id >= id)
+ 			id = curr_id + 1;
+-		wwid = strtok(NULL, " \t");
++		wwid = strtok(NULL, "");
+ 		if (!wwid){
+ 			condlog(3,
+ 				"Ignoring malformed line %u in bindings file",
diff --git a/0065-RHBZ-635088-update-priority.patch b/0065-RHBZ-635088-update-priority.patch
new file mode 100644
index 0000000..7c594dc
--- /dev/null
+++ b/0065-RHBZ-635088-update-priority.patch
@@ -0,0 +1,79 @@
+---
+ multipathd/main.c |   45 +++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 35 insertions(+), 10 deletions(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -943,14 +943,41 @@ retry_count_tick(vector mpvec)
+ 	}
+ }
+ 
+-int update_path_groups(struct multipath *mpp, struct vectors *vecs)
++int update_prio(struct path *pp, int refresh_all)
++{
++	int oldpriority;
++	struct pathgroup * pgp;
++	int i, j, changed = 0;
++
++	if (refresh_all) {
++		vector_foreach_slot (pp->mpp->pg, pgp, i) {
++			vector_foreach_slot (pgp->paths, pp, j) {
++				oldpriority = pp->priority;
++				pathinfo(pp, conf->hwtable, DI_PRIO);
++				if (pp->priority != oldpriority)
++					changed = 1;
++			}
++		}
++		return changed;
++	}
++	oldpriority = pp->priority;
++	pathinfo(pp, conf->hwtable, DI_PRIO);
++
++	if (pp->priority == oldpriority)
++		return 0;
++	return 1;
++}
++
++int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh)
+ {
+ 	int i;
+ 	struct path * pp;
+ 
+ 	update_mpp_paths(mpp, vecs->pathvec);
+-	vector_foreach_slot (mpp->paths, pp, i)
+-		pathinfo(pp, conf->hwtable, DI_PRIO);
++	if (!refresh) {
++		vector_foreach_slot (mpp->paths, pp, i)
++			pathinfo(pp, conf->hwtable, DI_PRIO);
++	}
+ 	setup_map(mpp);
+ 	mpp->action = ACT_RELOAD;
+ 	if (domap(mpp) <= 0) {
+@@ -969,7 +996,6 @@ void
+ check_path (struct vectors * vecs, struct path * pp)
+ {
+ 	int newstate;
+-	int oldpriority;
+ 	int new_path_up = 0;
+ 
+ 	if (!pp->mpp)
+@@ -1072,12 +1098,11 @@ check_path (struct vectors * vecs, struc
+ 	 * path prio refreshing
+ 	 */
+ 	condlog(4, "path prio refresh");
+-	oldpriority = pp->priority;
+-	pathinfo(pp, conf->hwtable, DI_PRIO);
+-	if (pp->priority != oldpriority &&
+-	    pp->mpp->pgpolicyfn == (pgpolicyfn *)group_by_prio)
+-		update_path_groups(pp->mpp, vecs);
+-	else if (need_switch_pathgroup(pp->mpp, new_path_up)) {
++	if (update_prio(pp, new_path_up) &&
++	    pp->mpp->pgpolicyfn == (pgpolicyfn *)group_by_prio &&
++	    pp->mpp->pgfailback != -FAILBACK_FOLLOWOVER)
++		update_path_groups(pp->mpp, vecs, !new_path_up);
++	else if (need_switch_pathgroup(pp->mpp, 0)) {
+ 		if (pp->mpp->pgfailback > 0 &&
+ 		    (new_path_up || pp->mpp->failback_tick <= 0))
+ 			pp->mpp->failback_tick =
diff --git a/0066-RHBZ-636071-mpathconf-variable_names.patch b/0066-RHBZ-636071-mpathconf-variable_names.patch
new file mode 100644
index 0000000..1df1527
--- /dev/null
+++ b/0066-RHBZ-636071-mpathconf-variable_names.patch
@@ -0,0 +1,35 @@
+---
+ multipath/mpathconf |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+Index: multipath-tools/multipath/mpathconf
+===================================================================
+--- multipath-tools.orig/multipath/mpathconf
++++ multipath-tools/multipath/mpathconf
+@@ -17,6 +17,8 @@
+ # This program was largely ripped off from lvmconf
+ #
+ 
++unset ENABLE FIND FRIENDLY MODULE MULTIPATHD CHKCONFIG HAVE_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_DEFAULTS HAVE_FRIENDLY HAVE_MULTIPATHD HAVE_CHKCONFIG HAVE_MODULE SHOW_STATUS CHANGED_CONFIG
++
+ DEFAULT_CONFIGFILE="/usr/share/doc/device-mapper-multipath-0.4.9/multipath.conf"
+ CONFIGFILE="/etc/multipath.conf"
+ MULTIPATHDIR="/etc/multipath"
+@@ -118,7 +120,7 @@ function validate_args
+ 		exit 1
+ 	fi
+ 	if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" ]; then
+-		DISPLAY=1
++		SHOW_STATUS=1
+ 	fi
+ 	if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
+ 		echo "--with_module must be either 'y' or 'n'"
+@@ -211,7 +213,7 @@ if [ "$HAVE_DEFAULTS" = "1" ]; then
+ 	fi
+ fi
+ 
+-if [ -n "$DISPLAY" ]; then
++if [ -n "$SHOW_STATUS" ]; then
+ 	if [ -z "$HAVE_DISABLE" -o "$HAVE_DISABLE" = 0 ]; then
+ 		echo "multipath is enabled"
+ 	else
diff --git a/0067-RHBZ-622569-symmetrix-config.patch b/0067-RHBZ-622569-symmetrix-config.patch
new file mode 100644
index 0000000..a6a8967
--- /dev/null
+++ b/0067-RHBZ-622569-symmetrix-config.patch
@@ -0,0 +1,36 @@
+---
+ libmultipath/hwtable.c  |    4 ++--
+ multipath.conf.defaults |    3 ++-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -261,9 +261,9 @@ static struct hwentry default_hw[] = {
+ 		.pgpolicy      = MULTIBUS,
+ 		.pgfailback    = FAILBACK_UNDEF,
+ 		.rr_weight     = RR_WEIGHT_NONE,
+-		.no_path_retry = NO_PATH_RETRY_UNDEF,
++		.no_path_retry = 6,
+ 		.minio         = DEFAULT_MINIO,
+-		.checker_name  = DIRECTIO,
++		.checker_name  = TUR,
+ 		.prio_name     = DEFAULT_PRIO,
+ 	},
+ 	{
+Index: multipath-tools/multipath.conf.defaults
+===================================================================
+--- multipath-tools.orig/multipath.conf.defaults
++++ multipath-tools/multipath.conf.defaults
+@@ -187,8 +187,9 @@
+ #		path_selector		"round-robin 0"
+ #		path_grouping_policy	multibus
+ #		rr_weight		uniform
++#		no_path_retry		6
+ #		rr_min_io		1000
+-#		path_checker		directio
++#		path_checker		tur
+ #		prio			const
+ #	}
+ #	device {
diff --git a/0068-RHBZ-632734-nvdisk-config.patch b/0068-RHBZ-632734-nvdisk-config.patch
new file mode 100644
index 0000000..3338935
--- /dev/null
+++ b/0068-RHBZ-632734-nvdisk-config.patch
@@ -0,0 +1,89 @@
+---
+ libmultipath/hwtable.c  |   34 ++++++++++++++++++++++++++++++++++
+ multipath.conf.defaults |   28 ++++++++++++++++++++++++++++
+ 2 files changed, 62 insertions(+)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -717,6 +717,40 @@ static struct hwentry default_hw[] = {
+ 		.prio_name     = DEFAULT_PRIO,
+ 	},
+ 	{
++		/* IBM 3303      NVDISK */
++		.vendor        = "IBM",
++		.product       = "3303      NVDISK",
++		.getuid        = DEFAULT_GETUID,
++		.features      = DEFAULT_FEATURES,
++		.hwhandler     = DEFAULT_HWHANDLER,
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = FAILOVER,
++		.pgfailback    = -FAILBACK_IMMEDIATE,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = (300 / DEFAULT_CHECKINT),
++		.minio         = DEFAULT_MINIO,
++		.checker_name  = TUR,
++		.prio_name     = DEFAULT_PRIO,
++		.prio_args     = NULL,
++	},
++	{
++		/* AIX NVDISK */
++		.vendor        = "AIX",
++		.product       = "NVDISK",
++		.getuid        = DEFAULT_GETUID,
++		.features      = DEFAULT_FEATURES,
++		.hwhandler     = "1 alua",
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = GROUP_BY_PRIO,
++		.pgfailback    = -FAILBACK_IMMEDIATE,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = (300 / DEFAULT_CHECKINT),
++		.minio         = DEFAULT_MINIO,
++		.checker_name  = TUR,
++		.prio_name     = PRIO_ALUA,
++		.prio_args     = NULL,
++	},
++	{
+ 		/* DELL MD3000 */
+ 		.vendor        = "DELL",
+ 		.product       = "MD3000",
+Index: multipath-tools/multipath.conf.defaults
+===================================================================
+--- multipath-tools.orig/multipath.conf.defaults
++++ multipath-tools/multipath.conf.defaults
+@@ -474,6 +474,34 @@
+ #		path_checker		tur
+ #		prio			alua
+ #	}
++#       device {
++#               vendor                  "IBM"
++#               product                 "3303      NVDISK"
++#               getuid_callout          "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
++#               features                "0"
++#               hardware_handler        "0"
++#               path_grouping_policy    failover
++#               failback                immediate
++#               no_path_retry           60
++#               rr_weight               uniform
++#               rr_min_io               1000
++#               path_checker            tur
++#       }
++#       device {
++#               vendor                  "AIX"
++#               product                 "NVDISK"
++#               getuid_callout          "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
++#               features                "0"
++#               hardware_handler        "1 alua"
++#               path_grouping_policy    group_by_prio
++#               failback                immediate
++#               no_path_retry           60
++#               rr_weight               uniform
++#               rr_min_io               1000
++#               path_checker            tur
++#               prio                    alua
++#               prio_args               ""
++#       }
+ #	device {
+ #		vendor			"SGI"
+ #		product			"TP9[13]00"
diff --git a/0069-RHBZ-636246-hp-open-config.patch b/0069-RHBZ-636246-hp-open-config.patch
new file mode 100644
index 0000000..d94c66b
--- /dev/null
+++ b/0069-RHBZ-636246-hp-open-config.patch
@@ -0,0 +1,74 @@
+---
+ libmultipath/hwtable.c  |   17 ++++++++++++++++-
+ multipath.conf.defaults |   16 +++++++++++++++-
+ 2 files changed, 31 insertions(+), 2 deletions(-)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -224,6 +224,21 @@ static struct hwentry default_hw[] = {
+ 		.checker_name  = TUR,
+ 		.prio_name     = DEFAULT_PRIO,
+ 	},
++	{
++		.vendor        = "HP",
++		.product       = "OPEN-.*",
++		.getuid        = DEFAULT_GETUID,
++		.features      = DEFAULT_FEATURES,
++		.hwhandler     = DEFAULT_HWHANDLER,
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = MULTIBUS,
++		.pgfailback    = FAILBACK_UNDEF,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = 18,
++		.minio         = DEFAULT_MINIO,
++		.checker_name  = TUR,
++		.prio_name     = DEFAULT_PRIO,
++	},
+ 	/*
+ 	 * DDN controller family
+ 	 *
+@@ -325,7 +340,7 @@ static struct hwentry default_hw[] = {
+ 	 * Mail : matthias.rudolph at hds.com
+ 	 */
+ 	{
+-		.vendor        = "(HITACHI|HP)",
++		.vendor        = "HITACHI",
+ 		.product       = "OPEN-.*",
+ 		.getuid        = DEFAULT_GETUID,
+ 		.features      = DEFAULT_FEATURES,
+Index: multipath-tools/multipath.conf.defaults
+===================================================================
+--- multipath-tools.orig/multipath.conf.defaults
++++ multipath-tools/multipath.conf.defaults
+@@ -166,6 +166,20 @@
+ #		prio			const
+ #	}
+ #	device {
++#		vendor			"HP"
++#		product			"OPEN-.*"
++#		getuid_callout		"/lib/udev/scsi_id --whitelisted --device=/dev/%n"
++#		features		"0"
++#		hardware_handler	"0"
++#		path_selector		"round-robin 0"
++#		path_grouping_policy	multibus
++#		rr_weight		uniform
++#		no_path_retry		18
++#		rr_min_io		1000
++#		path_checker		tur
++#		prio			const
++#	}
++#	device {
+ #		vendor			"DDN"
+ #		product			"SAN DataDirector"
+ #		getuid_callout		"/lib/udev/scsi_id --whitelisted --device=/dev/%n"
+@@ -238,7 +252,7 @@
+ #		prio			const
+ #	}
+ #	device {
+-#		vendor			"(HITACHI|HP)"
++#		vendor			"HITACHI"
+ #		product			"OPEN-.*"
+ #		getuid_callout		"/lib/udev/scsi_id --whitelisted --device=/dev/%n"
+ #		features		"1 queue_if_no_path"
diff --git a/0070-RHBZ-639037-hitachi-open-config.patch b/0070-RHBZ-639037-hitachi-open-config.patch
new file mode 100644
index 0000000..07a5bee
--- /dev/null
+++ b/0070-RHBZ-639037-hitachi-open-config.patch
@@ -0,0 +1,30 @@
+---
+ libmultipath/hwtable.c  |    2 +-
+ multipath.conf.defaults |    1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -349,7 +349,7 @@ static struct hwentry default_hw[] = {
+ 		.pgpolicy      = MULTIBUS,
+ 		.pgfailback    = FAILBACK_UNDEF,
+ 		.rr_weight     = RR_WEIGHT_NONE,
+-		.no_path_retry = NO_PATH_RETRY_UNDEF,
++		.no_path_retry = 6,
+ 		.minio         = DEFAULT_MINIO,
+ 		.checker_name  = TUR,
+ 		.prio_name     = DEFAULT_PRIO,
+Index: multipath-tools/multipath.conf.defaults
+===================================================================
+--- multipath-tools.orig/multipath.conf.defaults
++++ multipath-tools/multipath.conf.defaults
+@@ -260,6 +260,7 @@
+ #		path_selector		"round-robin 0"
+ #		path_grouping_policy	multibus
+ #		rr_weight		uniform
++#		no_path_retry		6
+ #		rr_min_io		100
+ #		path_checker		tur
+ #		prio			const
diff --git a/0071-RHBZ-611779-fix-whitespace-crash.patch b/0071-RHBZ-611779-fix-whitespace-crash.patch
new file mode 100644
index 0000000..3c6374a
--- /dev/null
+++ b/0071-RHBZ-611779-fix-whitespace-crash.patch
@@ -0,0 +1,20 @@
+---
+ multipathd/cli.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/multipathd/cli.c
+===================================================================
+--- multipath-tools.orig/multipathd/cli.c
++++ multipath-tools/multipathd/cli.c
+@@ -228,8 +228,10 @@ get_cmdvec (char * cmd, vector *v)
+ 	vector cmdvec, strvec;
+ 
+ 	strvec = alloc_strvec(cmd);
+-	if (!strvec)
++	if (!strvec) {
++		*v = NULL;
+ 		return 0;
++	}
+ 
+ 	cmdvec = vector_alloc();
+ 	*v = cmdvec;
diff --git a/0072-RHBZ-651389-change-scsi-tmo-order.patch b/0072-RHBZ-651389-change-scsi-tmo-order.patch
new file mode 100644
index 0000000..e0998d3
--- /dev/null
+++ b/0072-RHBZ-651389-change-scsi-tmo-order.patch
@@ -0,0 +1,34 @@
+---
+ libmultipath/discovery.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -289,12 +289,6 @@ sysfs_set_scsi_tmo (struct multipath *mp
+ 			condlog(0, "attr_path '/class/fc_remote_ports/rport-%d:%d-%d' too large", pp->sg_id.host_no, pp->sg_id.channel, rport_id);
+ 			return 1;
+ 		}
+-		if (mpp->dev_loss){
+-			snprintf(value, 11, "%u", mpp->dev_loss);
+- 			if (sysfs_attr_set_value(attr_path, "dev_loss_tmo",
+-						 value))
+-				return 1;
+-		}
+ 		if (mpp->fast_io_fail){
+ 			if (mpp->fast_io_fail == -1)
+ 				sprintf(value, "off");
+@@ -304,6 +298,12 @@ sysfs_set_scsi_tmo (struct multipath *mp
+ 						 value))
+ 				return 1;
+ 		}
++		if (mpp->dev_loss){
++			snprintf(value, 11, "%u", mpp->dev_loss);
++ 			if (sysfs_attr_set_value(attr_path, "dev_loss_tmo",
++						 value))
++				return 1;
++		}
+ 	}
+ 	return 0;
+ }
diff --git a/0073-RHBZ-650664-clarify-error-msg.patch b/0073-RHBZ-650664-clarify-error-msg.patch
new file mode 100644
index 0000000..57ca0aa
--- /dev/null
+++ b/0073-RHBZ-650664-clarify-error-msg.patch
@@ -0,0 +1,157 @@
+---
+ libmultipath/alias.c     |   14 ++++++++++----
+ libmultipath/callout.c   |    5 ++++-
+ libmultipath/discovery.c |    7 +++++--
+ libmultipath/file.c      |   14 ++++++++++----
+ libmultipath/finder.c    |    7 +++++--
+ libmultipath/sysfs.c     |   14 ++++++++++----
+ 6 files changed, 44 insertions(+), 17 deletions(-)
+
+Index: multipath-tools/libmultipath/callout.c
+===================================================================
+--- multipath-tools.orig/libmultipath/callout.c
++++ multipath-tools/libmultipath/callout.c
+@@ -65,7 +65,10 @@ int execute_program(char *path, char *va
+ 	retval = pipe(fds);
+ 
+ 	if (retval != 0) {
+-		condlog(0, "error creating pipe for callout: %s", strerror(errno));
++		if (errno == EMFILE)
++			condlog(0, "out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++		else
++			condlog(0, "error creating pipe for callout: %s", strerror(errno));
+ 		return -1;
+ 	}
+ 
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -945,8 +945,11 @@ pathinfo (struct path *pp, vector hwtabl
+ 		pp->fd = opennode(pp->dev, O_RDONLY);
+ 
+ 	if (pp->fd < 0) {
+-		condlog(4, "Couldn't open node for %s: %s",
+-			pp->dev, strerror(errno));
++		if (errno == EMFILE)
++			condlog(0, "out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++		else
++			condlog(4, "Couldn't open node for %s: %s",
++				pp->dev, strerror(errno));
+ 		goto blank;
+ 	}
+ 
+Index: multipath-tools/libmultipath/file.c
+===================================================================
+--- multipath-tools.orig/libmultipath/file.c
++++ multipath-tools/libmultipath/file.c
+@@ -140,8 +140,11 @@ open_file(char *file, int *can_write, ch
+ 			}
+ 		}
+ 		else {
+-			condlog(0, "Cannot open file [%s] : %s", file,
+-				strerror(errno));
++			if (errno == EMFILE)
++				condlog(0, "out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++			else
++				condlog(0, "Cannot open file [%s] : %s", file,
++					strerror(errno));
+ 			return -1;
+ 		}
+ 	}
+@@ -186,8 +189,11 @@ int pidfile_check(const char *file)
+ 	if (fd < 0) {
+ 		if (errno == ENOENT)
+ 			return 0;
+-		condlog(0, "Cannot open pidfile, %s : %s", file,
+-			strerror(errno));
++		if (errno == EMFILE)
++			condlog(0, "out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++		else
++			condlog(0, "Cannot open pidfile, %s : %s", file,
++				strerror(errno));
+ 		return -1;
+ 	}
+ 	lock.l_type = F_WRLCK;
+Index: multipath-tools/libmultipath/sysfs.c
+===================================================================
+--- multipath-tools.orig/libmultipath/sysfs.c
++++ multipath-tools/libmultipath/sysfs.c
+@@ -392,8 +392,11 @@ sysfs_attr_set_value(const char *devpath
+ 
+ 	fd = open(path_full, O_WRONLY);
+ 	if (fd < 0) {
+-		dbg("attribute '%s' can not be opened: %s",
+-		    path_full, strerror(errno));
++		if (errno == EMFILE)
++			dbg("out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++		else
++			dbg("attribute '%s' can not be opened: %s",
++			    path_full, strerror(errno));
+ 		goto out;
+ 	}
+ 	value_len = strlen(value) + 1;
+@@ -494,8 +497,11 @@ char *sysfs_attr_get_value(const char *d
+ 	/* read attribute value */
+ 	fd = open(path_full, O_RDONLY);
+ 	if (fd < 0) {
+-		dbg("attribute '%s' can not be opened: %s",
+-		    path_full, strerror(errno));
++		if (errno == EMFILE)
++			dbg("out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++		else
++			dbg("attribute '%s' can not be opened: %s",
++			    path_full, strerror(errno));
+ 		goto out;
+ 	}
+ 	size = read(fd, value, sizeof(value));
+Index: multipath-tools/libmultipath/alias.c
+===================================================================
+--- multipath-tools.orig/libmultipath/alias.c
++++ multipath-tools/libmultipath/alias.c
+@@ -224,8 +224,11 @@ get_user_friendly_alias(char *wwid, char
+ 
+ 	scan_fd = dup(fd);
+ 	if (scan_fd < 0) {
+-		condlog(0, "Cannot dup bindings file descriptor : %s",
+-			strerror(errno));
++		if (errno == EMFILE)
++			condlog(0, "out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++		else
++			condlog(0, "Cannot dup bindings file descriptor : %s",
++				strerror(errno));
+ 		close(fd);
+ 		return NULL;
+ 	}
+@@ -274,8 +277,11 @@ get_user_friendly_wwid(char *alias, char
+ 
+ 	scan_fd = dup(fd);
+ 	if (scan_fd < 0) {
+-		condlog(0, "Cannot dup bindings file descriptor : %s",
+-			strerror(errno));
++		if (errno == EMFILE)
++			condlog(0, "out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++		else
++			condlog(0, "Cannot dup bindings file descriptor : %s",
++				strerror(errno));
+ 		close(fd);
+ 		return NULL;
+ 	}
+Index: multipath-tools/libmultipath/finder.c
+===================================================================
+--- multipath-tools.orig/libmultipath/finder.c
++++ multipath-tools/libmultipath/finder.c
+@@ -89,8 +89,11 @@ check_wwids_file(char *wwid, int write_w
+ 
+ 	scan_fd = dup(fd);
+ 	if (scan_fd < 0) {
+-		condlog(0, "can't dup wwids file descriptor : %s",
+-			strerror(errno));
++		if (errno == EMFILE)
++			condlog(0, "out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++		else
++			condlog(0, "can't dup wwids file descriptor : %s",
++				strerror(errno));
+ 		close(fd);
+ 		return -1;
+ 	}
diff --git a/0074-RHBZ-602883-dont-print-change.patch b/0074-RHBZ-602883-dont-print-change.patch
new file mode 100644
index 0000000..1d06744
--- /dev/null
+++ b/0074-RHBZ-602883-dont-print-change.patch
@@ -0,0 +1,31 @@
+---
+ multipathd/main.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -217,7 +217,7 @@ flush_map(struct multipath * mpp, struct
+ static int
+ uev_add_map (struct sysfs_device * dev, struct vectors * vecs)
+ {
+-	condlog(2, "%s: add map (uevent)", dev->kernel);
++	condlog(3, "%s: add map (uevent)", dev->kernel);
+ 	return ev_add_map(dev, vecs);
+ }
+ 
+@@ -258,11 +258,12 @@ ev_add_map (struct sysfs_device * dev, s
+ 		 * if we create a multipath mapped device as a result
+ 		 * of uev_add_path
+ 		 */
+-		condlog(0, "%s: devmap already registered",
++		condlog(3, "%s: devmap already registered",
+ 			dev->kernel);
+ 		FREE(alias);
+ 		return 0;
+ 	}
++	condlog(0, "%s: adding map", dev->kernel);
+ 
+ 	/*
+ 	 * now we can register the map
diff --git a/0075-RHBZ-576919-log-checker-err.patch b/0075-RHBZ-576919-log-checker-err.patch
new file mode 100644
index 0000000..f654261
--- /dev/null
+++ b/0075-RHBZ-576919-log-checker-err.patch
@@ -0,0 +1,139 @@
+---
+ libmultipath/config.h      |    1 +
+ libmultipath/dict.c        |   27 +++++++++++++++++++++++++++
+ libmultipath/structs.h     |    5 +++++
+ multipath/multipath.conf.5 |    9 +++++++++
+ multipathd/main.c          |   13 ++++++++++---
+ 5 files changed, 52 insertions(+), 3 deletions(-)
+
+Index: multipath-tools/libmultipath/config.h
+===================================================================
+--- multipath-tools.orig/libmultipath/config.h
++++ multipath-tools/libmultipath/config.h
+@@ -88,6 +88,7 @@ struct config {
+ 	unsigned int dev_loss;
+ 	int find_multipaths;
+ 	int allow_queueing;
++	int log_checker_err;
+ 	uid_t uid;
+ 	gid_t gid;
+ 	mode_t mode;
+Index: multipath-tools/libmultipath/dict.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dict.c
++++ multipath-tools/libmultipath/dict.c
+@@ -490,6 +490,25 @@ def_find_multipaths_handler(vector strve
+ }
+ 
+ static int
++def_log_checker_err_handler(vector strvec)
++{
++	char * buff;
++
++	buff = set_value(strvec);
++
++	if (!buff)
++		return 1;
++
++	if (strlen(buff) == 4 && !strcmp(buff, "once"))
++		conf->log_checker_err = LOG_CHKR_ERR_ONCE;
++	else if (strlen(buff) == 6 && !strcmp(buff, "always"))
++		conf->log_checker_err = LOG_CHKR_ERR_ALWAYS;
++
++	free(buff);
++	return 0;
++}
++
++static int
+ names_handler(vector strvec)
+ {
+ 	char * buff;
+@@ -2117,6 +2136,13 @@ snprint_def_find_multipaths (char * buff
+ 	return snprintf(buff, len, "yes");
+ }
+ 
++static int
++snprint_def_log_checker_err (char * buff, int len, void * data)
++{
++	if (conf->log_checker_err == LOG_CHKR_ERR_ONCE)
++		return snprintf(buff, len, "once");
++	return snprintf(buff, len, "always");
++}
+ 
+ static int
+ snprint_def_user_friendly_names (char * buff, int len, void * data)
+@@ -2184,6 +2210,7 @@ init_keywords(void)
+ 	install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail);
+ 	install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
+ 	install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);
++	install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err);
+ 	__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
+ 	__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
+ 	__deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL);
+Index: multipath-tools/libmultipath/structs.h
+===================================================================
+--- multipath-tools.orig/libmultipath/structs.h
++++ multipath-tools/libmultipath/structs.h
+@@ -88,6 +88,11 @@ enum flush_states {
+ 	FLUSH_IN_PROGRESS,
+ };
+ 
++enum log_checker_err_states {
++	LOG_CHKR_ERR_ALWAYS,
++	LOG_CHKR_ERR_ONCE,
++};
++
+ struct scsi_idlun {
+ 	int dev_id;
+ 	int host_unique_id;
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -63,7 +63,10 @@
+ #define CMDSIZE 160
+ 
+ #define LOG_MSG(a,b) \
+-	if (strlen(b)) condlog(a, "%s: %s - %s", pp->mpp->alias, pp->dev, b);
++do { \
++	if (strlen(b)) \
++	condlog(a, "%s: %s - %s", pp->mpp->alias, pp->dev, b); \
++} while(0)
+ 
+ pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER;
+ pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER;
+@@ -1090,8 +1093,12 @@ check_path (struct vectors * vecs, struc
+ 		condlog(4, "%s: delay next check %is",
+ 				pp->dev_t, pp->tick);
+ 	}
+-	else if (newstate == PATH_DOWN)
+-		LOG_MSG(2, checker_message(&pp->checker));
++	else if (newstate == PATH_DOWN) {
++		if (conf->log_checker_err == LOG_CHKR_ERR_ONCE)
++			LOG_MSG(3, checker_message(&pp->checker));
++		else
++			LOG_MSG(2, checker_message(&pp->checker));
++	}
+ 
+ 	pp->state = newstate;
+ 
+Index: multipath-tools/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools.orig/multipath/multipath.conf.5
++++ multipath-tools/multipath/multipath.conf.5
+@@ -333,6 +333,15 @@ numeric or symbolic uid; default determi
+ .B gid
+ The group id to use for the mutipath device nodes. You may use either the
+ numeric or symbolic gid; default determined by the process.
++.TP
++.B log_checker_err
++If set to
++.I once
++, multipathd logs the first path checker error at logging level 2. Any later
++errors are logged at level 3 until the device is restored. If set to
++.I always
++, multipathd always logs the path checker error at logging level 2. Default is
++.I always
+ .
+ .SH "blacklist section"
+ The
diff --git a/0076-RHBZ-599690-update-multipath-conf.patch b/0076-RHBZ-599690-update-multipath-conf.patch
new file mode 100644
index 0000000..8c41b72
--- /dev/null
+++ b/0076-RHBZ-599690-update-multipath-conf.patch
@@ -0,0 +1,18 @@
+---
+ multipath/multipath.conf.5 |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools.orig/multipath/multipath.conf.5
++++ multipath-tools/multipath/multipath.conf.5
+@@ -40,7 +40,8 @@ The following \fIsection\fP keywords are
+ .TP 17
+ .B defaults
+ This section defines default values for attributes which are used
+-whenever no specific setting is given.
++whenever no specific setting is given in the appropriate device or
++multipath sections.
+ .TP
+ .B blacklist
+ This section defines which devices should be excluded from the
diff --git a/0077-RHBZ-622608-nvdisk-config.patch b/0077-RHBZ-622608-nvdisk-config.patch
new file mode 100644
index 0000000..131b83f
--- /dev/null
+++ b/0077-RHBZ-622608-nvdisk-config.patch
@@ -0,0 +1,49 @@
+---
+ libmultipath/hwtable.c |   34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -766,6 +766,40 @@ static struct hwentry default_hw[] = {
+ 		.prio_args     = NULL,
+ 	},
+ 	{
++		/* IBM 3303      NVDISK */
++		.vendor        = "IBM",
++		.product       = "3303      NVDISK",
++		.getuid        = DEFAULT_GETUID,
++		.features      = DEFAULT_FEATURES,
++		.hwhandler     = DEFAULT_HWHANDLER,
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = FAILOVER,
++		.pgfailback    = -FAILBACK_IMMEDIATE,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = (300 / DEFAULT_CHECKINT),
++		.minio         = DEFAULT_MINIO,
++		.checker_name  = TUR,
++		.prio_name     = DEFAULT_PRIO,
++		.prio_args     = NULL,
++	},
++	{
++		/* AIX NVDISK */
++		.vendor        = "AIX",
++		.product       = "NVDISK",
++		.getuid        = DEFAULT_GETUID,
++		.features      = DEFAULT_FEATURES,
++		.hwhandler     = "1 alua",
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = GROUP_BY_PRIO,
++		.pgfailback    = -FAILBACK_IMMEDIATE,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = (300 / DEFAULT_CHECKINT),
++		.minio         = DEFAULT_MINIO,
++		.checker_name  = TUR,
++		.prio_name     = PRIO_ALUA,
++		.prio_args     = NULL,
++	},
++	{
+ 		/* DELL MD3000 */
+ 		.vendor        = "DELL",
+ 		.product       = "MD3000",
diff --git a/0078-RHBZ-628095-config-warnings.patch b/0078-RHBZ-628095-config-warnings.patch
new file mode 100644
index 0000000..06cb6ad
--- /dev/null
+++ b/0078-RHBZ-628095-config-warnings.patch
@@ -0,0 +1,248 @@
+---
+ libmultipath/dict.c   |   16 +++++------
+ libmultipath/parser.c |   69 +++++++++++++++++++++++++++++++++++++++++++++-----
+ libmultipath/parser.h |    9 ++++--
+ 3 files changed, 77 insertions(+), 17 deletions(-)
+
+Index: multipath-tools/libmultipath/dict.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dict.c
++++ multipath-tools/libmultipath/dict.c
+@@ -2218,17 +2218,17 @@ init_keywords(void)
+ 	__deprecated install_keyword("default_path_checker", &def_path_checker_handler, NULL);
+ 
+ 	install_keyword_root("blacklist", &blacklist_handler);
+-	install_keyword("devnode", &ble_devnode_handler, &snprint_ble_simple);
+-	install_keyword("wwid", &ble_wwid_handler, &snprint_ble_simple);
+-	install_keyword("device", &ble_device_handler, NULL);
++	install_keyword_multi("devnode", &ble_devnode_handler, &snprint_ble_simple);
++	install_keyword_multi("wwid", &ble_wwid_handler, &snprint_ble_simple);
++	install_keyword_multi("device", &ble_device_handler, NULL);
+ 	install_sublevel();
+ 	install_keyword("vendor", &ble_vendor_handler, &snprint_bled_vendor);
+ 	install_keyword("product", &ble_product_handler, &snprint_bled_product);
+ 	install_sublevel_end();
+ 	install_keyword_root("blacklist_exceptions", &blacklist_exceptions_handler);
+-	install_keyword("devnode", &ble_except_devnode_handler, &snprint_ble_simple);
+-	install_keyword("wwid", &ble_except_wwid_handler, &snprint_ble_simple);
+-	install_keyword("device", &ble_except_device_handler, NULL);
++	install_keyword_multi("devnode", &ble_except_devnode_handler, &snprint_ble_simple);
++	install_keyword_multi("wwid", &ble_except_wwid_handler, &snprint_ble_simple);
++	install_keyword_multi("device", &ble_except_device_handler, NULL);
+ 	install_sublevel();
+ 	install_keyword("vendor", &ble_except_vendor_handler, &snprint_bled_vendor);
+ 	install_keyword("product", &ble_except_product_handler, &snprint_bled_product);
+@@ -2246,7 +2246,7 @@ init_keywords(void)
+ #endif
+ 
+ 	install_keyword_root("devices", &devices_handler);
+-	install_keyword("device", &device_handler, NULL);
++	install_keyword_multi("device", &device_handler, NULL);
+ 	install_sublevel();
+ 	install_keyword("vendor", &vendor_handler, &snprint_hw_vendor);
+ 	install_keyword("product", &product_handler, &snprint_hw_product);
+@@ -2271,7 +2271,7 @@ init_keywords(void)
+ 	install_sublevel_end();
+ 
+ 	install_keyword_root("multipaths", &multipaths_handler);
+-	install_keyword("multipath", &multipath_handler, NULL);
++	install_keyword_multi("multipath", &multipath_handler, NULL);
+ 	install_sublevel();
+ 	install_keyword("wwid", &wwid_handler, &snprint_mp_wwid);
+ 	install_keyword("alias", &alias_handler, &snprint_mp_alias);
+Index: multipath-tools/libmultipath/parser.c
+===================================================================
+--- multipath-tools.orig/libmultipath/parser.c
++++ multipath-tools/libmultipath/parser.c
+@@ -21,11 +21,13 @@
+ 
+ #include "parser.h"
+ #include "memory.h"
++#include "debug.h"
+ 
+ /* local vars */
+ static int sublevel = 0;
+ vector keywords = NULL;
+ vector *keywords_addr = NULL;
++static int line_nr;
+ 
+ void set_current_keywords (vector *k)
+ {
+@@ -35,7 +37,7 @@ void set_current_keywords (vector *k)
+ 
+ int
+ keyword_alloc(vector keywords, char *string, int (*handler) (vector),
+-		int (*print) (char *, int, void *))
++		int (*print) (char *, int, void *), int unique)
+ {
+ 	struct keyword *keyword;
+ 
+@@ -51,6 +53,7 @@ keyword_alloc(vector keywords, char *str
+ 	keyword->string = string;
+ 	keyword->handler = handler;
+ 	keyword->print = print;
++	keyword->unique = unique;
+ 
+ 	vector_set_slot(keywords, keyword);
+ 
+@@ -60,7 +63,7 @@ keyword_alloc(vector keywords, char *str
+ int
+ install_keyword_root(char *string, int (*handler) (vector))
+ {
+-	int r = keyword_alloc(keywords, string, handler, NULL);
++	int r = keyword_alloc(keywords, string, handler, NULL, 1);
+ 	if (!r)
+ 		*keywords_addr = keywords;
+ 	return r;
+@@ -79,8 +82,8 @@ install_sublevel_end(void)
+ }
+ 
+ int
+-install_keyword(char *string, int (*handler) (vector),
+-		int (*print) (char *, int, void *))
++_install_keyword(char *string, int (*handler) (vector),
++		int (*print) (char *, int, void *), int unique)
+ {
+ 	int i = 0;
+ 	struct keyword *keyword;
+@@ -101,7 +104,7 @@ install_keyword(char *string, int (*hand
+ 		return 1;
+ 
+ 	/* add new sub keyword */
+-	return keyword_alloc(keyword->sub, string, handler, print);
++	return keyword_alloc(keyword->sub, string, handler, print, unique);
+ }
+ 
+ void
+@@ -419,6 +422,39 @@ set_value(vector strvec)
+ 
+ /* non-recursive configuration stream handler */
+ static int kw_level = 0;
++
++int warn_on_duplicates(vector uniques, char *str)
++{
++	char *tmp;
++	int i;
++
++	vector_foreach_slot(uniques, tmp, i) {
++		if (!strcmp(str, tmp)) {
++			condlog(1, "multipath.conf line %d, duplicate keyword: %s", line_nr, str);
++			return 0;
++		}
++	}
++	tmp = strdup(str);
++	if (!tmp)
++		return 1;
++	if (!vector_alloc_slot(uniques)) {
++		free(tmp);
++		return 1;
++	}
++	vector_set_slot(uniques, tmp);
++	return 0;
++}
++
++void free_uniques(vector uniques)
++{
++	char *tmp;
++	int i;
++
++	vector_foreach_slot(uniques, tmp, i)
++		free(tmp);
++	vector_free(uniques);
++}
++
+ int
+ process_stream(vector keywords)
+ {
+@@ -428,13 +464,21 @@ process_stream(vector keywords)
+ 	char *str;
+ 	char *buf;
+ 	vector strvec;
++	vector uniques;
++
++	uniques = vector_alloc();
++	if (!uniques)
++		return 1;
+ 
+ 	buf = MALLOC(MAXBUF);
+ 
+-	if (!buf)
++	if (!buf) {
++		vector_free(uniques);
+ 		return 1;
++	}
+ 
+ 	while (read_line(buf, MAXBUF)) {
++		line_nr++;
+ 		strvec = alloc_strvec(buf);
+ 		memset(buf,0, MAXBUF);
+ 
+@@ -452,6 +496,12 @@ process_stream(vector keywords)
+ 			keyword = VECTOR_SLOT(keywords, i);
+ 
+ 			if (!strcmp(keyword->string, str)) {
++				if (keyword->unique &&
++				    warn_on_duplicates(uniques, str)) {
++						r = 1;
++						free_strvec(strvec);
++						goto out;
++				}
+ 				if (keyword->handler)
+ 					r += (*keyword->handler) (strvec);
+ 
+@@ -463,11 +513,17 @@ process_stream(vector keywords)
+ 				break;
+ 			}
+ 		}
++		if (i >= VECTOR_SIZE(keywords))
++			condlog(1,
++				"multipath.conf line %d, invalid keyword: %s",
++				line_nr, str);
+ 
+ 		free_strvec(strvec);
+ 	}
+ 
++out:
+ 	FREE(buf);
++	free_uniques(uniques);
+ 	return r;
+ }
+ 
+@@ -496,6 +552,7 @@ init_data(char *conf_file, void (*init_k
+ */
+ 
+ 	/* Stream handling */
++	line_nr = 0;
+ 	r = process_stream(keywords);
+ 	fclose(stream);
+ 	//free_keywords(keywords);
+Index: multipath-tools/libmultipath/parser.h
+===================================================================
+--- multipath-tools.orig/libmultipath/parser.h
++++ multipath-tools/libmultipath/parser.h
+@@ -44,6 +44,7 @@ struct keyword {
+ 	int (*handler) (vector);
+ 	int (*print) (char *, int, void *);
+ 	vector sub;
++	int unique;
+ };
+ 
+ /* global var exported */
+@@ -60,12 +61,14 @@ FILE *stream;
+ 
+ /* Prototypes */
+ extern int keyword_alloc(vector keywords, char *string, int (*handler) (vector),
+-			 int (*print) (char *, int, void *));
++			 int (*print) (char *, int, void *), int unique);
+ extern int install_keyword_root(char *string, int (*handler) (vector));
+ extern void install_sublevel(void);
+ extern void install_sublevel_end(void);
+-extern int install_keyword(char *string, int (*handler) (vector),
+-			   int (*print) (char *, int, void *));
++extern int _install_keyword(char *string, int (*handler) (vector),
++			    int (*print) (char *, int, void *), int unique);
++#define install_keyword(str, vec, pri) _install_keyword(str, vec, pri, 1)
++#define install_keyword_multi(str, vec, pri) _install_keyword(str, vec, pri, 0)
+ extern void dump_keywords(vector keydump, int level);
+ extern void free_keywords(vector keywords);
+ extern vector alloc_strvec(char *string);
diff --git a/0079-RHBZ-650797-display-iscsi-tgt-name.patch b/0079-RHBZ-650797-display-iscsi-tgt-name.patch
new file mode 100644
index 0000000..f7e06de
--- /dev/null
+++ b/0079-RHBZ-650797-display-iscsi-tgt-name.patch
@@ -0,0 +1,55 @@
+---
+ libmultipath/discovery.c |   19 ++++++++++++++++++-
+ libmultipath/structs.h   |    2 +-
+ 2 files changed, 19 insertions(+), 2 deletions(-)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -212,6 +212,7 @@ sysfs_get_fc_nodename (struct sysfs_devi
+ 		       unsigned int host, unsigned int channel,
+ 		       unsigned int target)
+ {
++	unsigned int checkhost, session;
+ 	char attr_path[SYSFS_PATH_SIZE], *attr;
+ 
+ 	if (safe_sprintf(attr_path,
+@@ -223,7 +224,23 @@ sysfs_get_fc_nodename (struct sysfs_devi
+ 
+ 	attr = sysfs_attr_get_value(attr_path, "node_name");
+ 	if (attr) {
+-		strlcpy(node, attr, strlen(attr));
++		strncpy(node, attr, strlen(attr));
++		return 0;
++	}
++
++	if (sscanf(dev->devpath, "/devices/platform/host%u/session%u/",
++	    &checkhost, &session) != 2)
++		return 1;
++	if (checkhost != host)
++		return 1;
++	if (safe_sprintf(attr_path, "/devices/platform/host%u/session%u/iscsi_session/session%u", host, session, session)) {
++		condlog(0, "attr_path too small");
++		return 1;
++	}
++
++	attr = sysfs_attr_get_value(attr_path, "targetname");
++	if (attr) {
++		strncpy(node, attr, strlen(attr));
+ 		return 0;
+ 	}
+ 
+Index: multipath-tools/libmultipath/structs.h
+===================================================================
+--- multipath-tools.orig/libmultipath/structs.h
++++ multipath-tools/libmultipath/structs.h
+@@ -5,7 +5,7 @@
+ 
+ #define WWID_SIZE		128
+ #define SERIAL_SIZE		64
+-#define NODE_NAME_SIZE		19
++#define NODE_NAME_SIZE		224
+ #define PATH_STR_SIZE  		16
+ #define PARAMS_SIZE		1024
+ #define FILE_NAME_SIZE		256
diff --git a/0080-RHBZ-662731-fix-no-config-value-segfault.patch b/0080-RHBZ-662731-fix-no-config-value-segfault.patch
new file mode 100644
index 0000000..72189bc
--- /dev/null
+++ b/0080-RHBZ-662731-fix-no-config-value-segfault.patch
@@ -0,0 +1,31 @@
+---
+ libmultipath/parser.c |   11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+Index: multipath-tools/libmultipath/parser.c
+===================================================================
+--- multipath-tools.orig/libmultipath/parser.c
++++ multipath-tools/libmultipath/parser.c
+@@ -386,13 +386,20 @@ alloc_value_block(vector strvec, void (*
+ void *
+ set_value(vector strvec)
+ {
+-	char *str = VECTOR_SLOT(strvec, 1);
+-	int size = strlen(str);
++	char *str;
++	int size;
+ 	int i = 0;
+ 	int len = 0;
+ 	char *alloc = NULL;
+ 	char *tmp;
+ 
++	str = VECTOR_SLOT(strvec, 1);
++	if (!str) {
++		str = VECTOR_SLOT(strvec, 0);
++		condlog(0, "option '%s' missing value\n", str);
++		return NULL;
++	}
++	size = strlen(str);
+ 	if (*str == '"') {
+ 		for (i = 2; i < VECTOR_SIZE(strvec); i++) {
+ 			str = VECTOR_SLOT(strvec, i);
diff --git a/0081-RHBZ-623644-fix-sysfs-caching.patch b/0081-RHBZ-623644-fix-sysfs-caching.patch
new file mode 100644
index 0000000..b85f6c6
--- /dev/null
+++ b/0081-RHBZ-623644-fix-sysfs-caching.patch
@@ -0,0 +1,376 @@
+---
+ libmultipath/discovery.c |   50 ++++++---------------
+ libmultipath/sysfs.c     |  108 ++++++++++++++++++-----------------------------
+ libmultipath/sysfs.h     |    3 -
+ multipathd/main.c        |    7 +--
+ 4 files changed, 62 insertions(+), 106 deletions(-)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -129,13 +129,8 @@ path_discovery (vector pathvec, struct c
+ extern int \
+ sysfs_get_##fname (struct sysfs_device * dev, char * buff, size_t len) \
+ { \
+-	char *attr; \
+-\
+-	attr = sysfs_attr_get_value(dev->devpath, #fname); \
+-	if (!attr) \
++	if (sysfs_attr_get_value(dev->devpath, #fname, buff, len) != 0) \
+ 		return 1; \
+-	if (strlcpy(buff, attr, len) != strlen(attr)) \
+-		return 2; \
+ 	strchop(buff); \
+ 	return 0; \
+ }
+@@ -150,24 +145,17 @@ declare_sysfs_get_str(state);
+ int
+ sysfs_get_dev (struct sysfs_device * dev, char * buff, size_t len)
+ {
+-	char *attr;
+-
+-	attr = sysfs_attr_get_value(dev->devpath, "dev");
+-	if (!attr) {
++	if (sysfs_attr_get_value(dev->devpath, "dev", buff, len) != 0) {
+ 		condlog(3, "%s: no 'dev' attribute in sysfs", dev->kernel);
+ 		return 1;
+ 	}
+-	if (strlcpy(buff, attr, len) != strlen(attr)) {
+-		condlog(3, "%s: overflow in 'dev' attribute", dev->kernel);
+-		return 2;
+-	}
+ 	return 0;
+ }
+ 
+ int
+ sysfs_get_timeout(struct sysfs_device *dev, unsigned int *timeout)
+ {
+-	char *attr;
++	char buff[NAME_SIZE];
+ 	char attr_path[SYSFS_PATH_SIZE];
+ 	int r;
+ 	unsigned int t;
+@@ -175,11 +163,10 @@ sysfs_get_timeout(struct sysfs_device *d
+ 	if (safe_sprintf(attr_path, "%s/device", dev->devpath))
+ 		return 1;
+ 
+-	attr = sysfs_attr_get_value(attr_path, "timeout");
+-	if (!attr)
++	if (sysfs_attr_get_value(attr_path, "timeout", buff, NAME_SIZE) != 0)
+ 		return 1;
+ 
+-	r = sscanf(attr, "%u\n", &t);
++	r = sscanf(buff, "%u\n", &t);
+ 
+ 	if (r != 1)
+ 		return 1;
+@@ -192,14 +179,13 @@ sysfs_get_timeout(struct sysfs_device *d
+ int
+ sysfs_get_size (struct sysfs_device * dev, unsigned long long * size)
+ {
+-	char *attr;
++	char buff[NAME_SIZE];
+ 	int r;
+ 
+-	attr = sysfs_attr_get_value(dev->devpath, "size");
+-	if (!attr)
++	if (sysfs_attr_get_value(dev->devpath, "size", buff, NAME_SIZE) != 0)
+ 		return 1;
+ 
+-	r = sscanf(attr, "%llu\n", size);
++	r = sscanf(buff, "%llu\n", size);
+ 
+ 	if (r != 1)
+ 		return 1;
+@@ -213,7 +199,7 @@ sysfs_get_fc_nodename (struct sysfs_devi
+ 		       unsigned int target)
+ {
+ 	unsigned int checkhost, session;
+-	char attr_path[SYSFS_PATH_SIZE], *attr;
++	char attr_path[SYSFS_PATH_SIZE];
+ 
+ 	if (safe_sprintf(attr_path,
+ 			 "/class/fc_transport/target%i:%i:%i",
+@@ -222,11 +208,8 @@ sysfs_get_fc_nodename (struct sysfs_devi
+ 		return 1;
+ 	}
+ 
+-	attr = sysfs_attr_get_value(attr_path, "node_name");
+-	if (attr) {
+-		strncpy(node, attr, strlen(attr));
++	if (!sysfs_attr_get_value(attr_path, "node_name", node, NODE_NAME_SIZE))
+ 		return 0;
+-	}
+ 
+ 	if (sscanf(dev->devpath, "/devices/platform/host%u/session%u/",
+ 	    &checkhost, &session) != 2)
+@@ -238,11 +221,9 @@ sysfs_get_fc_nodename (struct sysfs_devi
+ 		return 1;
+ 	}
+ 
+-	attr = sysfs_attr_get_value(attr_path, "targetname");
+-	if (attr) {
+-		strncpy(node, attr, strlen(attr));
++	if (!sysfs_attr_get_value(attr_path, "targetname", node,
++				  NODE_NAME_SIZE))
+ 		return 0;
+-	}
+ 
+ 	return 1;
+ }
+@@ -670,14 +651,11 @@ cciss_sysfs_pathinfo (struct path * pp, 
+ static int
+ common_sysfs_pathinfo (struct path * pp, struct sysfs_device *dev)
+ {
+-	char *attr;
+-
+-	attr = sysfs_attr_get_value(dev->devpath, "dev");
+-	if (!attr) {
++	if (sysfs_attr_get_value(dev->devpath, "dev", pp->dev_t,
++				 BLK_DEV_SIZE) != 0) {
+ 		condlog(3, "%s: no 'dev' attribute in sysfs", pp->dev);
+ 		return 1;
+ 	}
+-	strlcpy(pp->dev_t, attr, BLK_DEV_SIZE);
+ 
+ 	condlog(3, "%s: dev_t = %s", pp->dev, pp->dev_t);
+ 
+Index: multipath-tools/libmultipath/sysfs.c
+===================================================================
+--- multipath-tools.orig/libmultipath/sysfs.c
++++ multipath-tools/libmultipath/sysfs.c
+@@ -37,15 +37,6 @@
+ 
+ char sysfs_path[PATH_SIZE];
+ 
+-/* attribute value cache */
+-static LIST_HEAD(attr_list);
+-struct sysfs_attr {
+-	struct list_head node;
+-	char path[PATH_SIZE];
+-	char *value;			/* points to value_local if value is cached */
+-	char value_local[NAME_SIZE];
+-};
+-
+ /* list of sysfs devices */
+ static LIST_HEAD(sysfs_dev_list);
+ struct sysfs_dev {
+@@ -62,24 +53,15 @@ int sysfs_init(char *path, size_t len)
+ 		strlcpy(sysfs_path, "/sys", sizeof(sysfs_path));
+ 	dbg("sysfs_path='%s'", sysfs_path);
+ 
+-	INIT_LIST_HEAD(&attr_list);
+ 	INIT_LIST_HEAD(&sysfs_dev_list);
+ 	return 0;
+ }
+ 
+ void sysfs_cleanup(void)
+ {
+-	struct sysfs_attr *attr_loop;
+-	struct sysfs_attr *attr_temp;
+-
+ 	struct sysfs_dev *sysdev_loop;
+ 	struct sysfs_dev *sysdev_temp;
+ 
+-	list_for_each_entry_safe(attr_loop, attr_temp, &attr_list, node) {
+-		list_del(&attr_loop->node);
+-		free(attr_loop);
+-	}
+-
+ 	list_for_each_entry_safe(sysdev_loop, sysdev_temp, &sysfs_dev_list, node) {
+ 		list_del(&sysdev_loop->node);
+ 		free(sysdev_loop);
+@@ -343,6 +325,8 @@ void sysfs_device_put(struct sysfs_devic
+ 
+ 	list_for_each_entry(sysdev_loop, &sysfs_dev_list, node) {
+ 		if (&sysdev_loop->dev == dev) {
++			if (dev->parent)
++				sysfs_device_put(dev->parent);
+ 			dbg("removed dev '%s' from cache",
+ 			    sysdev_loop->dev.devpath);
+ 			list_del(&sysdev_loop->node);
+@@ -350,8 +334,7 @@ void sysfs_device_put(struct sysfs_devic
+ 			return;
+ 		}
+ 	}
+-	dbg("dev '%s' not found in cache",
+-	    sysdev_loop->dev.devpath);
++	dbg("dev '%s' not found in cache", dev->devpath);
+ 
+ 	return;
+ }
+@@ -416,17 +399,24 @@ out:
+ }
+ 
+ 
+-char *sysfs_attr_get_value(const char *devpath, const char *attr_name)
++int sysfs_attr_get_value(const char *devpath, const char *attr_name,
++			 char *buff, int len)
+ {
+ 	char path_full[PATH_SIZE];
+ 	const char *path;
+ 	char value[NAME_SIZE];
+-	struct sysfs_attr *attr_loop;
+-	struct sysfs_attr *attr = NULL;
+ 	struct stat statbuf;
+ 	int fd;
+ 	ssize_t size;
+ 	size_t sysfs_len;
++	int ret = -1;
++
++	if (buff == NULL) {
++		condlog(0, "no space to store sysfs attr value '%s'",
++			attr_name);
++		goto out;
++	}
++	memset(buff, 0, len);
+ 
+ 	dbg("open '%s'/'%s'", devpath, attr_name);
+ 	sysfs_len = strlcpy(path_full, sysfs_path, sizeof(path_full));
+@@ -437,29 +427,6 @@ char *sysfs_attr_get_value(const char *d
+ 	strlcat(path_full, "/", sizeof(path_full));
+ 	strlcat(path_full, attr_name, sizeof(path_full));
+ 
+-	/* look for attribute in cache */
+-	list_for_each_entry(attr_loop, &attr_list, node) {
+-		if (strcmp(attr_loop->path, path) == 0) {
+-			dbg("found in cache '%s'", attr_loop->path);
+-			attr = attr_loop;
+-		}
+-	}
+-	if (!attr) {
+-		/* store attribute in cache */
+-		dbg("new uncached attribute '%s'", path_full);
+-		attr = malloc(sizeof(struct sysfs_attr));
+-		if (attr == NULL)
+-			return NULL;
+-		memset(attr, 0x00, sizeof(struct sysfs_attr));
+-		strlcpy(attr->path, path, sizeof(attr->path));
+-		dbg("add to cache '%s'", path_full);
+-		list_add(&attr->node, &attr_list);
+-	} else {
+-		/* clear old value */
+-		if(attr->value)
+-			memset(attr->value, 0x00, sizeof(attr->value));
+-	}
+-
+ 	if (lstat(path_full, &statbuf) != 0) {
+ 		dbg("stat '%s' failed: %s", path_full, strerror(errno));
+ 		goto out;
+@@ -467,20 +434,27 @@ char *sysfs_attr_get_value(const char *d
+ 
+ 	if (S_ISLNK(statbuf.st_mode)) {
+ 		/* links return the last element of the target path */
+-		char link_target[PATH_SIZE];
+-		int len;
++		int link_len;
+ 		const char *pos;
+ 
+-		len = readlink(path_full, link_target, sizeof(link_target));
+-		if (len > 0) {
+-			link_target[len] = '\0';
+-			pos = strrchr(link_target, '/');
++		link_len = readlink(path_full, value, sizeof(value));
++		if (link_len > 0) {
++			if (link_len >= sizeof(value)) {
++				condlog(0, "overflow in attribute '%s'",
++					path_full);
++				goto out;
++			}
++			value[link_len] = '\0';
++			pos = strrchr(value, '/');
+ 			if (pos != NULL) {
+-				dbg("cache '%s' with link value '%s'",
+-				    path_full, value);
+-				strlcpy(attr->value_local, &pos[1],
+-					sizeof(attr->value_local));
+-				attr->value = attr->value_local;
++				pos++;
++				if (strlen(pos) >= len) {
++					condlog(0, "overflow in attribute '%s'",
++						path_full);
++					goto out;
++				}
++				strncpy(buff, pos, len - 1);
++				ret = 0;
+ 			}
+ 		}
+ 		goto out;
+@@ -498,9 +472,9 @@ char *sysfs_attr_get_value(const char *d
+ 	fd = open(path_full, O_RDONLY);
+ 	if (fd < 0) {
+ 		if (errno == EMFILE)
+-			dbg("out of file descriptors. set or increase max_fds in /etc/multipath.conf");
++			condlog(0, "out of file descriptors. set or increase max_fds in /etc/multipath.conf");
+ 		else
+-			dbg("attribute '%s' can not be opened: %s",
++			condlog(0, "attribute '%s' can not be opened: %s",
+ 			    path_full, strerror(errno));
+ 		goto out;
+ 	}
+@@ -512,16 +486,18 @@ char *sysfs_attr_get_value(const char *d
+ 		dbg("overflow in attribute '%s', truncating", path_full);
+ 		size--;
+ 	}
+-
+-	/* got a valid value, store and return it */
+ 	value[size] = '\0';
+ 	remove_trailing_chars(value, '\n');
+-	dbg("cache '%s' with attribute value '%s'", path_full, value);
+-	strlcpy(attr->value_local, value, sizeof(attr->value_local));
+-	attr->value = attr->value_local;
+-
++	strchop(value);
++	if (strlen(value) >= len) {
++		condlog(0, "overflow in attribute '%s'", path_full);
++		goto out;
++	}
++	strncpy(buff, value, len - 1);
++	/* got a valid value, store and return it */
++	ret = 0;
+ out:
+-	return attr && attr->value && strlen(attr->value) ? attr->value : NULL;
++	return ret;
+ }
+ 
+ int sysfs_lookup_devpath_by_subsys_id(char *devpath_full, size_t len,
+Index: multipath-tools/libmultipath/sysfs.h
+===================================================================
+--- multipath-tools.orig/libmultipath/sysfs.h
++++ multipath-tools/libmultipath/sysfs.h
+@@ -19,7 +19,8 @@ struct sysfs_device *sysfs_device_get(co
+ struct sysfs_device *sysfs_device_get_parent(struct sysfs_device *dev);
+ struct sysfs_device *sysfs_device_get_parent_with_subsystem(struct sysfs_device *dev, const char *subsystem);
+ void sysfs_device_put(struct sysfs_device *dev);
+-char *sysfs_attr_get_value(const char *devpath, const char *attr_name);
++int sysfs_attr_get_value(const char *devpath, const char *attr_name,
++			 char *buff, int len);
+ int sysfs_resolve_link(char *path, size_t size);
+ int sysfs_get_size (struct sysfs_device * dev, unsigned long long * size);
+ int sysfs_attr_set_value(const char *devpath, const char *attr_name,
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -228,16 +228,17 @@ int
+ ev_add_map (struct sysfs_device * dev, struct vectors * vecs)
+ {
+ 	char * alias;
+-	char *dev_t;
++	char dev_t[BLK_DEV_SIZE];
+ 	int major, minor;
+ 	char * refwwid;
+ 	struct multipath * mpp;
+ 	int map_present;
+ 	int r = 1;
+ 
+-	dev_t = sysfs_attr_get_value(dev->devpath, "dev");
++	if (sysfs_attr_get_value(dev->devpath, "dev", dev_t, BLK_DEV_SIZE) != 0)
++		return 1;
+ 
+-	if (!dev_t || sscanf(dev_t, "%d:%d", &major, &minor) != 2)
++	if (sscanf(dev_t, "%d:%d", &major, &minor) != 2)
+ 		return 1;
+ 
+ 	alias = dm_mapname(major, minor);
diff --git a/0083-RHBZ-636213-633643-new-configs.patch b/0083-RHBZ-636213-633643-new-configs.patch
new file mode 100644
index 0000000..6f81a18
--- /dev/null
+++ b/0083-RHBZ-636213-633643-new-configs.patch
@@ -0,0 +1,99 @@
+---
+ libmultipath/hwtable.c  |   32 ++++++++++++++++++++++++++++++++
+ multipath.conf.defaults |   28 ++++++++++++++++++++++++++++
+ 2 files changed, 60 insertions(+)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -239,6 +239,22 @@ static struct hwentry default_hw[] = {
+ 		.checker_name  = TUR,
+ 		.prio_name     = DEFAULT_PRIO,
+ 	},
++	{
++		/* HP P2000 family arrays */
++		.vendor        = "HP",
++		.product       = "P2000 G3 FC|P2000G3 FC/iSCSI|P2000 G3 SAS|P2000 G3 iSCSI",
++		.getuid        = DEFAULT_GETUID,
++		.features      = DEFAULT_FEATURES,
++		.hwhandler     = DEFAULT_HWHANDLER,
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = GROUP_BY_PRIO,
++		.pgfailback    = -FAILBACK_IMMEDIATE,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = 18,
++		.minio         = 100,
++		.checker_name  = TUR,
++		.prio_name     = PRIO_ALUA,
++	},
+ 	/*
+ 	 * DDN controller family
+ 	 *
+@@ -1118,6 +1134,22 @@ static struct hwentry default_hw[] = {
+ 		.checker_name  = DEFAULT_CHECKER,
+ 		.prio_name     = DEFAULT_PRIO,
+ 	},
++	/* NEC Storage M Series */
++	{
++		.vendor        = "NEC",
++		.product       = "DISK ARRAY",
++		.getuid        = DEFAULT_GETUID,
++		.features      = DEFAULT_FEATURES,
++		.hwhandler     = "1 alua",
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = GROUP_BY_PRIO,
++		.pgfailback    = -FAILBACK_IMMEDIATE,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = NO_PATH_RETRY_UNDEF,
++		.minio         = DEFAULT_MINIO,
++		.checker_name  = TUR,
++		.prio_name     = PRIO_ALUA,
++	},
+ 	/*
+ 	 * EOL
+ 	 */
+Index: multipath-tools/multipath.conf.defaults
+===================================================================
+--- multipath-tools.orig/multipath.conf.defaults
++++ multipath-tools/multipath.conf.defaults
+@@ -180,6 +180,20 @@
+ #		prio			const
+ #	}
+ #	device {
++#		vendor			"HP"
++#		product			"P2000 G3 FC|P2000G3 FC/iSCSI|P2000 G3 SAS|P2000 G3 iSCS"
++#		getuid_callout		"/lib/udev/scsi_id --whitelisted --device=/dev/%n"
++#		features		"0"
++#		hardware_handler	"0"
++#		path_selector		"round-robin 0"
++#		path_grouping_policy	group_by_prio
++#		rr_weight		uniform
++#		no_path_retry		18
++#		rr_min_io		100
++#		path_checker		tur
++#		prio			alua
++#	}
++#	device {
+ #		vendor			"DDN"
+ #		product			"SAN DataDirector"
+ #		getuid_callout		"/lib/udev/scsi_id --whitelisted --device=/dev/%n"
+@@ -659,4 +673,18 @@
+ #		path_checker		directio
+ #		prio			const
+ #	}
++#	device {
++#		vendor                  "NEC"
++#		product                 "DISK ARRAY"
++#		getuid_callout          "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
++#		features                "0"
++#		hardware_handler        "1 alua"
++#		path_selector           "round-robin 0"
++#		path_grouping_policy    group_by_prio
++#		failback                immediate
++#		rr_weight               uniform
++#		rr_min_io               1000
++#		path_checker            tur
++#		prio                    alua
++#	}
+ #}
diff --git a/0084-RHBZ-644111-read-only-bindings.patch b/0084-RHBZ-644111-read-only-bindings.patch
new file mode 100644
index 0000000..23fce2a
--- /dev/null
+++ b/0084-RHBZ-644111-read-only-bindings.patch
@@ -0,0 +1,160 @@
+From c2f3abecdb76c4e7b3ec3aa418625b4f1b942496 Mon Sep 17 00:00:00 2001
+From: Malahal Naineni <malahal at us.ibm.com>
+Date: Mon, 16 Aug 2010 15:57:02 -0700
+Subject: [PATCH] option to multipath to not modify the bindinfs file
+
+initramfs is mounted read-write causing multipath to update the
+initramfs bindings file and name all multipath devices it finds using
+friendly names. The actual changes to the file are thrown away as they
+are only written to the memory image rather than to the disk image. This
+may cause the in memory updated initramfs bindings file inconsistent
+with the actual bindings file in the active root file system image when
+devices are added or removed.
+
+In other words, the boot time updated initramfs bindings file may have
+'uuid1 map to mpatha' and 'uuid2 map to mpathb', but the active root fs
+bindings file may have 'uuid1 map to mpathb' and 'uuid2 map to mpatha'
+
+The option, -B, will not modify the bindings file. It will only use the
+bindings file if needed.  This option to multipath should be used when
+invoked in the initramfs context to avoid the inconsistency.
+
+Signed-off-by: Malahal Naineni (malahal at us.ibm.com)
+---
+ libmultipath/alias.c   |    4 ++--
+ libmultipath/alias.h   |    2 +-
+ libmultipath/config.h  |    1 +
+ libmultipath/propsel.c |    3 ++-
+ multipath/main.c       |    5 ++++-
+ multipath/multipath.8  |    5 ++++-
+ multipathd/main.c      |    5 ++++-
+ 7 files changed, 18 insertions(+), 7 deletions(-)
+
+Index: multipath-tools/libmultipath/alias.c
+===================================================================
+--- multipath-tools.orig/libmultipath/alias.c
++++ multipath-tools/libmultipath/alias.c
+@@ -206,7 +206,7 @@ allocate_binding(int fd, char *wwid, int
+ }
+ 
+ char *
+-get_user_friendly_alias(char *wwid, char *file)
++get_user_friendly_alias(char *wwid, char *file, int bindings_read_only)
+ {
+ 	char *alias;
+ 	int fd, scan_fd, id;
+@@ -250,7 +250,7 @@ get_user_friendly_alias(char *wwid, char
+ 		return NULL;
+ 	}
+ 
+-	if (!alias && can_write)
++	if (!alias && can_write && !bindings_read_only)
+ 		alias = allocate_binding(fd, wwid, id);
+ 
+ 	fclose(f);
+Index: multipath-tools/libmultipath/alias.h
+===================================================================
+--- multipath-tools.orig/libmultipath/alias.h
++++ multipath-tools/libmultipath/alias.h
+@@ -7,5 +7,5 @@
+ "# alias wwid\n" \
+ "#\n"
+ 
+-char *get_user_friendly_alias(char *wwid, char *file);
++char *get_user_friendly_alias(char *wwid, char *file, int bindings_readonly);
+ char *get_user_friendly_wwid(char *alias, char *file);
+Index: multipath-tools/libmultipath/config.h
+===================================================================
+--- multipath-tools.orig/libmultipath/config.h
++++ multipath-tools/libmultipath/config.h
+@@ -76,6 +76,7 @@ struct config {
+ 	int rr_weight;
+ 	int no_path_retry;
+ 	int user_friendly_names;
++	int bindings_read_only;
+ 	int pg_timeout;
+ 	int max_fds;
+ 	int force_reload;
+Index: multipath-tools/libmultipath/propsel.c
+===================================================================
+--- multipath-tools.orig/libmultipath/propsel.c
++++ multipath-tools/libmultipath/propsel.c
+@@ -219,7 +219,8 @@ select_alias (struct multipath * mp)
+ 		mp->alias = NULL;
+ 		if (conf->user_friendly_names)
+ 			mp->alias = get_user_friendly_alias(mp->wwid,
+-					conf->bindings_file);
++					conf->bindings_file,
++					conf->bindings_read_only);
+ 		if (mp->alias == NULL){
+ 			char *alias;
+ 			if ((alias = MALLOC(WWID_SIZE)) != NULL){
+Index: multipath-tools/multipath/main.c
+===================================================================
+--- multipath-tools.orig/multipath/main.c
++++ multipath-tools/multipath/main.c
+@@ -383,7 +383,7 @@ main (int argc, char *argv[])
+ 		condlog(0, "multipath tools need sysfs mounted");
+ 		exit(1);
+ 	}
+-	while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:rq")) != EOF ) {
++	while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:Brq")) != EOF ) {
+ 		switch(arg) {
+ 		case 1: printf("optarg : %s\n",optarg);
+ 			break;
+@@ -403,6 +403,9 @@ main (int argc, char *argv[])
+ 		case 'q':
+ 			conf->allow_queueing = 1;
+ 			break;
++		case 'B':
++			conf->bindings_read_only = 1;
++			break;
+ 		case 'd':
+ 			if (!conf->dry_run)
+ 				conf->dry_run = 1;
+Index: multipath-tools/multipath/multipath.8
+===================================================================
+--- multipath-tools.orig/multipath/multipath.8
++++ multipath-tools/multipath/multipath.8
+@@ -6,7 +6,7 @@ multipath \- Device mapper target autoco
+ .RB [\| \-v\ \c
+ .IR verbosity \|]
+ .RB [\| \-d \|]
+-.RB [\| \-h | \-l | \-ll | \-f | \-F \|]
++.RB [\| \-h | \-l | \-ll | \-f | \-F | \-B \|]
+ .RB [\| \-p\ \c
+ .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|]
+ .RB [\| device \|]
+@@ -47,6 +47,9 @@ flush a multipath device map specified a
+ .B \-F
+ flush all unused multipath device maps
+ .TP
++.B \-B
++treat the bindings file as read only
++.TP
+ .BI \-p " policy"
+ force maps to specified policy:
+ .RS 1.2i
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -1640,7 +1640,7 @@ main (int argc, char *argv[])
+ 	if (!conf)
+ 		exit(1);
+ 
+-	while ((arg = getopt(argc, argv, ":dv:k::")) != EOF ) {
++	while ((arg = getopt(argc, argv, ":dv:k::B")) != EOF ) {
+ 	switch(arg) {
+ 		case 'd':
+ 			logsink = 0;
+@@ -1653,6 +1653,9 @@ main (int argc, char *argv[])
+ 
+ 			conf->verbosity = atoi(optarg);
+ 			break;
++		case 'B':
++			conf->bindings_read_only = 1;
++			break;
+ 		case 'k':
+ 			uxclnt(optarg);
+ 			exit(0);
diff --git a/0085-RHBZ-645605-fix-offline-check.patch b/0085-RHBZ-645605-fix-offline-check.patch
new file mode 100644
index 0000000..7ae7e8c
--- /dev/null
+++ b/0085-RHBZ-645605-fix-offline-check.patch
@@ -0,0 +1,17 @@
+---
+ libmultipath/discovery.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -711,7 +711,7 @@ path_offline (struct path * pp)
+ 	char buff[SCSI_STATE_SIZE];
+ 
+ 	if (path_state(pp, buff))
+-		return 1;
++		return 0;
+ 
+ 	if (!strncmp(buff, "offline", 7)) {
+ 		pp->offline = 1;
diff --git a/0086-RHBZ-681144-sysfs-device-cleanup.patch b/0086-RHBZ-681144-sysfs-device-cleanup.patch
new file mode 100644
index 0000000..3158892
--- /dev/null
+++ b/0086-RHBZ-681144-sysfs-device-cleanup.patch
@@ -0,0 +1,92 @@
+---
+ multipathd/cli_handlers.c |    2 +-
+ multipathd/main.c         |   20 +++++++++++++-------
+ multipathd/main.h         |    2 +-
+ 3 files changed, 15 insertions(+), 9 deletions(-)
+
+Index: multipath-tools/multipathd/cli_handlers.c
+===================================================================
+--- multipath-tools.orig/multipathd/cli_handlers.c
++++ multipath-tools/multipathd/cli_handlers.c
+@@ -416,7 +416,7 @@ cli_del_path (void * v, char ** reply, i
+ 
+ 	condlog(2, "%s: remove path (operator)", param);
+ 
+-	return ev_remove_path(param, vecs);
++	return ev_remove_path(param, vecs, NULL);
+ }
+ 
+ int
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -496,23 +496,25 @@ fail:
+ static int
+ uev_remove_path (struct sysfs_device * dev, struct vectors * vecs)
+ {
+-	int retval;
++	int retval, del_sysdev;
+ 
+ 	condlog(2, "%s: remove path (uevent)", dev->kernel);
+-	retval = ev_remove_path(dev->kernel, vecs);
+-	if (!retval)
++	retval = ev_remove_path(dev->kernel, vecs, &del_sysdev);
++	if (del_sysdev)
+ 		sysfs_device_put(dev);
+ 
+ 	return retval;
+ }
+ 
+ int
+-ev_remove_path (char * devname, struct vectors * vecs)
++ev_remove_path (char * devname, struct vectors * vecs, int *del_sysdev)
+ {
+ 	struct multipath * mpp;
+ 	struct path * pp;
+ 	int i, retval = 0;
+ 
++	if (del_sysdev)
++		*del_sysdev = 0;
+ 	pp = find_path_by_dev(vecs->pathvec, devname);
+ 
+ 	if (!pp) {
+@@ -599,6 +601,10 @@ out:
+ 	if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1)
+ 		vector_del_slot(vecs->pathvec, i);
+ 
++	if (pp->sysdev)
++		sysfs_device_put(pp->sysdev);
++	else if (del_sysdev)
++		*del_sysdev = 1;
+ 	free_path(pp);
+ 
+ 	return retval;
+@@ -689,11 +695,11 @@ uev_trigger (struct uevent * uev, void *
+ 	if (uev_discard(uev->devpath))
+ 		return 0;
+ 
++	lock(vecs->lock);
++
+ 	sysdev = sysfs_device_get(uev->devpath);
+ 	if(!sysdev)
+-		return 0;
+-
+-	lock(vecs->lock);
++		goto out;
+ 
+ 	/*
+ 	 * device map event
+Index: multipath-tools/multipathd/main.h
+===================================================================
+--- multipath-tools.orig/multipathd/main.h
++++ multipath-tools/multipathd/main.h
+@@ -5,7 +5,7 @@
+ 
+ int reconfigure (struct vectors *);
+ int ev_add_path (char *, struct vectors *);
+-int ev_remove_path (char *, struct vectors *);
++int ev_remove_path (char *, struct vectors *, int *);
+ int ev_add_map (struct sysfs_device *, struct vectors *);
+ int ev_remove_map (char *, struct vectors *);
+ void sync_map_state (struct multipath *);
diff --git a/0087-RHBZ-680480-skip-if-no-sysdev.patch b/0087-RHBZ-680480-skip-if-no-sysdev.patch
new file mode 100644
index 0000000..f076c0e
--- /dev/null
+++ b/0087-RHBZ-680480-skip-if-no-sysdev.patch
@@ -0,0 +1,19 @@
+---
+ libmultipath/discovery.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -859,6 +859,10 @@ get_state (struct path * pp, int daemon)
+ 			return PATH_PENDING;
+ 		checker_set_async(c);
+ 	}
++	if (!pp->sysdev) {
++		condlog(2, "%s: no sysfs information", pp->dev);
++		return PATH_DOWN;
++	}
+ 	if (!conf->checker_timeout)
+ 		sysfs_get_timeout(pp->sysdev, &(c->timeout));
+ 	state = checker_check(c);
diff --git a/0088-RHBZ-693524-fix-prio-segfault.patch b/0088-RHBZ-693524-fix-prio-segfault.patch
new file mode 100644
index 0000000..b0357aa
--- /dev/null
+++ b/0088-RHBZ-693524-fix-prio-segfault.patch
@@ -0,0 +1,29 @@
+---
+ multipathd/main.c |    9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -957,15 +957,16 @@ retry_count_tick(vector mpvec)
+ int update_prio(struct path *pp, int refresh_all)
+ {
+ 	int oldpriority;
++	struct path *pp1;
+ 	struct pathgroup * pgp;
+ 	int i, j, changed = 0;
+ 
+ 	if (refresh_all) {
+ 		vector_foreach_slot (pp->mpp->pg, pgp, i) {
+-			vector_foreach_slot (pgp->paths, pp, j) {
+-				oldpriority = pp->priority;
+-				pathinfo(pp, conf->hwtable, DI_PRIO);
+-				if (pp->priority != oldpriority)
++			vector_foreach_slot (pgp->paths, pp1, j) {
++				oldpriority = pp1->priority;
++				pathinfo(pp1, conf->hwtable, DI_PRIO);
++				if (pp1->priority != oldpriority)
+ 					changed = 1;
+ 			}
+ 		}
diff --git a/0089-RHBZ-694602-RSSM-config.patch b/0089-RHBZ-694602-RSSM-config.patch
new file mode 100644
index 0000000..5432320
--- /dev/null
+++ b/0089-RHBZ-694602-RSSM-config.patch
@@ -0,0 +1,58 @@
+---
+ libmultipath/hwtable.c  |   16 ++++++++++++++++
+ multipath.conf.defaults |   15 +++++++++++++++
+ 2 files changed, 31 insertions(+)
+
+Index: multipath-tools/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools.orig/libmultipath/hwtable.c
++++ multipath-tools/libmultipath/hwtable.c
+@@ -725,6 +725,22 @@ static struct hwentry default_hw[] = {
+ 		.checker_name  = TUR,
+ 		.prio_name     = PRIO_ALUA,
+ 	},
++	{
++		/* IBM RSSM */
++		.vendor        = "IBM",
++		.product       = "1820N00",
++		.getuid        = DEFAULT_GETUID,
++		.features      = DEFAULT_FEATURES,
++		.hwhandler     = DEFAULT_HWHANDLER,
++		.selector      = DEFAULT_SELECTOR,
++		.pgpolicy      = GROUP_BY_PRIO,
++		.pgfailback    = -FAILBACK_IMMEDIATE,
++		.rr_weight     = RR_WEIGHT_NONE,
++		.no_path_retry = NO_PATH_RETRY_QUEUE,
++		.minio         = 100,
++		.checker_name  = TUR,
++		.prio_name     = PRIO_ALUA,
++	},
+ 	/*
+ 	 * IBM Power Virtual SCSI Devices
+ 	 *
+Index: multipath-tools/multipath.conf.defaults
+===================================================================
+--- multipath-tools.orig/multipath.conf.defaults
++++ multipath-tools/multipath.conf.defaults
+@@ -491,6 +491,21 @@
+ #		prio			ontap
+ #	}
+ #	device {
++#	        vendor                  "IBM"
++#	        product                 "1820N00"
++#	        getuid_callout          "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
++#	        features		"0"
++#	        hardware_handler        "0"
++#	        path_selector           "round-robin 0"
++#	        path_grouping_policy    group_by_prio
++#	        failback                immediate
++#	        rr_weight               uniform
++#	        rr_min_io               100
++#	        path_checker            tur
++#	        prio                    alua
++#	        no_path_retry           queue
++#       }
++#	device {
+ #		vendor			"Pillar"
+ #		product			"Axiom.*"
+ #		getuid_callout		"/lib/udev/scsi_id --whitelisted --device=/dev/%n"
diff --git a/0090-RHBZ-700169-fix-nr-active.patch b/0090-RHBZ-700169-fix-nr-active.patch
new file mode 100644
index 0000000..ee93e1a
--- /dev/null
+++ b/0090-RHBZ-700169-fix-nr-active.patch
@@ -0,0 +1,17 @@
+---
+ libmultipath/configure.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/configure.c
+===================================================================
+--- multipath-tools.orig/libmultipath/configure.c
++++ multipath-tools/libmultipath/configure.c
+@@ -90,7 +90,7 @@ setup_map (struct multipath * mpp)
+ 	if (mpp->pgpolicyfn && mpp->pgpolicyfn(mpp))
+ 		return 1;
+ 
+-	mpp->nr_active = pathcount(mpp, PATH_UP);
++	mpp->nr_active = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
+ 
+ 	/*
+ 	 * ponders each path group and determine highest prio pg
diff --git a/0091-RHBZ-699577-manpage-clarification.patch b/0091-RHBZ-699577-manpage-clarification.patch
new file mode 100644
index 0000000..a1143b9
--- /dev/null
+++ b/0091-RHBZ-699577-manpage-clarification.patch
@@ -0,0 +1,51 @@
+---
+ multipath/multipath.conf.5 |   26 +++++++++++++++++++-------
+ 1 file changed, 19 insertions(+), 7 deletions(-)
+
+Index: multipath-tools/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools.orig/multipath/multipath.conf.5
++++ multipath-tools/multipath/multipath.conf.5
+@@ -39,9 +39,8 @@ section in which they occor.
+ The following \fIsection\fP keywords are recognized:
+ .TP 17
+ .B defaults
+-This section defines default values for attributes which are used
+-whenever no specific setting is given in the appropriate device or
+-multipath sections.
++This section defines default settings for devices-mapper-multipath. These
++values can be overwritten by the devices and multipaths sections.
+ .TP
+ .B blacklist
+ This section defines which devices should be excluded from the
+@@ -54,13 +53,26 @@ multipath topology discovery, despite be
+ section.
+ .TP
+ .B multipaths
+-This section defines the multipath topologies. They are indexed by a
+-\fIWorld Wide Identifier\fR(wwid), which is the result of the
+-\fIgetuid_callout\fR program.
++This section defines the settings for individual multipath devices.
++These values overwrite what is specified in the defaults and devices
++section of the configuration file.
++The devices are identified by the \fIwwid\fR keyword, which is a regular
++expression that must match the result of the \fIgetuid_callout\fR program.
+ .TP
+ .B devices
+-This section defines the device-specific settings.
++This section defines the settings for individual storage controller types.
++These value overwrite what is specified in the defaults section of the
++configuration file.
++These controller types are identified by the \fIvendor\fR, \fIproduct\fR, and
++\fIrevision\fR keywords, which are regular expressions that must match the
++sysfs information about this device.
++If you are using a storage array that is not supported by default, you may need
++to create a devices subsection for your array.
+ .RE
++.P
++The priority of configuration in multipath.conf is:
++.br
++\fImultipaths\fR is greater than \fIdevices\fR is greater that \fIdefaults\fR
+ .LP
+ .SH "defaults section"
+ The
diff --git a/0092-RHBZ-689504-rdac-retry.patch b/0092-RHBZ-689504-rdac-retry.patch
new file mode 100644
index 0000000..f10eeae
--- /dev/null
+++ b/0092-RHBZ-689504-rdac-retry.patch
@@ -0,0 +1,64 @@
+From patchwork Tue Mar  1 19:08:24 2011
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: multipath: Retry host transient errors for rdac checker
+Date: Tue, 01 Mar 2011 19:08:24 -0000
+From: Moger, Babu <Babu.Moger at lsi.com>
+X-Patchwork-Id: 600411
+Message-Id: <E463DF2B2E584B4A82673F53D62C2EF4FF7DC637 at cosmail01.lsi.com>
+To: "dm-devel at redhat.com" <dm-devel at redhat.com>
+
+Sometimes if the host is in transient state, we need to wait till the devloss timeout to
+expire before switching path group. We have seen in some cases path group switch happens
+even before the devloss timeout expire. This patch fixes the problem for rdac checker..
+
+Signed-off-by: Babu Moger <babu.moger at lsi.com>
+
+---
+--
+dm-devel mailing list
+dm-devel at redhat.com
+https://www.redhat.com/mailman/listinfo/dm-devel
+
+---
+ libmultipath/checkers/rdac.c |   18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+Index: multipath-tools/libmultipath/checkers/rdac.c
+===================================================================
+--- multipath-tools.orig/libmultipath/checkers/rdac.c
++++ multipath-tools/libmultipath/checkers/rdac.c
+@@ -48,7 +48,9 @@ do_inq(int sg_fd, unsigned int pg_op, vo
+ 	unsigned char inqCmdBlk[INQUIRY_CMDLEN] = { INQUIRY_CMD, 1, 0, 0, 0, 0 };
+ 	unsigned char sense_b[SENSE_BUFF_LEN];
+ 	struct sg_io_hdr io_hdr;
++	int retry_rdac = 5;
+ 
++retry:
+ 	inqCmdBlk[2] = (unsigned char) pg_op;
+ 	inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff);
+ 	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
+@@ -72,6 +74,22 @@ do_inq(int sg_fd, unsigned int pg_op, vo
+ 	if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
+ 	    (0 == io_hdr.driver_status))
+ 		return 0;
++
++	/* check if we need to retry this error */
++	if (io_hdr.info & SG_INFO_OK_MASK) {
++		switch (io_hdr.host_status) {
++		case DID_BUS_BUSY:
++		case DID_ERROR:
++		case DID_TRANSPORT_DISRUPTED:
++			/* Transport error, retry */
++			if (--retry_rdac)
++				goto retry;
++			break;
++		default:
++			break;
++		}
++	}
++
+ 	if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
+ 	    (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
+ 	    (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
diff --git a/0093-RHBZ-677449-dont-remove-map-on-enomem.patch b/0093-RHBZ-677449-dont-remove-map-on-enomem.patch
new file mode 100644
index 0000000..bf8e76c
--- /dev/null
+++ b/0093-RHBZ-677449-dont-remove-map-on-enomem.patch
@@ -0,0 +1,18 @@
+---
+ multipathd/main.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -883,7 +883,8 @@ mpvec_garbage_collector (struct vectors 
+ 		return;
+ 
+ 	vector_foreach_slot (vecs->mpvec, mpp, i) {
+-		if (mpp && mpp->alias && !dm_map_present(mpp->alias)) {
++		if (mpp && mpp->alias && !dm_map_present(mpp->alias) &&
++		    errno != ENOMEM) {
+ 			condlog(2, "%s: remove dead map", mpp->alias);
+ 			remove_map_and_stop_waiter(mpp, vecs, 1);
+ 			i--;
diff --git a/0094-RHBZ-707560-check-return-value.patch b/0094-RHBZ-707560-check-return-value.patch
new file mode 100644
index 0000000..4b6becf
--- /dev/null
+++ b/0094-RHBZ-707560-check-return-value.patch
@@ -0,0 +1,18 @@
+---
+ multipathd/main.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -999,7 +999,8 @@ int update_path_groups(struct multipath 
+ 		return 1;
+ 	}
+ 	dm_lib_release();
+-	setup_multipath(vecs, mpp);
++	if (setup_multipath(vecs, mpp) != 0)
++		return 1;
+ 	sync_map_state(mpp);
+ 
+ 	return 0;
diff --git a/0095-RHBZ-678673-no-path-groups.patch b/0095-RHBZ-678673-no-path-groups.patch
new file mode 100644
index 0000000..dde39ac
--- /dev/null
+++ b/0095-RHBZ-678673-no-path-groups.patch
@@ -0,0 +1,30 @@
+---
+ libmultipath/dmparser.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/dmparser.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dmparser.c
++++ multipath-tools/libmultipath/dmparser.c
+@@ -88,6 +88,7 @@ assemble_map (struct multipath * mp)
+ 	int i, j;
+ 	int shift, freechar;
+ 	int minio;
++	int nr_priority_groups, initial_pg_nr;
+ 	char * p;
+ 	struct pathgroup * pgp;
+ 	struct path * pp;
+@@ -96,9 +97,12 @@ assemble_map (struct multipath * mp)
+ 	p = mp->params;
+ 	freechar = sizeof(mp->params);
+ 
++	nr_priority_groups = VECTOR_SIZE(mp->pg);
++	initial_pg_nr = (nr_priority_groups ? mp->bestpg : 0);
++
+ 	shift = snprintf(p, freechar, "%s %s %i %i",
+ 			 assemble_features(mp), mp->hwhandler,
+-			 VECTOR_SIZE(mp->pg), mp->bestpg);
++			 nr_priority_groups, initial_pg_nr);
+ 
+ 	if (shift >= freechar) {
+ 		fprintf(stderr, "mp->params too small\n");
diff --git a/0096-RHBZ-683616-ioship-support.patch b/0096-RHBZ-683616-ioship-support.patch
new file mode 100644
index 0000000..42383b5
--- /dev/null
+++ b/0096-RHBZ-683616-ioship-support.patch
@@ -0,0 +1,151 @@
+---
+ libmultipath/checkers/rdac.c     |   92 ++++++++++++++++++++++++++++++++++++++-
+ libmultipath/prioritizers/rdac.c |    4 +
+ 2 files changed, 95 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/libmultipath/checkers/rdac.c
+===================================================================
+--- multipath-tools.orig/libmultipath/checkers/rdac.c
++++ multipath-tools/libmultipath/checkers/rdac.c
+@@ -12,27 +12,113 @@
+ #include <errno.h>
+ 
+ #include "checkers.h"
++#include "debug.h"
+ 
+ #include "../libmultipath/sg_include.h"
+ 
+ #define INQUIRY_CMDLEN		6
+ #define INQUIRY_CMD		0x12
++#define MODE_SENSE_CMD		0x5a
++#define MODE_SELECT_CMD		0x55
++#define MODE_SEN_SEL_CMDLEN	10
+ #define SENSE_BUFF_LEN		32
+ #define SCSI_CHECK_CONDITION	0x2
+ #define SCSI_COMMAND_TERMINATED	0x22
+ #define SG_ERR_DRIVER_SENSE	0x08
+ #define RECOVERED_ERROR		0x01
+ 
++
++#define CURRENT_PAGE_CODE_VALUES	0
++#define CHANGEABLE_PAGE_CODE_VALUES 	1
++
+ #define MSG_RDAC_UP    "rdac checker reports path is up"
+ #define MSG_RDAC_DOWN  "rdac checker reports path is down"
+ #define MSG_RDAC_GHOST "rdac checker reports path is ghost"
+ 
++struct control_mode_page {
++	unsigned char header[8];
++	unsigned char page_code;
++	unsigned char page_len;
++	unsigned char dontcare0[3];
++	unsigned char tas_bit;
++	unsigned char dontcare1[6];
++};
++
+ struct rdac_checker_context {
+ 	void * dummy;
+ };
+ 
+ int libcheck_init (struct checker * c)
+ {
++	unsigned char cmd[MODE_SEN_SEL_CMDLEN];
++	unsigned char sense_b[SENSE_BUFF_LEN];
++	struct sg_io_hdr io_hdr;
++	struct control_mode_page current, changeable;
++	int set = 0;
++
++	memset(cmd, 0, MODE_SEN_SEL_CMDLEN);
++	cmd[0] = MODE_SENSE_CMD;
++	cmd[1] = 0x08; /* DBD bit on */
++	cmd[2] = 0xA + (CURRENT_PAGE_CODE_VALUES << 6);
++	cmd[8] = (sizeof(struct control_mode_page) &  0xff);
++
++	memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
++	memset(sense_b, 0, SENSE_BUFF_LEN);
++	memset(&current, 0, sizeof(struct control_mode_page));
++
++	io_hdr.interface_id = 'S';
++	io_hdr.cmd_len = MODE_SEN_SEL_CMDLEN;
++	io_hdr.mx_sb_len = sizeof(sense_b);
++	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
++	io_hdr.dxfer_len = (sizeof(struct control_mode_page) &  0xff);
++	io_hdr.dxferp = &current;
++	io_hdr.cmdp = cmd;
++	io_hdr.sbp = sense_b;
++	io_hdr.timeout = c->timeout;
++
++	if (ioctl(c->fd, SG_IO, &io_hdr) < 0)
++		goto out;
++
++	/* check the TAS bit to see if it is already set */
++	if ((current.tas_bit >> 6) & 0x1) {
++		set = 1;
++		goto out;
++	}
++
++	/* get the changeble values */
++	cmd[2] = 0xA + (CHANGEABLE_PAGE_CODE_VALUES << 6);
++	io_hdr.dxferp = &changeable;
++	memset(&changeable, 0, sizeof(struct control_mode_page));
++
++	if (ioctl(c->fd, SG_IO, &io_hdr) < 0)
++		goto out;
++
++	/* if TAS bit is not settable exit */
++	if (((changeable.tas_bit >> 6) & 0x1) == 0)
++		goto out;
++
++	/* Now go ahead and set it */
++	memset(cmd, 0, MODE_SEN_SEL_CMDLEN);
++	cmd[0] = MODE_SELECT_CMD;
++	cmd[1] = 0x1; /* set SP bit on */
++	cmd[8] = (sizeof(struct control_mode_page) &  0xff);
++
++	/* use the same buffer as current, only set the tas bit */
++	current.page_code = 0xA;
++	current.page_len = 0xA;
++	current.tas_bit |= (1 << 6);
++
++	io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
++	io_hdr.dxferp = &current;
++
++	if (ioctl(c->fd, SG_IO, &io_hdr) < 0)
++		goto out;
++
++	/* Success */
++	set = 1;
++out:
++	if (set == 0)
++		condlog(0, "rdac checker failed to set TAS bit");
+ 	return 0;
+ }
+ 
+@@ -132,7 +218,11 @@ libcheck_check (struct checker * c)
+ 		goto done;
+ 	}
+ 
+-	ret = ((inq.avtcvp & 0x1) ? PATH_UP : PATH_GHOST);
++	/* If owner set or ioship mode is enabled return PATH_UP always */
++	if ((inq.avtcvp & 0x1) || ((inq.avtcvp >> 5) & 0x1))
++		ret = PATH_UP;
++	else
++		ret = PATH_GHOST;
+ 
+ done:
+ 	switch (ret) {
+Index: multipath-tools/libmultipath/prioritizers/rdac.c
+===================================================================
+--- multipath-tools.orig/libmultipath/prioritizers/rdac.c
++++ multipath-tools/libmultipath/prioritizers/rdac.c
+@@ -81,6 +81,10 @@ int rdac_prio(const char *dev, int fd)
+ 		break;
+ 	}
+ 
++	/* For ioship mode set the bit 3 (00001000) */
++	if ((sense_buffer[8] >> 5) & 0x01)
++		ret |= 0x08;
++
+ out:
+ 	return(ret);
+ }
diff --git a/0097-RHBZ-697386-fix-shutdown-crash.patch b/0097-RHBZ-697386-fix-shutdown-crash.patch
new file mode 100644
index 0000000..7faa7a9
--- /dev/null
+++ b/0097-RHBZ-697386-fix-shutdown-crash.patch
@@ -0,0 +1,17 @@
+---
+ multipathd/main.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -1155,6 +1155,8 @@ checkerloop (void *ap)
+ 		block_signal(SIGHUP, &old);
+ 		pthread_cleanup_push(cleanup_lock, &vecs->lock);
+ 		lock(vecs->lock);
++		/* check to see if we are exiting */
++		pthread_testcancel();
+ 		condlog(4, "tick");
+ 
+ 		if (vecs->pathvec) {
diff --git a/0098-RHBZ-706555-dont-update-pgs-in-manual.patch b/0098-RHBZ-706555-dont-update-pgs-in-manual.patch
new file mode 100644
index 0000000..3ae8a54
--- /dev/null
+++ b/0098-RHBZ-706555-dont-update-pgs-in-manual.patch
@@ -0,0 +1,18 @@
+---
+ multipathd/main.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+Index: multipath-tools/multipathd/main.c
+===================================================================
+--- multipath-tools.orig/multipathd/main.c
++++ multipath-tools/multipathd/main.c
+@@ -1118,7 +1118,8 @@ check_path (struct vectors * vecs, struc
+ 	condlog(4, "path prio refresh");
+ 	if (update_prio(pp, new_path_up) &&
+ 	    pp->mpp->pgpolicyfn == (pgpolicyfn *)group_by_prio &&
+-	    pp->mpp->pgfailback != -FAILBACK_FOLLOWOVER)
++	    (pp->mpp->pgfailback == -FAILBACK_IMMEDIATE ||
++	     pp->mpp->pgfailback > 0))
+ 		update_path_groups(pp->mpp, vecs, !new_path_up);
+ 	else if (need_switch_pathgroup(pp->mpp, 0)) {
+ 		if (pp->mpp->pgfailback > 0 &&
diff --git a/0099-RHBZ-705854-warn-on-bad-dev-loss-tmo.patch b/0099-RHBZ-705854-warn-on-bad-dev-loss-tmo.patch
new file mode 100644
index 0000000..a82e64c
--- /dev/null
+++ b/0099-RHBZ-705854-warn-on-bad-dev-loss-tmo.patch
@@ -0,0 +1,17 @@
+---
+ libmultipath/discovery.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+Index: multipath-tools/libmultipath/discovery.c
+===================================================================
+--- multipath-tools.orig/libmultipath/discovery.c
++++ multipath-tools/libmultipath/discovery.c
+@@ -297,6 +297,8 @@ sysfs_set_scsi_tmo (struct multipath *mp
+ 				return 1;
+ 		}
+ 		if (mpp->dev_loss){
++			if (mpp->dev_loss > 600 && mpp->fast_io_fail <= 0)
++				condlog(2, "you must enable fast_io_fail_tmo in order to set dev_loss_tmo greater than 600");
+ 			snprintf(value, 11, "%u", mpp->dev_loss);
+  			if (sysfs_attr_set_value(attr_path, "dev_loss_tmo",
+ 						 value))
diff --git a/0100-RHBZ-710478-deprecate-uid-gid-mode.patch b/0100-RHBZ-710478-deprecate-uid-gid-mode.patch
new file mode 100644
index 0000000..d7373b6
--- /dev/null
+++ b/0100-RHBZ-710478-deprecate-uid-gid-mode.patch
@@ -0,0 +1,162 @@
+---
+ libmultipath/dict.c        |   12 +++++-----
+ multipath.conf.annotated   |   53 ---------------------------------------------
+ multipath.conf.synthetic   |    3 --
+ multipath/multipath.conf.5 |   18 ---------------
+ 4 files changed, 6 insertions(+), 80 deletions(-)
+
+Index: multipath-tools/libmultipath/dict.c
+===================================================================
+--- multipath-tools.orig/libmultipath/dict.c
++++ multipath-tools/libmultipath/dict.c
+@@ -2204,13 +2204,13 @@ init_keywords(void)
+ 	install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout);
+ 	install_keyword("flush_on_last_del", &def_flush_on_last_del_handler, &snprint_def_flush_on_last_del);
+ 	install_keyword("user_friendly_names", &names_handler, &snprint_def_user_friendly_names);
+-	install_keyword("mode", &def_mode_handler, &snprint_def_mode);
+-	install_keyword("uid", &def_uid_handler, &snprint_def_uid);
+-	install_keyword("gid", &def_gid_handler, &snprint_def_gid);
+ 	install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail);
+ 	install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
+ 	install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths);
+ 	install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err);
++	__deprecated install_keyword("mode", &def_mode_handler, &snprint_def_mode);
++	__deprecated install_keyword("uid", &def_uid_handler, &snprint_def_uid);
++	__deprecated install_keyword("gid", &def_gid_handler, &snprint_def_gid);
+ 	__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
+ 	__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
+ 	__deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL);
+@@ -2283,9 +2283,9 @@ init_keywords(void)
+ 	install_keyword("rr_min_io", &mp_minio_handler, &snprint_mp_rr_min_io);
+ 	install_keyword("pg_timeout", &mp_pg_timeout_handler, &snprint_mp_pg_timeout);
+ 	install_keyword("flush_on_last_del", &mp_flush_on_last_del_handler, &snprint_mp_flush_on_last_del);
+-	install_keyword("mode", &mp_mode_handler, &snprint_mp_mode);
+-	install_keyword("uid", &mp_uid_handler, &snprint_mp_uid);
+-	install_keyword("gid", &mp_gid_handler, &snprint_mp_gid);
++	__deprecated install_keyword("mode", &mp_mode_handler, &snprint_mp_mode);
++	__deprecated install_keyword("uid", &mp_uid_handler, &snprint_mp_uid);
++	__deprecated install_keyword("gid", &mp_gid_handler, &snprint_mp_gid);
+ 	install_keyword("prio", &mp_prio_handler, &snprint_mp_prio);
+ 	install_sublevel_end();
+ }
+Index: multipath-tools/multipath.conf.annotated
+===================================================================
+--- multipath-tools.orig/multipath.conf.annotated
++++ multipath-tools/multipath.conf.annotated
+@@ -176,32 +176,6 @@
+ #	user_friendly_names no
+ #
+ #	#
+-#	# name    : mode
+-#	# scope   : multipath
+-#	# desc    : The mode to use for the multipath device nodes, in octal.
+-#	# values  : 0000 - 0777
+-#	# default : determined by the process
+-#	mode 0644
+-#
+-#	#
+-#	# name    : uid
+-#	# scope   : multipath
+-#	# desc    : The user id to use for the multipath device nodes. You
+-#	#           may use either the numeric or symbolic uid
+-#	# values  : <user_id>
+-#	# default : determined by the process
+-#	uid 0
+-#
+-#	#
+-#	# name    : gid
+-#	# scope   : multipath
+-#	# desc    : The group id to user for the multipath device nodes. You
+-#	#           may use either the numeric or symbolic gid
+-#	# values  : <group_id>
+-#	# default : determined by the process
+-#	gid disk
+-#
+-#	#
+ #	# name    : checker_timeout
+ #	# scope   : multipath & multipathd
+ #	# desc    : The timeout to use for path checkers that issue scsi
+@@ -369,33 +343,6 @@
+ #		#
+ #		flush_on_last_del       yes
+ #
+-#		#
+-#		# name    : mode
+-#		# scope   : multipath
+-#		# desc    : The mode to use for the multipath device nodes, in
+-#		#           octal.
+-#		# values  : 0000 - 0777
+-#		# default : determined by the process
+-#		mode 0644
+-#
+-#		#
+-#		# name    : uid
+-#		# scope   : multipath
+-#		# desc    : The user id to use for the multipath device nodes.
+-#		#           You may use either the numeric or symbolic uid
+-#		# values  : <user_id>
+-#		# default : determined by the process
+-#		uid 0
+-#
+-#		#
+-#		# name    : gid
+-#		# scope   : multipath
+-#		# desc    : The group id to user for the multipath device nodes.
+-#		#           You may use either the numeric or symbolic gid
+-#		# values  : <group_id>
+-#		# default : determined by the process
+-#		gid 0
+-#
+ #	}
+ #	multipath {
+ #		wwid	1DEC_____321816758474
+Index: multipath-tools/multipath.conf.synthetic
+===================================================================
+--- multipath-tools.orig/multipath.conf.synthetic
++++ multipath-tools/multipath.conf.synthetic
+@@ -18,9 +18,6 @@
+ #	no_path_retry		fail
+ #	queue_without_daemon    no
+ #	user_friendly_names	no
+-#	mode			644
+-#	uid			0
+-#	gid			disk
+ #}
+ #blacklist {
+ #       wwid 26353900f02796769
+Index: multipath-tools/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools.orig/multipath/multipath.conf.5
++++ multipath-tools/multipath/multipath.conf.5
+@@ -335,18 +335,6 @@ will disable the timeout.
+ Specify the number of seconds the scsi layer will wait after a problem has
+ been detected on a FC remote port before removing it from the system.
+ .TP
+-.B mode
+-The mode to use for the multipath device nodes, in octal; default determined
+-by the process
+-.TP
+-.B uid
+-The user id to use for the multipath device nodes. You may use either the
+-numeric or symbolic uid; default determined by the process.
+-.TP
+-.B gid
+-The group id to use for the mutipath device nodes. You may use either the
+-numeric or symbolic gid; default determined by the process.
+-.TP
+ .B log_checker_err
+ If set to
+ .I once
+@@ -446,12 +434,6 @@ section:
+ .B rr_weight
+ .TP
+ .B flush_on_last_del
+-.TP
+-.B mode
+-.TP
+-.B uid
+-.TP
+-.B gid
+ .RE
+ .PD
+ .LP
diff --git a/0101-RHBZ-631009-disable-udev-disk-rules-on-reload.patch b/0101-RHBZ-631009-disable-udev-disk-rules-on-reload.patch
new file mode 100644
index 0000000..3903cb3
--- /dev/null
+++ b/0101-RHBZ-631009-disable-udev-disk-rules-on-reload.patch
@@ -0,0 +1,173 @@
+---
+ kpartx/devmapper.c       |   14 +++++++++++---
+ kpartx/devmapper.h       |    2 +-
+ kpartx/kpartx.c          |   15 +++++++++++----
+ libmultipath/config.h    |    1 +
+ libmultipath/devmapper.c |   12 ++++++++++--
+ multipath/main.c         |    5 ++++-
+ 6 files changed, 38 insertions(+), 11 deletions(-)
+
+Index: multipath-tools/kpartx/devmapper.c
+===================================================================
+--- multipath-tools.orig/kpartx/devmapper.c
++++ multipath-tools/kpartx/devmapper.c
+@@ -52,7 +52,8 @@ dm_prereq (char * str, int x, int y, int
+ }
+ 
+ extern int
+-dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie) {
++dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie,
++	      int force_udev_rules) {
+ 	int r = 0;
+ 	int udev_wait_flag = (task == DM_DEVICE_RESUME ||
+ 			      task == DM_DEVICE_REMOVE);
+@@ -70,8 +71,15 @@ dm_simplecmd (int task, const char *name
+ 	if (no_flush)
+ 		dm_task_no_flush(dmt);
+ 
+-	if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, 0))
+-		goto out;
++	if (udev_wait_flag) {
++		if (!dm_task_set_cookie(dmt, cookie, (force_udev_rules)? 0 :
++					DM_UDEV_DISABLE_DISK_RULES_FLAG))
++			goto out;
++	}
++	else if (task == DM_DEVICE_RESUME && dm_cookie_supported() &&
++		 !force_udev_rules)
++		dm_task_set_event_nr(dmt, DM_UDEV_DISABLE_DISK_RULES_FLAG <<
++					  DM_UDEV_FLAGS_SHIFT);
+ 	r = dm_task_run(dmt);
+ 
+ 	out:
+Index: multipath-tools/kpartx/devmapper.h
+===================================================================
+--- multipath-tools.orig/kpartx/devmapper.h
++++ multipath-tools/kpartx/devmapper.h
+@@ -3,7 +3,7 @@
+ #define MKDEV(ma,mi)    ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
+ 
+ int dm_prereq (char *, int, int, int);
+-int dm_simplecmd (int, const char *, int, uint32_t *);
++int dm_simplecmd (int, const char *, int, uint32_t *, int);
+ int dm_addmap (int, const char *, const char *, const char *, uint64_t,
+ 	       const char *, int, mode_t, uid_t, gid_t, uint32_t *);
+ int dm_map_present (char *);
+Index: multipath-tools/kpartx/kpartx.c
+===================================================================
+--- multipath-tools.orig/kpartx/kpartx.c
++++ multipath-tools/kpartx/kpartx.c
+@@ -82,7 +82,7 @@ initpts(void)
+ 	addpts("sun", read_sun_pt);
+ }
+ 
+-static char short_opts[] = "ladgvp:t:s";
++static char short_opts[] = "ladgvp:t:su";
+ 
+ /* Used in gpt.c */
+ int force_gpt=0;
+@@ -184,7 +184,8 @@ get_hotplug_device(void)
+ }
+ 
+ int
+-main(int argc, char **argv){
++main(int argc, char **argv)
++{
+ 	int fd, i, j, k, n, op, off, arg;
+ 	struct slice all;
+ 	struct pt *ptp;
+@@ -202,6 +203,7 @@ main(int argc, char **argv){
+ 	int sync = 0;
+ 	struct stat buf;
+ 	uint32_t cookie = 0;
++	int force_udev_rules = 0;
+ 
+ 	initpts();
+ 	init_crc32();
+@@ -257,6 +259,9 @@ main(int argc, char **argv){
+ 		case 's':
+ 			sync = 1;
+ 			break;
++		case 'u':
++			force_udev_rules = 1;
++			break;
+ 		default:
+ 			usage();
+ 			exit(1);
+@@ -404,7 +409,8 @@ main(int argc, char **argv){
+ 					continue;
+ 
+ 				if (!dm_simplecmd(DM_DEVICE_REMOVE, partname,
+-						  0, &cookie)) {
++						  0, &cookie,
++						  force_udev_rules)) {
+ 					r++;
+ 					continue;
+ 				}
+@@ -454,7 +460,8 @@ main(int argc, char **argv){
+ 				}
+ 				if (op == DM_DEVICE_RELOAD &&
+ 				    !dm_simplecmd(DM_DEVICE_RESUME, partname,
+-						  1, &cookie)) {
++						  1, &cookie,
++						  force_udev_rules)) {
+ 					fprintf(stderr, "resume failed on %s\n",
+ 						partname);
+ 					r++;
+Index: multipath-tools/libmultipath/config.h
+===================================================================
+--- multipath-tools.orig/libmultipath/config.h
++++ multipath-tools/libmultipath/config.h
+@@ -90,6 +90,7 @@ struct config {
+ 	int find_multipaths;
+ 	int allow_queueing;
+ 	int log_checker_err;
++	int force_udev_rules;
+ 	uid_t uid;
+ 	gid_t gid;
+ 	mode_t mode;
+Index: multipath-tools/libmultipath/devmapper.c
+===================================================================
+--- multipath-tools.orig/libmultipath/devmapper.c
++++ multipath-tools/libmultipath/devmapper.c
+@@ -168,8 +168,16 @@ dm_simplecmd (int task, const char *name
+ 		dm_task_no_flush(dmt);		/* for DM_DEVICE_SUSPEND/RESUME */
+ #endif
+ 
+-	if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, 0))
+-		goto out;
++	if (udev_wait_flag) {
++		if (!dm_task_set_cookie(dmt, &conf->cookie,
++					(conf->force_udev_rules)? 0 :
++					DM_UDEV_DISABLE_DISK_RULES_FLAG))
++			goto out;
++	}
++	else if (task == DM_DEVICE_RESUME && dm_cookie_supported() &&
++		 !conf->force_udev_rules)
++		dm_task_set_event_nr(dmt, DM_UDEV_DISABLE_DISK_RULES_FLAG <<
++					  DM_UDEV_FLAGS_SHIFT);
+ 	r = dm_task_run (dmt);
+ 
+ 	out:
+Index: multipath-tools/multipath/main.c
+===================================================================
+--- multipath-tools.orig/multipath/main.c
++++ multipath-tools/multipath/main.c
+@@ -383,7 +383,7 @@ main (int argc, char *argv[])
+ 		condlog(0, "multipath tools need sysfs mounted");
+ 		exit(1);
+ 	}
+-	while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:Brq")) != EOF ) {
++	while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:Brqu")) != EOF ) {
+ 		switch(arg) {
+ 		case 1: printf("optarg : %s\n",optarg);
+ 			break;
+@@ -439,6 +439,9 @@ main (int argc, char *argv[])
+ 		case 'r':
+ 			conf->force_reload = 1;
+ 			break;
++		case 'u':
++			conf->force_udev_rules = 1;
++			break;
+ 		case 'h':
+ 			usage(argv[0]);
+ 		case ':':
diff --git a/0102-RHBZ-690828-systemd-unit-file.patch b/0102-RHBZ-690828-systemd-unit-file.patch
new file mode 100644
index 0000000..0c6aaa3
--- /dev/null
+++ b/0102-RHBZ-690828-systemd-unit-file.patch
@@ -0,0 +1,58 @@
+---
+ Makefile.inc                  |    1 +
+ multipathd/Makefile           |    2 ++
+ multipathd/multipathd.service |   14 ++++++++++++++
+ 3 files changed, 17 insertions(+)
+
+Index: multipath-tools/Makefile.inc
+===================================================================
+--- multipath-tools.orig/Makefile.inc
++++ multipath-tools/Makefile.inc
+@@ -31,6 +31,7 @@ man5dir     = $(prefix)/usr/share/man/ma
+ rcdir	    = $(prefix)/etc/rc.d/init.d
+ syslibdir   = $(prefix)/$(LIB)
+ libdir	    = $(prefix)/$(LIB)/multipath
++unitdir     = $(prefix)/lib/systemd/system
+ 
+ GZIP        = /bin/gzip -9 -c
+ INSTALL_PROGRAM = install
+Index: multipath-tools/multipathd/Makefile
+===================================================================
+--- multipath-tools.orig/multipathd/Makefile
++++ multipath-tools/multipathd/Makefile
+@@ -36,6 +36,8 @@ install:
+ 	$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
+ 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir)
+ 	$(INSTALL_PROGRAM) -m 755 multipathd.init.redhat $(DESTDIR)$(rcdir)/$(EXEC)
++	$(INSTALL_PROGRAM) -d $(DESTDIR)$(unitdir)
++	$(INSTALL_PROGRAM) -m 644 $(EXEC).service $(DESTDIR)$(unitdir)
+ 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
+ 	$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
+ 
+@@ -43,6 +45,7 @@ uninstall:
+ 	rm -f $(DESTDIR)$(bindir)/$(EXEC)
+ 	rm -f $(DESTDIR)$(rcdir)/$(EXEC)
+ 	rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
++	rm -f $(DESTDIR)$(unitdir)/$(EXEC).service
+ 
+ clean:
+ 	rm -f core *.o $(EXEC) *.gz
+Index: multipath-tools/multipathd/multipathd.service
+===================================================================
+--- /dev/null
++++ multipath-tools/multipathd/multipathd.service
+@@ -0,0 +1,14 @@
++[Unit]
++Description=Device-Mapper Multipath Device Controller
++Before=iscsi.service iscsid.service
++After=syslog.target
++
++[Service]
++Type=forking
++PIDFile=/var/run/multipathd.pid
++ExecStart=/sbin/multipathd
++ExecReload=/bin/kill -HUP $MAINPID
++#ExecStop=/path/to/scrip delete-me if not necessary
++
++[Install]
++WantedBy=multi-user.target
diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec
index 067b898..496e270 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: 15%{?dist}
+Release: 16%{?dist}
 License: GPL+
 Group: System Environment/Base
 URL: http://christophe.varoqui.free.fr/
@@ -37,20 +37,98 @@ Patch1021: 0021-RHBZ-548874-add-find-multipaths.patch
 Patch1022: 0022-RHBZ-557845-RHEL5-style-partitions.patch
 Patch1023: 0023-RHBZ-557810-emc-invista-config.patch
 Patch1024: 0024-RHBZ-565933-checker-timeout.patch
+Patch1025: 0025-RHBZ-508827-update-multipathd-manpage.patch
+Patch1026: 0026-RHBZ-549636-default-path-selector.patch
+Patch1027: 0027-RHBZ-509443-enhance-show-config.patch
+Patch1028: 0028-RHBZ-452617-add-revision-parameter.patch
+Patch1029: 0029-RHBZ-567219-recalculate-pgs-in-checkerloop.patch
+Patch1030: 0030-RHBZ-558636-check-if-multipath-owns-path.patch
+Patch1031: 0031-RHBZ-570546-display-avg-pg-prio.patch
+Patch1032: 0032-RHBZ-575767-ontap_prio.patch
+Patch1033: 0033-RHBZ-573715-eurologic-config.patch
+Patch1034: 0034-RHBZ-579575-add-q-multipath-option.patch
+Patch1035: 0035-RHBZ-467709-add-followover.patch
+Patch1036: 0036-RH-clear-messages.patch
+Patch1037: 0037-RH-adopt-paths.patch
+Patch1038: 0038-RHBZ-587201-IBM-SGI.patch
+Patch1039: 0039-RHBZ-589153-manpage-update.patch
+Patch1040: 0040-RHBZ-587695-add-checker-msg-alias.patch
+Patch1041: 0041-RHBZ-587695-add-rdac-message.patch
+Patch1042: 0042-RHBZ-590038-fix-fast-io-fail-tmo.patch
+Patch1043: 0043-RHBZ-590028-close-sysfs_attr_fd.patch
+Patch1044: 0044-RHBZ-591940-dont-clear-daemon.patch
+Patch1045: 0045-RHBZ-593379-dont-add-unknown-paths.patch
+Patch1046: 0046-RHBZ-593426-move-adopt-path.patch
+Patch1047: 0047-RHBZ-591608-only-switch-pgs-once.patch
+Patch1048: 0048-RHBZ-592494-fix-user-configs.patch
+Patch1049: 0049-RHBZ-591644-enhance-mpathconf.patch
+Patch1050: 0050-RHBZ-595400-fix-checker-tmo.patch
+Patch1051: 0051-RHBZ-596156-mpathconf-man-page.patch
+Patch1052: 0052-RHBZ-601247-fix-path-adoption.patch
+Patch1053: 0053-RHBZ-596323-remember_more_wwids.patch
+Patch1054: 0054-RHBZ-596319-rules-cleanup.patch
+Patch1055: 0055-RHBZ-602257-update-on-show-topology.patch
+Patch1056: 0056-RHBZ-603812-better-type-check.patch
+Patch1057: 0057-RHBZ-607869-fix-resize.patch
+Patch1058: 0058-RHBZ-601665-assemble-features.patch
+Patch1059: 0059-RHBZ-607874-handle-offlined-paths.patch
+Patch1060: 0060-RHBZ-606420-fix-remove-map.patch
+Patch1061: 0061-RHBZ-620479-find-rport.patch
+Patch1062: 0062-RHBZ-592998-hpsc-config.patch
+Patch1063: 0063-RHBZ-595719-udev_link_priority.patch
+Patch1064: 0064-RHBZ-612173-fix-reverse-lookup.patch
+Patch1065: 0065-RHBZ-635088-update-priority.patch
+Patch1066: 0066-RHBZ-636071-mpathconf-variable_names.patch
+Patch1067: 0067-RHBZ-622569-symmetrix-config.patch
+Patch1068: 0068-RHBZ-632734-nvdisk-config.patch
+Patch1069: 0069-RHBZ-636246-hp-open-config.patch
+Patch1070: 0070-RHBZ-639037-hitachi-open-config.patch
+Patch1071: 0071-RHBZ-611779-fix-whitespace-crash.patch
+Patch1072: 0072-RHBZ-651389-change-scsi-tmo-order.patch
+Patch1073: 0073-RHBZ-650664-clarify-error-msg.patch
+Patch1074: 0074-RHBZ-602883-dont-print-change.patch
+Patch1075: 0075-RHBZ-576919-log-checker-err.patch
+Patch1076: 0076-RHBZ-599690-update-multipath-conf.patch
+Patch1077: 0077-RHBZ-622608-nvdisk-config.patch
+Patch1078: 0078-RHBZ-628095-config-warnings.patch
+Patch1079: 0079-RHBZ-650797-display-iscsi-tgt-name.patch
+Patch1080: 0080-RHBZ-662731-fix-no-config-value-segfault.patch
+Patch1081: 0081-RHBZ-623644-fix-sysfs-caching.patch
+Patch1083: 0083-RHBZ-636213-633643-new-configs.patch
+Patch1084: 0084-RHBZ-644111-read-only-bindings.patch
+Patch1085: 0085-RHBZ-645605-fix-offline-check.patch
+Patch1086: 0086-RHBZ-681144-sysfs-device-cleanup.patch
+Patch1087: 0087-RHBZ-680480-skip-if-no-sysdev.patch
+Patch1088: 0088-RHBZ-693524-fix-prio-segfault.patch
+Patch1089: 0089-RHBZ-694602-RSSM-config.patch
+Patch1090: 0090-RHBZ-700169-fix-nr-active.patch
+Patch1091: 0091-RHBZ-699577-manpage-clarification.patch
+Patch1092: 0092-RHBZ-689504-rdac-retry.patch
+Patch1093: 0093-RHBZ-677449-dont-remove-map-on-enomem.patch
+Patch1094: 0094-RHBZ-707560-check-return-value.patch
+Patch1095: 0095-RHBZ-678673-no-path-groups.patch
+Patch1096: 0096-RHBZ-683616-ioship-support.patch
+Patch1097: 0097-RHBZ-697386-fix-shutdown-crash.patch
+Patch1098: 0098-RHBZ-706555-dont-update-pgs-in-manual.patch
+Patch1099: 0099-RHBZ-705854-warn-on-bad-dev-loss-tmo.patch
+Patch1100: 0100-RHBZ-710478-deprecate-uid-gid-mode.patch
+Patch1101: 0101-RHBZ-631009-disable-udev-disk-rules-on-reload.patch
+Patch1102: 0102-RHBZ-690828-systemd-unit-file.patch
 
 # runtime
 Requires: %{name}-libs = %{version}-%{release}
 Requires: kpartx = %{version}-%{release}
 Requires: device-mapper >= 1.02.39-1
-Requires(post): chkconfig
-Requires(preun): chkconfig
-Requires(preun): initscripts
-Requires(postun): initscripts
+Requires: udev initscripts
+Requires(post): systemd-units systemd-sysv chkconfig
+Requires(preun): systemd-units
+Requires(postun): systemd-units
 
 # build/setup
 BuildRequires: libaio-devel, device-mapper-devel >= 1.02.39-1
 BuildRequires: libselinux-devel, libsepol-devel
 BuildRequires: readline-devel, ncurses-devel
+BuildRequires: systemd-units
 
 BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
 
@@ -71,6 +149,14 @@ The %{name}-libs provides the path checker
 and prioritizer modules. It also contains the multipath shared library,
 libmultipath.
 
+%package sysvinit
+Summary: SysV init script for device-mapper-multipath
+Group: System Environment/Libraries
+
+%description sysvinit
+SysV style init script for device-mapper-multipth. It needs to be
+installed only if systemd is not used as the system init process.
+
 %package -n kpartx
 Summary: Partition device manager for device-mapper devices
 Group: System Environment/Base
@@ -107,6 +193,83 @@ kpartx manages partition creation and removal for device-mapper devices.
 %patch1022 -p1
 %patch1023 -p1
 %patch1024 -p1
+%patch1025 -p1
+%patch1026 -p1
+%patch1027 -p1
+%patch1028 -p1
+%patch1029 -p1
+%patch1030 -p1
+%patch1031 -p1
+%patch1032 -p1
+%patch1033 -p1
+%patch1034 -p1
+%patch1035 -p1
+%patch1036 -p1
+%patch1037 -p1
+%patch1038 -p1
+%patch1039 -p1
+%patch1040 -p1
+%patch1041 -p1
+%patch1042 -p1
+%patch1043 -p1
+%patch1044 -p1
+%patch1045 -p1
+%patch1046 -p1
+%patch1047 -p1
+%patch1048 -p1
+%patch1049 -p1
+%patch1050 -p1
+%patch1051 -p1
+%patch1052 -p1
+%patch1053 -p1
+%patch1054 -p1
+%patch1055 -p1
+%patch1056 -p1
+%patch1057 -p1
+%patch1058 -p1
+%patch1059 -p1
+%patch1060 -p1
+%patch1061 -p1
+%patch1062 -p1
+%patch1063 -p1
+%patch1064 -p1
+%patch1065 -p1
+%patch1066 -p1
+%patch1067 -p1
+%patch1068 -p1
+%patch1069 -p1
+%patch1070 -p1
+%patch1071 -p1
+%patch1072 -p1
+%patch1073 -p1
+%patch1074 -p1
+%patch1075 -p1
+%patch1076 -p1
+%patch1077 -p1
+%patch1078 -p1
+%patch1079 -p1
+%patch1080 -p1
+%patch1081 -p1
+%patch1083 -p1
+%patch1084 -p1
+%patch1085 -p1
+%patch1086 -p1
+%patch1087 -p1
+%patch1088 -p1
+%patch1089 -p1
+%patch1090 -p1
+%patch1091 -p1
+%patch1092 -p1
+%patch1093 -p1
+%patch1094 -p1
+%patch1095 -p1
+%patch1096 -p1
+%patch1097 -p1
+%patch1098 -p1
+%patch1099 -p1
+%patch1100 -p1
+%patch1101 -p1
+%patch1102 -p1
 cp %{SOURCE1} .
 
 %build
@@ -123,7 +286,8 @@ make install \
 	bindir=%{_sbindir} \
 	syslibdir=%{_libdir} \
 	libdir=%{_libmpathdir} \
-	rcdir=%{_initrddir}
+	rcdir=%{_initrddir} \
+	unitdir=%{_unitdir}
 
 # tree fix up
 # install -m 0644 %{SOURCE1} %{buildroot}/etc/multipath.conf
@@ -133,34 +297,42 @@ install -d %{buildroot}/etc/multipath
 rm -rf %{buildroot}
 
 %post
-/sbin/chkconfig --add multipathd
-if [ "$1" -gt "1" -a ! -e /etc/multipath/bindings -a \
-    -f /var/lib/multipath/bindings ]; then
-	mv /var/lib/multipath/bindings /etc/multipath/bindings
-	ln -s /etc/multipath/bindings /var/lib/multipath/bindings
+if [ $1 -eq 1 ] ; then
+	/bin/systemctl enable multipathd.service >/dev/null 2>&1 || :
 fi
 
 %preun
-if [ "$1" = 0 ]; then
-	/sbin/service multipathd stop /dev/null 2>&1
-	/sbin/chkconfig --del multipathd
+if [ $1 -eq 0 ] ; then
+	/bin/systemctl --no-reload disable multipathd.service > /dev/null 2>&1 || :
+	bin/systemctl stop multipathd.service > /dev/null 2>&1 || :
 fi
 
 %postun
-if [ "$1" -ge "1" ]; then
-	/sbin/service multipathd condrestart >/dev/null 2>&1 || :
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
+if [ $1 -ge 1 ] ; then
+	/bin/systemctl try-restart multipathd.service >/dev/null 2>&1 || :
 fi
 
+%triggerun --  %{name} < 0.4.9-16
+%{_bindir}/systemd-sysv-convert --save multipathd >/dev/null 2>&1 ||: 
+bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||:
+/sbin/chkconfig --del multipathd >/dev/null 2>&1 || :
+/bin/systemctl try-restart multipathd.service >/dev/null 2>&1 || :
+
+%triggerpostun -n %{name}-sysvinit -- %{name} < 0.4.9-16
+/sbin/chkconfig --add mdmonitor >/dev/null 2>&1 || :
+
 %files
 %defattr(-,root,root,-)
 %{_sbindir}/multipath
 %{_sbindir}/multipathd
 %{_sbindir}/cciss_id
 %{_sbindir}/mpathconf
-%{_initrddir}/multipathd
+%{_unitdir}/multipathd.service
 %{_mandir}/man5/multipath.conf.5.gz
 %{_mandir}/man8/multipath.8.gz
 %{_mandir}/man8/multipathd.8.gz
+%{_mandir}/man8/mpathconf.8.gz
 %config /lib/udev/rules.d/40-multipath.rules
 %doc AUTHOR COPYING FAQ
 %doc multipath.conf multipath.conf.annotated
@@ -178,12 +350,28 @@ fi
 
 %postun libs -p /sbin/ldconfig
 
+%files sysvinit
+%{_initrddir}/multipathd
+
 %files -n kpartx
 %defattr(-,root,root,-)
 /sbin/kpartx
 %{_mandir}/man8/kpartx.8.gz
 
 %changelog
+* Fri Jul 15 2011 Benjamin Marzinski <bmarzins at redhat.com> -0.4.9-16
+- Modify 0012-RH-udev-sync-support.patch
+- Modify 0021-RHBZ-548874-add-find-multipaths.patch
+- Modify 0022-RHBZ-557845-RHEL5-style-partitions.patch
+- Add 0025-RHBZ-508827-update-multipathd-manpage.patch through
+      0101-RHBZ-631009-disable-udev-disk-rules-on-reload.patch
+  * sync with current state of RHEL6. Next release should include a updated
+    source tarball with most of these fixes rolled in.
+- Add 0102-RHBZ-690828-systemd-unit-file.patch
+  * Add Jóhann B. Guðmundsson's unit file for systemd.
+  * Add sub-package sysvinit for SysV init script.
+- Resolves: bz #690828
+
 * Tue Feb 08 2011 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 0.4.9-15
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
 


More information about the scm-commits mailing list