summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2016-07-22 15:20:02 -0500
committerBenjamin Marzinski <bmarzins@redhat.com>2016-07-22 15:20:02 -0500
commit906e1e11285fc41097fd89893227664addb00848 (patch)
treebbcab8e0a7182fd7e3327209001fc5fe95ac66a3
parent6738b34a0b0aabf1bc8c15d540bafa29ca99c58f (diff)
downloaddevice-mapper-multipath-906e1e11285fc41097fd89893227664addb00848.tar.gz
device-mapper-multipath-906e1e11285fc41097fd89893227664addb00848.tar.xz
device-mapper-multipath-906e1e11285fc41097fd89893227664addb00848.zip
device-mapper-multipath-0.4.9-83
Modify 0135-RHBZ-1299600-path-dev-uevents.patch * trigger uevents when adding wwids for existing devices during startup Refresh 0136-RHBZ-1304687-wait-for-map-add.patch Refresh 0150-RHBZ-1253913-fix-startup-msg.patch Modify 0159-UPBZ-1255885-udev-waits.patch * fix bug in failure path Add 0160-RH-udev-flags.patch Add 0161-RHBZ-1311659-no-kpartx.patch * skip_kpartx option disables kpartx running on multipath devices Add 0162-RHBZ-1333331-huawei-config.patch * Add default config for Huawei XSG1 array Add 0163-UPBZ-1333492-resize-map.patch * restore old size if resize fails Add 0164-RHBZ-1311463-dos-part-rollover.patch * fix incorrect partition size due to 4k device size rollover Add 0165-UPBZ-1341748-MSA-2040-conf.patch * Add default config for MSA 2040 array Add 0166-RHBZ-1323429-dont-allow-new-wwid.patch * don't allow path wwid to change while it is in use Add 0167-RHBZ-1335176-fix-show-cmds.patch * and new show multipath format wildcard, 'f' to sho number of failures. This will hopefully be useful for tracking what happens to multipath devices for bz #1335176 Add 0168-RHBZ-1347769-shared-lock.patch * make multipath lock the path devices with a shared lock Add 0169-UPBZ-1353357-json-output.patch * add mulitpathd json output command Add 0170-UPBZ-1352925-fix-typo.patch Add 0171-UPBZ-1356651-allow-zero-size.patch * Allow zero-sized paths to be added to a multipath device Add 0172-RHBZ-1350931-no-active-add.patch * Allow paths to be added to a new map if no active paths exist. Also fixes 1351430
-rw-r--r--0135-RHBZ-1299600-path-dev-uevents.patch29
-rw-r--r--0136-RHBZ-1304687-wait-for-map-add.patch4
-rw-r--r--0150-RHBZ-1253913-fix-startup-msg.patch14
-rw-r--r--0159-UPBZ-1255885-udev-waits.patch188
-rw-r--r--0160-RH-udev-flags.patch20
-rw-r--r--0161-RHBZ-1311659-no-kpartx.patch618
-rw-r--r--0162-RHBZ-1333331-huawei-config.patch24
-rw-r--r--0163-UPBZ-1333492-resize-map.patch24
-rw-r--r--0164-RHBZ-1311463-dos-part-rollover.patch17
-rw-r--r--0165-UPBZ-1341748-MSA-2040-conf.patch30
-rw-r--r--0166-RHBZ-1323429-dont-allow-new-wwid.patch24
-rw-r--r--0167-RHBZ-1335176-fix-show-cmds.patch138
-rw-r--r--0168-RHBZ-1347769-shared-lock.patch17
-rw-r--r--0169-UPBZ-1353357-json-output.patch549
-rw-r--r--0170-UPBZ-1352925-fix-typo.patch26
-rw-r--r--0171-UPBZ-1356651-allow-zero-size.patch79
-rw-r--r--0172-RHBZ-1350931-no-active-add.patch37
-rw-r--r--device-mapper-multipath.spec64
18 files changed, 1727 insertions, 175 deletions
diff --git a/0135-RHBZ-1299600-path-dev-uevents.patch b/0135-RHBZ-1299600-path-dev-uevents.patch
index fddbe19..2de58a4 100644
--- a/0135-RHBZ-1299600-path-dev-uevents.patch
+++ b/0135-RHBZ-1299600-path-dev-uevents.patch
@@ -1,8 +1,10 @@
---
libmultipath/configure.c | 30 ++++++++++++++++++++++++++++--
+ libmultipath/configure.h | 1 +
libmultipath/wwids.c | 4 ++--
multipath/main.c | 2 +-
- 3 files changed, 31 insertions(+), 5 deletions(-)
+ multipathd/main.c | 3 ++-
+ 5 files changed, 34 insertions(+), 6 deletions(-)
Index: multipath-tools-130222/libmultipath/configure.c
===================================================================
@@ -20,7 +22,7 @@ Index: multipath-tools-130222/libmultipath/configure.c
return 1;
}
-+static void
++void
+trigger_uevents (struct multipath *mpp)
+{
+ struct pathgroup * pgp;
@@ -94,3 +96,26 @@ Index: multipath-tools-130222/multipath/main.c
printf("wwid '%s' added\n", refwwid);
else
printf("failed adding '%s' to wwids file\n",
+Index: multipath-tools-130222/libmultipath/configure.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/configure.h
++++ multipath-tools-130222/libmultipath/configure.h
+@@ -31,3 +31,4 @@ int coalesce_paths (struct vectors *vecs
+ int get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid);
+ int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh);
+ int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name);
++void trigger_uevents (struct multipath *mpp);
+Index: multipath-tools-130222/multipathd/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/main.c
++++ multipath-tools-130222/multipathd/main.c
+@@ -1435,7 +1435,8 @@ configure (struct vectors * vecs, int st
+
+ sync_maps_state(mpvec);
+ vector_foreach_slot(mpvec, mpp, i){
+- remember_wwid(mpp->wwid);
++ if (remember_wwid(mpp->wwid) > 0)
++ trigger_uevents(mpp);
+ update_map_pr(mpp);
+ }
+
diff --git a/0136-RHBZ-1304687-wait-for-map-add.patch b/0136-RHBZ-1304687-wait-for-map-add.patch
index 03deb1a..cd9cdee 100644
--- a/0136-RHBZ-1304687-wait-for-map-add.patch
+++ b/0136-RHBZ-1304687-wait-for-map-add.patch
@@ -332,7 +332,7 @@ Index: multipath-tools-130222/multipathd/main.c
}
if (count)
count--;
-@@ -1464,6 +1555,22 @@ configure (struct vectors * vecs, int st
+@@ -1465,6 +1556,22 @@ configure (struct vectors * vecs, int st
}
int
@@ -355,7 +355,7 @@ Index: multipath-tools-130222/multipathd/main.c
reconfigure (struct vectors * vecs)
{
struct config * old = conf;
-@@ -1543,12 +1650,18 @@ void
+@@ -1544,12 +1651,18 @@ void
handle_signals(void)
{
if (reconfig_sig && running_state == DAEMON_RUNNING) {
diff --git a/0150-RHBZ-1253913-fix-startup-msg.patch b/0150-RHBZ-1253913-fix-startup-msg.patch
index ca661e8..7dc5125 100644
--- a/0150-RHBZ-1253913-fix-startup-msg.patch
+++ b/0150-RHBZ-1253913-fix-startup-msg.patch
@@ -14,7 +14,7 @@ Index: multipath-tools-130222/multipathd/main.c
static sem_t exit_sem;
/*
-@@ -1704,6 +1705,12 @@ sigusr2 (int sig)
+@@ -1705,6 +1706,12 @@ sigusr2 (int sig)
}
static void
@@ -27,7 +27,7 @@ Index: multipath-tools-130222/multipathd/main.c
signal_init(void)
{
sigset_t set;
-@@ -1806,6 +1813,9 @@ child (void * param)
+@@ -1807,6 +1814,9 @@ child (void * param)
}
running_state = DAEMON_START;
@@ -37,7 +37,7 @@ Index: multipath-tools-130222/multipathd/main.c
condlog(2, "--------start up--------");
condlog(2, "read " DEFAULT_CONFIGFILE);
-@@ -1897,8 +1907,6 @@ child (void * param)
+@@ -1898,8 +1908,6 @@ child (void * param)
}
pthread_attr_destroy(&misc_attr);
@@ -46,7 +46,7 @@ Index: multipath-tools-130222/multipathd/main.c
update_timestamp(1);
/* Ignore errors, we can live without */
-@@ -1978,7 +1986,10 @@ daemonize(void)
+@@ -1979,7 +1987,10 @@ daemonize(void)
{
int pid;
int dev_null_fd;
@@ -57,7 +57,7 @@ Index: multipath-tools-130222/multipathd/main.c
if( (pid = fork()) < 0){
fprintf(stderr, "Failed first fork : %s\n", strerror(errno));
return -1;
-@@ -1986,10 +1997,13 @@ daemonize(void)
+@@ -1987,10 +1998,13 @@ daemonize(void)
else if (pid != 0)
return pid;
@@ -72,7 +72,7 @@ Index: multipath-tools-130222/multipathd/main.c
else if (pid != 0)
_exit(0);
-@@ -2000,30 +2014,34 @@ daemonize(void)
+@@ -2001,30 +2015,34 @@ daemonize(void)
if (dev_null_fd < 0){
fprintf(stderr, "cannot open /dev/null for input & output : %s\n",
strerror(errno));
@@ -111,7 +111,7 @@ Index: multipath-tools-130222/multipathd/main.c
}
int
-@@ -2102,10 +2120,12 @@ main (int argc, char *argv[])
+@@ -2103,10 +2121,12 @@ main (int argc, char *argv[])
if (err < 0)
/* error */
exit(1);
diff --git a/0159-UPBZ-1255885-udev-waits.patch b/0159-UPBZ-1255885-udev-waits.patch
index 9af0981..9e0921b 100644
--- a/0159-UPBZ-1255885-udev-waits.patch
+++ b/0159-UPBZ-1255885-udev-waits.patch
@@ -1,14 +1,11 @@
---
- kpartx/devmapper.c | 53 ++++++++++++++++++++++++++++++++++------------
- kpartx/devmapper.h | 4 +--
- kpartx/kpartx.c | 16 ++++++-------
- libmultipath/config.h | 1
- libmultipath/configure.c | 5 ++--
- libmultipath/devmapper.c | 48 +++++++++++++++++++++++++++++++----------
- libmultipath/devmapper.h | 2 -
- multipath/main.c | 2 -
- multipathd/cli_handlers.c | 4 +--
- 9 files changed, 92 insertions(+), 43 deletions(-)
+ kpartx/devmapper.c | 41 ++++++++++++++++++++++++++++-------------
+ kpartx/devmapper.h | 4 ++--
+ kpartx/kpartx.c | 16 ++++++++--------
+ libmultipath/config.h | 1 -
+ libmultipath/devmapper.c | 19 +++++++++++++------
+ multipath/main.c | 2 --
+ 6 files changed, 51 insertions(+), 32 deletions(-)
Index: multipath-tools-130222/kpartx/devmapper.c
===================================================================
@@ -43,7 +40,7 @@ Index: multipath-tools-130222/kpartx/devmapper.c
struct dm_task *dmt;
if (!(dmt = dm_task_create(task)))
-@@ -78,10 +74,23 @@ dm_simplecmd (int task, const char *name
+@@ -78,10 +74,17 @@ dm_simplecmd (int task, const char *name
if (no_flush)
dm_task_no_flush(dmt);
@@ -51,25 +48,19 @@ Index: multipath-tools-130222/kpartx/devmapper.c
+#ifdef LIBDM_API_COOKIE
+ if (!udev_sync)
+ udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
-+ if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags)) {
-+ dm_udev_complete(cookie);
++ if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
-+ }
+#endif
r = dm_task_run(dmt);
-
+#ifdef LIBDM_API_COOKIE
-+ if (udev_wait_flag) {
-+ if (!r)
-+ dm_udev_complete(cookie);
-+ else
-+ dm_udev_wait(cookie);
-+ }
++ if (udev_wait_flag)
++ dm_udev_wait(cookie);
+#endif
out:
dm_task_destroy(dmt);
return r;
-@@ -90,10 +99,14 @@ dm_simplecmd (int task, const char *name
+@@ -90,10 +93,14 @@ dm_simplecmd (int task, const char *name
extern int
dm_addmap (int task, const char *name, const char *target,
const char *params, uint64_t size, int ro, const char *uuid, int part,
@@ -85,7 +76,7 @@ Index: multipath-tools-130222/kpartx/devmapper.c
if (!(dmt = dm_task_create (task)))
return 0;
-@@ -128,10 +141,24 @@ dm_addmap (int task, const char *name, c
+@@ -128,10 +135,18 @@ dm_addmap (int task, const char *name, c
dm_task_no_open_count(dmt);
@@ -94,20 +85,14 @@ Index: multipath-tools-130222/kpartx/devmapper.c
+ if (!udev_sync)
+ udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
+ if (task == DM_DEVICE_CREATE &&
-+ !dm_task_set_cookie(dmt, &cookie, udev_flags)) {
-+ dm_udev_complete(cookie);
++ !dm_task_set_cookie(dmt, &cookie, udev_flags))
goto addout;
-+ }
+#endif
r = dm_task_run (dmt);
-
+#ifdef LIBDM_API_COOKIE
-+ if (task == DM_DEVICE_CREATE) {
-+ if (!r)
-+ dm_udev_complete(cookie);
-+ else
++ if (task == DM_DEVICE_CREATE)
+ dm_udev_wait(cookie);
-+ }
+#endif
addout:
dm_task_destroy (dmt);
@@ -214,29 +199,6 @@ Index: multipath-tools-130222/libmultipath/config.h
int reassign_maps;
int retain_hwhandler;
int detect_prio;
-Index: multipath-tools-130222/libmultipath/configure.c
-===================================================================
---- multipath-tools-130222.orig/libmultipath/configure.c
-+++ multipath-tools-130222/libmultipath/configure.c
-@@ -654,7 +654,8 @@ domap (struct multipath * mpp, char * pa
- case ACT_RELOAD:
- r = dm_addmap_reload(mpp, params);
- if (r)
-- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG);
-+ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias,
-+ 0, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG);
- break;
-
- case ACT_RESIZE:
-@@ -672,7 +673,7 @@ domap (struct multipath * mpp, char * pa
- if (r) {
- r = dm_addmap_reload(mpp, params);
- if (r)
-- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG);
-+ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, 0, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG);
- }
- break;
-
Index: multipath-tools-130222/libmultipath/devmapper.c
===================================================================
--- multipath-tools-130222.orig/libmultipath/devmapper.c
@@ -249,38 +211,21 @@ Index: multipath-tools-130222/libmultipath/devmapper.c
struct dm_task *dmt;
if (!(dmt = dm_task_create (task)))
-@@ -233,10 +234,18 @@ dm_simplecmd (int task, const char *name
+@@ -233,10 +234,12 @@ dm_simplecmd (int task, const char *name
if (do_deferred(deferred_remove))
dm_task_deferred_remove(dmt);
#endif
- if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags))
-+ if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags)) {
-+ dm_udev_complete(cookie);
++ if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags))
goto out;
-+ }
r = dm_task_run (dmt);
-+ if (udev_wait_flag) {
-+ if (!r)
-+ dm_udev_complete(cookie);
-+ else
++ if (udev_wait_flag)
+ udev_wait(cookie);
-+ }
out:
dm_task_destroy (dmt);
return r;
-@@ -248,8 +257,8 @@ dm_simplecmd_flush (int task, const char
- }
-
- extern int
--dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) {
-- return dm_simplecmd(task, name, 1, 1, udev_flags, 0);
-+dm_simplecmd_noflush (int task, const char *name, int needsync, uint16_t udev_flags) {
-+ return dm_simplecmd(task, name, 1, needsync, udev_flags, 0);
- }
-
- static int
-@@ -264,6 +273,7 @@ dm_addmap (int task, const char *target,
+@@ -264,6 +267,7 @@ dm_addmap (int task, const char *target,
int r = 0;
struct dm_task *dmt;
char *prefixed_uuid = NULL;
@@ -288,54 +233,21 @@ Index: multipath-tools-130222/libmultipath/devmapper.c
if (!(dmt = dm_task_create (task)))
return 0;
-@@ -304,10 +314,18 @@ dm_addmap (int task, const char *target,
+@@ -304,10 +308,12 @@ dm_addmap (int task, const char *target,
dm_task_no_open_count(dmt);
if (task == DM_DEVICE_CREATE &&
- !dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
-+ !dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) {
-+ dm_udev_complete(cookie);
++ !dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
goto freeout;
-+ }
r = dm_task_run (dmt);
-+ if (task == DM_DEVICE_CREATE) {
-+ if (!r)
-+ dm_udev_complete(cookie);
-+ else
++ if (task == DM_DEVICE_CREATE)
+ udev_wait(cookie);
-+ }
freeout:
if (prefixed_uuid)
FREE(prefixed_uuid);
-@@ -325,7 +343,8 @@ dm_addmap_create (struct multipath *mpp,
- for (ro = 0; ro <= 1; ro++) {
- int err;
-
-- if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, 1, ro))
-+ if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH,
-+ mpp, params, 1, ro))
- return 1;
- /*
- * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD.
-@@ -806,14 +825,14 @@ dm_suspend_and_flush_map (const char * m
- if (s)
- queue_if_no_path = 0;
- else
-- s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0, 0);
-+ s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 1, 0);
-
- if (!dm_flush_map(mapname)) {
- condlog(4, "multipath map %s removed", mapname);
- return 0;
- }
- condlog(2, "failed to remove multipath map %s", mapname);
-- dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 0);
-+ dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 1, 0);
- if (queue_if_no_path)
- s = dm_queue_if_no_path((char *)mapname, 1);
- return 1;
-@@ -1366,6 +1385,7 @@ dm_rename (const char * old, char * new)
+@@ -1366,6 +1372,7 @@ dm_rename (const char * old, char * new)
{
int r = 0;
struct dm_task *dmt;
@@ -343,7 +255,7 @@ Index: multipath-tools-130222/libmultipath/devmapper.c
if (dm_rename_partmaps(old, new))
return r;
-@@ -1381,14 +1401,18 @@ dm_rename (const char * old, char * new)
+@@ -1381,12 +1388,12 @@ dm_rename (const char * old, char * new)
dm_task_no_open_count(dmt);
@@ -354,40 +266,12 @@ Index: multipath-tools-130222/libmultipath/devmapper.c
goto out;
+ r = dm_task_run(dmt);
+
-+ if (!r)
-+ dm_udev_complete(cookie);
-+ else
-+ udev_wait(cookie);
++ udev_wait(cookie);
- r = 1;
out:
dm_task_destroy(dmt);
-+
return r;
- }
-
-@@ -1453,7 +1477,7 @@ int dm_reassign_table(const char *name,
- condlog(3, "%s: failed to reassign targets", name);
- goto out_reload;
- }
-- dm_simplecmd_noflush(DM_DEVICE_RESUME, name, MPATH_UDEV_RELOAD_FLAG);
-+ dm_simplecmd_noflush(DM_DEVICE_RESUME, name, 1, MPATH_UDEV_RELOAD_FLAG);
- }
- r = 1;
-
-Index: multipath-tools-130222/libmultipath/devmapper.h
-===================================================================
---- multipath-tools-130222.orig/libmultipath/devmapper.h
-+++ multipath-tools-130222/libmultipath/devmapper.h
-@@ -16,7 +16,7 @@ void dm_init(void);
- int dm_prereq (void);
- int dm_drv_version (unsigned int * version, char * str);
- int dm_simplecmd_flush (int, const char *, int, uint16_t);
--int dm_simplecmd_noflush (int, const char *, uint16_t);
-+int dm_simplecmd_noflush (int, const char *, int, uint16_t);
- int dm_addmap_create (struct multipath *mpp, char *params);
- int dm_addmap_reload (struct multipath *mpp, char *params);
- int dm_map_present (const char *);
Index: multipath-tools-130222/multipath/main.c
===================================================================
--- multipath-tools-130222.orig/multipath/main.c
@@ -401,25 +285,3 @@ Index: multipath-tools-130222/multipath/main.c
dm_lib_release();
dm_lib_exit();
-Index: multipath-tools-130222/multipathd/cli_handlers.c
-===================================================================
---- multipath-tools-130222.orig/multipathd/cli_handlers.c
-+++ multipath-tools-130222/multipathd/cli_handlers.c
-@@ -807,7 +807,7 @@ cli_suspend(void * v, char ** reply, int
- return 1;
- }
-
-- r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0);
-+ r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0, 0);
-
- condlog(2, "%s: suspend (operator)", param);
-
-@@ -837,7 +837,7 @@ cli_resume(void * v, char ** reply, int
- return 1;
- }
-
-- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0);
-+ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0, 0);
-
- condlog(2, "%s: resume (operator)", param);
-
diff --git a/0160-RH-udev-flags.patch b/0160-RH-udev-flags.patch
new file mode 100644
index 0000000..29a2c9c
--- /dev/null
+++ b/0160-RH-udev-flags.patch
@@ -0,0 +1,20 @@
+---
+ libmultipath/devmapper.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/devmapper.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/devmapper.c
++++ multipath-tools-130222/libmultipath/devmapper.c
+@@ -213,8 +213,9 @@ dm_prereq (void)
+ static int
+ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags, int deferred_remove) {
+ int r = 0;
+- int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME ||
+- task == DM_DEVICE_REMOVE));
++ int udev_wait_flag = ((need_sync && (task == DM_DEVICE_RESUME ||
++ task == DM_DEVICE_REMOVE)) ||
++ udev_flags);
+ uint32_t cookie = 0;
+ struct dm_task *dmt;
+
diff --git a/0161-RHBZ-1311659-no-kpartx.patch b/0161-RHBZ-1311659-no-kpartx.patch
new file mode 100644
index 0000000..0bce7f6
--- /dev/null
+++ b/0161-RHBZ-1311659-no-kpartx.patch
@@ -0,0 +1,618 @@
+---
+ libmultipath/config.c | 3 +
+ libmultipath/config.h | 3 +
+ libmultipath/configure.c | 15 +++--
+ libmultipath/defaults.h | 1
+ libmultipath/devmapper.c | 35 +++++++++----
+ libmultipath/devmapper.h | 8 ++-
+ libmultipath/dict.c | 114 +++++++++++++++++++++++++++++++++++++++++++++
+ libmultipath/propsel.c | 26 ++++++++++
+ libmultipath/propsel.h | 1
+ libmultipath/structs.h | 7 ++
+ multipath/multipath.conf.5 | 10 +++
+ multipath/multipath.rules | 1
+ multipathd/cli_handlers.c | 4 +
+ 13 files changed, 211 insertions(+), 17 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/config.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/config.c
++++ multipath-tools-130222/libmultipath/config.c
+@@ -343,6 +343,7 @@ merge_hwe (struct hwentry * dst, struct
+ merge_num(deferred_remove);
+ merge_num(delay_watch_checks);
+ merge_num(delay_wait_checks);
++ merge_num(skip_kpartx);
+
+ /*
+ * Make sure features is consistent with
+@@ -403,6 +404,7 @@ overwrite_hwe (struct hwentry * dst, str
+ overwrite_num(deferred_remove);
+ overwrite_num(delay_watch_checks);
+ overwrite_num(delay_wait_checks);
++ overwrite_num(skip_kpartx);
+
+ /*
+ * Make sure features is consistent with
+@@ -677,6 +679,7 @@ load_config (char * file, struct udev *u
+ conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY;
+ conf->new_bindings_in_boot = 0;
+ conf->uev_msg_delay = DEFAULT_UEV_MSG_DELAY;
++ conf->skip_kpartx = DEFAULT_SKIP_KPARTX;
+
+ /*
+ * preload default hwtable
+Index: multipath-tools-130222/libmultipath/config.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/config.h
++++ multipath-tools-130222/libmultipath/config.h
+@@ -64,6 +64,7 @@ struct hwentry {
+ int deferred_remove;
+ int delay_watch_checks;
+ int delay_wait_checks;
++ int skip_kpartx;
+ char * bl_product;
+ };
+
+@@ -90,6 +91,7 @@ struct mpentry {
+ int deferred_remove;
+ int delay_watch_checks;
+ int delay_wait_checks;
++ int skip_kpartx;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+@@ -143,6 +145,7 @@ struct config {
+ int new_bindings_in_boot;
+ int delayed_reconfig;
+ int uev_msg_delay;
++ int skip_kpartx;
+ unsigned int version[3];
+
+ char * dev;
+Index: multipath-tools-130222/libmultipath/configure.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/configure.c
++++ multipath-tools-130222/libmultipath/configure.c
+@@ -294,6 +294,7 @@ setup_map (struct multipath * mpp, char
+ select_deferred_remove(mpp);
+ select_delay_watch_checks(mpp);
+ select_delay_wait_checks(mpp);
++ select_skip_kpartx(mpp);
+
+ sysfs_set_scsi_tmo(mpp);
+ /*
+@@ -446,6 +447,7 @@ select_action (struct multipath * mpp, v
+ }
+ mpp->force_udev_reload = !pathcount(mpp, PATH_WILD);
+ if (cmpp->size != mpp->size) {
++ mpp->force_udev_reload = 1;
+ mpp->action = ACT_RESIZE;
+ condlog(3, "%s: set ACT_RESIZE (size change)",
+ mpp->alias);
+@@ -609,6 +611,7 @@ extern int
+ domap (struct multipath * mpp, char * params)
+ {
+ int r = 0;
++ uint16_t udev_flags = ((mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG) | ((mpp->skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0);
+
+ /*
+ * last chance to quit before touching the devmaps
+@@ -654,25 +657,27 @@ domap (struct multipath * mpp, char * pa
+ case ACT_RELOAD:
+ r = dm_addmap_reload(mpp, params);
+ if (r)
+- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG);
++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias,
++ udev_flags);
+ break;
+
+ case ACT_RESIZE:
+ r = dm_addmap_reload(mpp, params);
+ if (r)
+- r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1, 0);
++ r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1,
++ udev_flags);
+ break;
+
+ case ACT_RENAME:
+- r = dm_rename(mpp->alias_old, mpp->alias);
++ r = dm_rename(mpp->alias_old, mpp->alias, mpp->skip_kpartx);
+ break;
+
+ case ACT_RENAME2:
+- r = dm_rename(mpp->alias_old, mpp->alias);
++ r = dm_rename(mpp->alias_old, mpp->alias, mpp->skip_kpartx);
+ if (r) {
+ r = dm_addmap_reload(mpp, params);
+ if (r)
+- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG);
++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, udev_flags);
+ }
+ break;
+
+Index: multipath-tools-130222/libmultipath/defaults.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/defaults.h
++++ multipath-tools-130222/libmultipath/defaults.h
+@@ -24,6 +24,7 @@
+ #define DEFAULT_RETRIGGER_DELAY 10
+ #define DEFAULT_RETRIGGER_TRIES 3
+ #define DEFAULT_UEV_MSG_DELAY 30
++#define DEFAULT_SKIP_KPARTX SKIP_KPARTX_OFF
+
+ #define DEFAULT_CHECKINT 5
+ #define MAX_CHECKINT(a) (a << 2)
+Index: multipath-tools-130222/libmultipath/devmapper.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/devmapper.c
++++ multipath-tools-130222/libmultipath/devmapper.c
+@@ -262,13 +262,14 @@ dm_device_remove (const char *name, int
+ deferred_remove);
+ }
+
+-extern int
++static int
+ dm_addmap (int task, const char *target, struct multipath *mpp, char * params,
+- int use_uuid, int ro) {
++ int use_uuid, int ro, int skip_kpartx) {
+ int r = 0;
+ struct dm_task *dmt;
+ char *prefixed_uuid = NULL;
+ uint32_t cookie = 0;
++ uint16_t udev_flags = ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0);
+
+ if (!(dmt = dm_task_create (task)))
+ return 0;
+@@ -309,7 +310,7 @@ dm_addmap (int task, const char *target,
+ dm_task_no_open_count(dmt);
+
+ if (task == DM_DEVICE_CREATE &&
+- !dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
++ !dm_task_set_cookie(dmt, &cookie, udev_flags))
+ goto freeout;
+ r = dm_task_run (dmt);
+
+@@ -332,7 +333,8 @@ dm_addmap_create (struct multipath *mpp,
+ for (ro = 0; ro <= 1; ro++) {
+ int err;
+
+- if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, 1, ro))
++ if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH,
++ mpp, params, 1, ro, mpp->skip_kpartx))
+ return 1;
+ /*
+ * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD.
+@@ -354,11 +356,11 @@ dm_addmap_create (struct multipath *mpp,
+
+ extern int
+ dm_addmap_reload (struct multipath *mpp, char *params) {
+- if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW))
++ if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW, SKIP_KPARTX_OFF))
+ return 1;
+ if (errno != EROFS)
+ return 0;
+- return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO);
++ return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO, SKIP_KPARTX_OFF);
+ }
+
+ extern int
+@@ -720,6 +722,12 @@ out:
+ }
+
+ static int
++has_partmap(const char *name, void *data)
++{
++ return 1;
++}
++
++static int
+ partmap_in_use(const char *name, void *data)
+ {
+ int part_count, *ret_count = (int *)data;
+@@ -798,10 +806,16 @@ dm_suspend_and_flush_map (const char * m
+ int s = 0, queue_if_no_path = 0;
+ unsigned long long mapsize;
+ char params[PARAMS_SIZE] = {0};
++ int udev_flags = 0;
+
+ if (!dm_is_mpath(mapname))
+ return 0; /* nothing to do */
+
++ /* if the device currently has no partitions, do not
++ run kpartx on it if you fail to delete it */
++ if (do_foreach_partmaps(mapname, has_partmap, NULL) == 0)
++ udev_flags |= MPATH_UDEV_NO_KPARTX_FLAG;
++
+ if (!dm_get_map(mapname, &mapsize, params)) {
+ if (strstr(params, "queue_if_no_path"))
+ queue_if_no_path = 1;
+@@ -820,7 +834,7 @@ dm_suspend_and_flush_map (const char * m
+ return 0;
+ }
+ condlog(2, "failed to remove multipath map %s", mapname);
+- dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 0);
++ dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, udev_flags);
+ if (queue_if_no_path)
+ s = dm_queue_if_no_path((char *)mapname, 1);
+ return 1;
+@@ -1349,7 +1363,7 @@ rename_partmap (const char *name, void *
+ for (offset = strlen(rd->old); name[offset] && !(isdigit(name[offset])); offset++); /* do nothing */
+ snprintf(buff, PARAMS_SIZE, "%s%s%s", rd->new, rd->delim,
+ name + offset);
+- dm_rename(name, buff);
++ dm_rename(name, buff, SKIP_KPARTX_OFF);
+ condlog(4, "partition map %s renamed", name);
+ return 0;
+ }
+@@ -1369,11 +1383,12 @@ dm_rename_partmaps (const char * old, ch
+ }
+
+ int
+-dm_rename (const char * old, char * new)
++dm_rename (const char * old, char * new, int skip_kpartx)
+ {
+ int r = 0;
+ struct dm_task *dmt;
+ uint32_t cookie;
++ uint16_t udev_flags = ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0);
+
+ if (dm_rename_partmaps(old, new))
+ return r;
+@@ -1389,7 +1404,7 @@ dm_rename (const char * old, char * new)
+
+ dm_task_no_open_count(dmt);
+
+- if (!dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
++ if (!dm_task_set_cookie(dmt, &cookie, udev_flags))
+ goto out;
+ r = dm_task_run(dmt);
+
+Index: multipath-tools-130222/libmultipath/devmapper.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/devmapper.h
++++ multipath-tools-130222/libmultipath/devmapper.h
+@@ -12,6 +12,12 @@
+ #define MPATH_UDEV_RELOAD_FLAG 0
+ #endif
+
++#ifdef DM_SUBSYSTEM_UDEV_FLAG1
++#define MPATH_UDEV_NO_KPARTX_FLAG DM_SUBSYSTEM_UDEV_FLAG1
++#else
++#define MPATH_UDEV_NO_KPARTX_FLAG 0
++#endif
++
+ void dm_init(void);
+ int dm_prereq (void);
+ int dm_drv_version (unsigned int * version, char * str);
+@@ -47,7 +53,7 @@ int dm_remove_partmaps (const char * map
+ int deferred_remove);
+ int dm_get_uuid(char *name, char *uuid);
+ int dm_get_info (char * mapname, struct dm_info ** dmi);
+-int dm_rename (const char * old, char * new);
++int dm_rename (const char * old, char * new, int skip_kpartx);
+ int dm_reassign(const char * mapname);
+ int dm_reassign_table(const char *name, char *old, char *new);
+ int dm_setgeometry(struct multipath *mpp);
+Index: multipath-tools-130222/libmultipath/dict.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/dict.c
++++ multipath-tools-130222/libmultipath/dict.c
+@@ -779,6 +779,29 @@ def_deferred_remove_handler(vector strve
+ }
+
+ static int
++def_skip_kpartx_handler(vector strvec)
++{
++ char * buff;
++
++ buff = set_value(strvec);
++
++ if (!buff)
++ return 1;
++
++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "0")))
++ conf->skip_kpartx = SKIP_KPARTX_OFF;
++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "1")))
++ conf->skip_kpartx = SKIP_KPARTX_ON;
++ else
++ conf->skip_kpartx = DEFAULT_SKIP_KPARTX;
++
++ FREE(buff);
++ return 0;
++}
++
++static int
+ def_ignore_new_boot_devs_handler(vector strvec)
+ {
+ char * buff;
+@@ -1629,6 +1652,33 @@ hw_deferred_remove_handler(vector strvec
+ }
+
+ static int
++hw_skip_kpartx_handler(vector strvec)
++{
++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable);
++ char * buff;
++
++ if (!hwe)
++ return 1;
++
++ buff = set_value(strvec);
++
++ if (!buff)
++ return 1;
++
++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "0")))
++ hwe->skip_kpartx = SKIP_KPARTX_OFF;
++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "1")))
++ hwe->skip_kpartx = SKIP_KPARTX_ON;
++ else
++ hwe->skip_kpartx = SKIP_KPARTX_UNDEF;
++
++ FREE(buff);
++ return 0;
++}
++
++static int
+ hw_delay_watch_checks_handler(vector strvec)
+ {
+ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable);
+@@ -2154,6 +2204,32 @@ mp_deferred_remove_handler(vector strvec
+ }
+
+ static int
++mp_skip_kpartx_handler(vector strvec)
++{
++ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable);
++ char * buff;
++
++ if (!mpe)
++ return 1;
++
++ buff = set_value(strvec);
++ if (!buff)
++ return 1;
++
++ if ((strlen(buff) == 2 && strcmp(buff, "no") == 0) ||
++ (strlen(buff) == 1 && strcmp(buff, "0") == 0))
++ mpe->skip_kpartx = SKIP_KPARTX_OFF;
++ else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) ||
++ (strlen(buff) == 1 && strcmp(buff, "1") == 0))
++ mpe->skip_kpartx = SKIP_KPARTX_ON;
++ else
++ mpe->skip_kpartx = SKIP_KPARTX_UNDEF;
++
++ FREE(buff);
++ return 0;
++}
++
++static int
+ mp_delay_watch_checks_handler(vector strvec)
+ {
+ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable);
+@@ -2461,6 +2537,19 @@ snprint_mp_deferred_remove (char * buff,
+ }
+
+ static int
++snprint_mp_skip_kpartx (char * buff, int len, void * data)
++{
++ struct mpentry * mpe = (struct mpentry *)data;
++
++ if (mpe->skip_kpartx == SKIP_KPARTX_UNDEF)
++ return 0;
++ else if (mpe->skip_kpartx == SKIP_KPARTX_OFF)
++ return snprintf(buff, len, "no");
++ else
++ return snprintf(buff, len, "yes");
++}
++
++static int
+ snprint_mp_delay_watch_checks(char * buff, int len, void * data)
+ {
+ struct mpentry * mpe = (struct mpentry *)data;
+@@ -2813,6 +2902,19 @@ snprint_hw_deferred_remove(char * buff,
+ }
+
+ static int
++snprint_hw_skip_kpartx(char * buff, int len, void * data)
++{
++ struct hwentry * hwe = (struct hwentry *)data;
++
++ if (hwe->skip_kpartx == SKIP_KPARTX_ON)
++ return snprintf(buff, len, "yes");
++ else if (hwe->skip_kpartx == SKIP_KPARTX_OFF)
++ return snprintf(buff, len, "no");
++ else
++ return 0;
++}
++
++static int
+ snprint_hw_delay_watch_checks(char * buff, int len, void * data)
+ {
+ struct hwentry * hwe = (struct hwentry *)data;
+@@ -3231,6 +3333,15 @@ snprint_def_deferred_remove(char * buff,
+ }
+
+ static int
++snprint_def_skip_kpartx(char * buff, int len, void * data)
++{
++ if (conf->skip_kpartx == SKIP_KPARTX_ON)
++ return snprintf(buff, len, "yes");
++ else
++ return snprintf(buff, len, "no");
++}
++
++static int
+ snprint_def_ignore_new_boot_devs(char * buff, int len, void * data)
+ {
+ if (conf->ignore_new_boot_devs == 1)
+@@ -3364,6 +3475,7 @@ init_keywords(void)
+ install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync);
+ install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove);
+ install_keyword("ignore_new_boot_devs", &def_ignore_new_boot_devs_handler, &snprint_def_ignore_new_boot_devs);
++ install_keyword("skip_kpartx", &def_skip_kpartx_handler, &snprint_def_skip_kpartx);
+ install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir);
+ install_keyword("delay_watch_checks", &def_delay_watch_checks_handler, &snprint_def_delay_watch_checks);
+ install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks);
+@@ -3438,6 +3550,7 @@ init_keywords(void)
+ install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove);
+ install_keyword("delay_watch_checks", &hw_delay_watch_checks_handler, &snprint_hw_delay_watch_checks);
+ install_keyword("delay_wait_checks", &hw_delay_wait_checks_handler, &snprint_hw_delay_wait_checks);
++ install_keyword("skip_kpartx", &hw_skip_kpartx_handler, &snprint_hw_skip_kpartx);
+ install_sublevel_end();
+
+ install_keyword_root("multipaths", &multipaths_handler);
+@@ -3465,5 +3578,6 @@ init_keywords(void)
+ install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove);
+ install_keyword("delay_watch_checks", &mp_delay_watch_checks_handler, &snprint_mp_delay_watch_checks);
+ install_keyword("delay_wait_checks", &mp_delay_wait_checks_handler, &snprint_mp_delay_wait_checks);
++ install_keyword("skip_kpartx", &mp_skip_kpartx_handler, &snprint_mp_skip_kpartx);
+ install_sublevel_end();
+ }
+Index: multipath-tools-130222/libmultipath/propsel.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/propsel.c
++++ multipath-tools-130222/libmultipath/propsel.c
+@@ -854,3 +854,29 @@ select_delay_wait_checks (struct multipa
+ condlog(3, "delay_wait_checks = DISABLED (internal default)");
+ return 0;
+ }
++
++extern int
++select_skip_kpartx (struct multipath * mp)
++{
++ if (mp->mpe && mp->mpe->skip_kpartx != SKIP_KPARTX_UNDEF) {
++ mp->skip_kpartx = mp->mpe->skip_kpartx;
++ condlog(3, "skip_kpartx = %i (multipath setting)",
++ mp->skip_kpartx);
++ return 0;
++ }
++ if (mp->hwe && mp->hwe->skip_kpartx != SKIP_KPARTX_UNDEF) {
++ mp->skip_kpartx = mp->hwe->skip_kpartx;
++ condlog(3, "skip_kpartx = %i (controler setting)",
++ mp->skip_kpartx);
++ return 0;
++ }
++ if (conf->skip_kpartx != SKIP_KPARTX_UNDEF) {
++ mp->skip_kpartx = conf->skip_kpartx;
++ condlog(3, "skip_kpartx = %i (config file default)",
++ mp->skip_kpartx);
++ return 0;
++ }
++ mp->skip_kpartx = DEFAULT_SKIP_KPARTX;
++ condlog(3, "skip_kpartx = DISABLED (internal default)");
++ return 0;
++}
+Index: multipath-tools-130222/libmultipath/propsel.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/propsel.h
++++ multipath-tools-130222/libmultipath/propsel.h
+@@ -23,3 +23,4 @@ int select_detect_prio(struct path * pp)
+ int select_deferred_remove(struct multipath *mp);
+ int select_delay_watch_checks (struct multipath * mp);
+ int select_delay_wait_checks (struct multipath * mp);
++int select_skip_kpartx (struct multipath * mp);
+Index: multipath-tools-130222/libmultipath/structs.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/structs.h
++++ multipath-tools-130222/libmultipath/structs.h
+@@ -121,6 +121,12 @@ enum deferred_remove_states {
+ DEFERRED_REMOVE_IN_PROGRESS,
+ };
+
++enum skip_kpartx_states {
++ SKIP_KPARTX_UNDEF,
++ SKIP_KPARTX_OFF,
++ SKIP_KPARTX_ON,
++};
++
+ enum scsi_protocol {
+ SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */
+ SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */
+@@ -236,6 +242,7 @@ struct multipath {
+ int delay_watch_checks;
+ int delay_wait_checks;
+ int force_udev_reload;
++ int skip_kpartx;
+ unsigned int dev_loss;
+ uid_t uid;
+ gid_t gid;
+Index: multipath-tools-130222/multipath/multipath.rules
+===================================================================
+--- multipath-tools-130222.orig/multipath/multipath.rules
++++ multipath-tools-130222/multipath/multipath.rules
+@@ -44,6 +44,7 @@ KERNEL!="dm-*", GOTO="end_mpath"
+ ENV{DM_UUID}=="mpath-?*|part[0-9]*-mpath-?*", OPTIONS+="link_priority=10"
+ ACTION!="change", GOTO="end_mpath"
+ ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath"
++ENV{DM_SUBSYSTEM_UDEV_FLAG1}=="1", GOTO="end_mpath"
+ ENV{DM_ACTIVATION}=="1", ENV{DM_MULTIPATH_NEED_KPARTX}="1"
+ ENV{DM_SUSPENDED}=="1", GOTO="end_mpath"
+ ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath"
+Index: multipath-tools-130222/multipathd/cli_handlers.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli_handlers.c
++++ multipath-tools-130222/multipathd/cli_handlers.c
+@@ -825,19 +825,21 @@ cli_resume(void * v, char ** reply, int
+ char * param = get_keyparam(v, MAP);
+ int r;
+ struct multipath * mpp;
++ uint16_t udev_flags;
+
+ param = convert_dev(param, 0);
+ mpp = find_mp_by_alias(vecs->mpvec, param);
+ if (!mpp)
+ return 1;
+
++ udev_flags = (mpp->skip_kpartx)? MPATH_UDEV_NO_KPARTX_FLAG : 0;
+ if (mpp->wait_for_udev) {
+ condlog(2, "%s: device not fully created, failing resume",
+ mpp->alias);
+ return 1;
+ }
+
+- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0);
++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, udev_flags);
+
+ condlog(2, "%s: resume (operator)", param);
+
+Index: multipath-tools-130222/multipath/multipath.conf.5
+===================================================================
+--- multipath-tools-130222.orig/multipath/multipath.conf.5
++++ multipath-tools-130222/multipath/multipath.conf.5
+@@ -505,6 +505,12 @@ message. This warning message will print
+ .I missing_uev_msg_delay
+ seconds until the uevent is received. the default is
+ .I 30
++.TP
++.B skip_kpartx
++If set to
++.I yes
++, kpartx will not automatically create partitions on the device. The default is
++.I no
+ .
+ .SH "blacklist section"
+ The
+@@ -612,6 +618,8 @@ section:
+ .B delay_watch_checks
+ .TP
+ .B delay_wait_checks
++.TP
++.B skip_kpartx
+ .RE
+ .PD
+ .LP
+@@ -708,6 +716,8 @@ section:
+ .B delay_watch_checks
+ .TP
+ .B delay_wait_checks
++.TP
++.B skip_kpartx
+ .RE
+ .PD
+ .LP
diff --git a/0162-RHBZ-1333331-huawei-config.patch b/0162-RHBZ-1333331-huawei-config.patch
new file mode 100644
index 0000000..7b97e07
--- /dev/null
+++ b/0162-RHBZ-1333331-huawei-config.patch
@@ -0,0 +1,24 @@
+---
+ libmultipath/hwtable.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+Index: multipath-tools-130222/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/hwtable.c
++++ multipath-tools-130222/libmultipath/hwtable.c
+@@ -1182,6 +1182,15 @@ static struct hwentry default_hw[] = {
+ .dev_loss = 60,
+ .prio_args = NULL,
+ },
++ {
++ .vendor = "HUAWEI",
++ .product = "XSG1",
++ .features = DEFAULT_FEATURES,
++ .hwhandler = DEFAULT_HWHANDLER,
++ .pgpolicy = MULTIBUS,
++ .pgfailback = -FAILBACK_IMMEDIATE,
++ .checker_name = TUR,
++ },
+ /*
+ * EOL
+ */
diff --git a/0163-UPBZ-1333492-resize-map.patch b/0163-UPBZ-1333492-resize-map.patch
new file mode 100644
index 0000000..cc24b6f
--- /dev/null
+++ b/0163-UPBZ-1333492-resize-map.patch
@@ -0,0 +1,24 @@
+---
+ multipathd/cli_handlers.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+Index: multipath-tools-130222/multipathd/cli_handlers.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli_handlers.c
++++ multipath-tools-130222/multipathd/cli_handlers.c
+@@ -571,6 +571,7 @@ int resize_map(struct multipath *mpp, un
+ struct vectors * vecs)
+ {
+ char params[PARAMS_SIZE] = {0};
++ unsigned long long orig_size = mpp->size;
+
+ mpp->size = size;
+ update_mpp_paths(mpp, vecs->pathvec);
+@@ -579,6 +580,7 @@ int resize_map(struct multipath *mpp, un
+ if (domap(mpp, params) <= 0) {
+ condlog(0, "%s: failed to resize map : %s", mpp->alias,
+ strerror(errno));
++ mpp->size = orig_size;
+ return 1;
+ }
+ return 0;
diff --git a/0164-RHBZ-1311463-dos-part-rollover.patch b/0164-RHBZ-1311463-dos-part-rollover.patch
new file mode 100644
index 0000000..dc511f2
--- /dev/null
+++ b/0164-RHBZ-1311463-dos-part-rollover.patch
@@ -0,0 +1,17 @@
+---
+ kpartx/dos.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools-130222/kpartx/dos.c
+===================================================================
+--- multipath-tools-130222.orig/kpartx/dos.c
++++ multipath-tools-130222/kpartx/dos.c
+@@ -78,7 +78,7 @@ read_dos_pt(int fd, struct slice all, st
+ unsigned long offset = all.start;
+ int i, n=4;
+ unsigned char *bp;
+- int sector_size_mul = get_sector_size(fd)/512;
++ uint64_t sector_size_mul = get_sector_size(fd)/512;
+
+ bp = (unsigned char *)getblock(fd, offset);
+ if (bp == NULL)
diff --git a/0165-UPBZ-1341748-MSA-2040-conf.patch b/0165-UPBZ-1341748-MSA-2040-conf.patch
new file mode 100644
index 0000000..6c6e64a
--- /dev/null
+++ b/0165-UPBZ-1341748-MSA-2040-conf.patch
@@ -0,0 +1,30 @@
+---
+ libmultipath/hwtable.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+Index: multipath-tools-130222/libmultipath/hwtable.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/hwtable.c
++++ multipath-tools-130222/libmultipath/hwtable.c
+@@ -175,6 +175,21 @@ static struct hwentry default_hw[] = {
+ .prio_name = PRIO_ALUA,
+ .prio_args = NULL,
+ },
++ {
++ /* HP MSA 1040/2040 product family */
++ .vendor = "HP",
++ .product = "MSA (1|2)040 SA(N|S)",
++ .features = DEFAULT_FEATURES,
++ .hwhandler = DEFAULT_HWHANDLER,
++ .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,
++ .prio_args = NULL,
++ },
+
+ {
+ /* HP SVSP */
diff --git a/0166-RHBZ-1323429-dont-allow-new-wwid.patch b/0166-RHBZ-1323429-dont-allow-new-wwid.patch
new file mode 100644
index 0000000..b0fc664
--- /dev/null
+++ b/0166-RHBZ-1323429-dont-allow-new-wwid.patch
@@ -0,0 +1,24 @@
+---
+ libmultipath/dmparser.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+Index: multipath-tools-130222/libmultipath/dmparser.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/dmparser.c
++++ multipath-tools-130222/libmultipath/dmparser.c
+@@ -360,6 +360,15 @@ disassemble_map (vector pathvec, char *
+ else if (!strlen(pp->wwid))
+ strncpy(pp->wwid, mpp->wwid, WWID_SIZE);
+
++ /*
++ * Something went wrong. Likely the user changed the
++ * path uid_attribute after creating a device
++ */
++ else if (strcmp(pp->wwid, mpp->wwid) != 0) {
++ condlog(0, "%s: path wwid appears to have changed. Using old wwid.\n", pp->dev_t);
++ strncpy(pp->wwid, mpp->wwid, WWID_SIZE);
++ }
++
+ pgp->id ^= (long)pp;
+ pp->pgindex = i + 1;
+
diff --git a/0167-RHBZ-1335176-fix-show-cmds.patch b/0167-RHBZ-1335176-fix-show-cmds.patch
new file mode 100644
index 0000000..55154b6
--- /dev/null
+++ b/0167-RHBZ-1335176-fix-show-cmds.patch
@@ -0,0 +1,138 @@
+---
+ libmultipath/print.c | 7 +++++++
+ libmultipath/structs.h | 1 +
+ libmultipath/structs_vec.c | 24 ++++++++++++++----------
+ multipathd/cli_handlers.c | 11 ++++++++++-
+ multipathd/main.c | 2 ++
+ 5 files changed, 34 insertions(+), 11 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/print.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/print.c
++++ multipath-tools-130222/libmultipath/print.c
+@@ -248,6 +248,12 @@ snprint_q_timeouts (char * buff, size_t
+ }
+
+ static int
++snprint_map_failures (char * buff, size_t len, struct multipath * mpp)
++{
++ return snprint_uint(buff, len, mpp->stat_map_failures);
++}
++
++static int
+ snprint_multipath_uuid (char * buff, size_t len, struct multipath * mpp)
+ {
+ return snprint_str(buff, len, mpp->wwid);
+@@ -546,6 +552,7 @@ struct multipath_data mpd[] = {
+ {'t', "dm-st", 0, snprint_dm_map_state},
+ {'S', "size", 0, snprint_multipath_size},
+ {'f', "features", 0, snprint_features},
++ {'x', "failures", 0, snprint_map_failures},
+ {'h', "hwhandler", 0, snprint_hwhandler},
+ {'A', "action", 0, snprint_action},
+ {'0', "path_faults", 0, snprint_path_faults},
+Index: multipath-tools-130222/libmultipath/structs.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/structs.h
++++ multipath-tools-130222/libmultipath/structs.h
+@@ -270,6 +270,7 @@ struct multipath {
+ unsigned int stat_map_loads;
+ unsigned int stat_total_queueing_time;
+ unsigned int stat_queueing_timeouts;
++ unsigned int stat_map_failures;
+
+ /* checkers shared data */
+ void * mpcontext;
+Index: multipath-tools-130222/libmultipath/structs_vec.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/structs_vec.c
++++ multipath-tools-130222/libmultipath/structs_vec.c
+@@ -579,16 +579,20 @@ int update_multipath (struct vectors *ve
+ */
+ void update_queue_mode_del_path(struct multipath *mpp)
+ {
+- if (--mpp->nr_active == 0 && mpp->no_path_retry > 0) {
+- /*
+- * Enter retry mode.
+- * meaning of +1: retry_tick may be decremented in
+- * checkerloop before starting retry.
+- */
+- mpp->stat_queueing_timeouts++;
+- mpp->retry_tick = mpp->no_path_retry * conf->checkint + 1;
+- condlog(1, "%s: Entering recovery mode: max_retries=%d",
+- mpp->alias, mpp->no_path_retry);
++ if (--mpp->nr_active == 0) {
++ if (mpp->no_path_retry > 0) {
++ /*
++ * Enter retry mode.
++ * meaning of +1: retry_tick may be decremented in
++ * checkerloop before starting retry.
++ */
++ mpp->stat_queueing_timeouts++;
++ mpp->retry_tick = mpp->no_path_retry *
++ conf->checkint + 1;
++ condlog(1, "%s: Entering recovery mode: max_retries=%d",
++ mpp->alias, mpp->no_path_retry);
++ } else if (mpp->no_path_retry != NO_PATH_RETRY_QUEUE)
++ mpp->stat_map_failures++;
+ }
+ condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
+ }
+Index: multipath-tools-130222/multipathd/cli_handlers.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli_handlers.c
++++ multipath-tools-130222/multipathd/cli_handlers.c
+@@ -319,9 +319,14 @@ show_maps (char ** r, int *len, struct v
+ c += snprint_multipath_header(c, reply + maxlen - c,
+ style);
+
+- 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(c, reply + maxlen - c,
+ style, mpp, pretty);
++ }
+
+ again = ((c - reply) == (maxlen - 1));
+
+@@ -742,6 +747,8 @@ cli_disable_queueing(void *v, char **rep
+ return 1;
+ }
+
++ if (mpp->nr_active == 0)
++ mpp->stat_map_failures++;
+ mpp->retry_tick = 0;
+ dm_queue_if_no_path(mpp->alias, 0);
+ return 0;
+@@ -756,6 +763,8 @@ cli_disable_all_queueing(void *v, char *
+
+ condlog(2, "disable queueing (operator)");
+ vector_foreach_slot(vecs->mpvec, mpp, i) {
++ if (mpp->nr_active == 0)
++ mpp->stat_map_failures++;
+ mpp->retry_tick = 0;
+ dm_queue_if_no_path(mpp->alias, 0);
+ }
+Index: multipath-tools-130222/multipathd/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/main.c
++++ multipath-tools-130222/multipathd/main.c
+@@ -716,6 +716,7 @@ ev_remove_path (struct path *pp, struct
+ mpp->retry_tick = 0;
+ mpp->no_path_retry = NO_PATH_RETRY_FAIL;
+ mpp->flush_on_last_del = FLUSH_IN_PROGRESS;
++ mpp->stat_map_failures++;
+ dm_queue_if_no_path(mpp->alias, 0);
+ }
+ if (!flush_map(mpp, vecs, 1)) {
+@@ -1184,6 +1185,7 @@ retry_count_tick(vector mpvec)
+ mpp->stat_total_queueing_time++;
+ condlog(4, "%s: Retrying.. No active path", mpp->alias);
+ if(--mpp->retry_tick == 0) {
++ mpp->stat_map_failures++;
+ dm_queue_if_no_path(mpp->alias, 0);
+ condlog(2, "%s: Disable queueing", mpp->alias);
+ }
diff --git a/0168-RHBZ-1347769-shared-lock.patch b/0168-RHBZ-1347769-shared-lock.patch
new file mode 100644
index 0000000..084d112
--- /dev/null
+++ b/0168-RHBZ-1347769-shared-lock.patch
@@ -0,0 +1,17 @@
+---
+ libmultipath/configure.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: multipath-tools-130222/libmultipath/configure.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/configure.c
++++ multipath-tools-130222/libmultipath/configure.c
+@@ -552,7 +552,7 @@ lock_multipath (struct multipath * mpp,
+ if (!pgp->paths)
+ continue;
+ vector_foreach_slot(pgp->paths, pp, j) {
+- if (lock && flock(pp->fd, LOCK_EX | LOCK_NB) &&
++ if (lock && flock(pp->fd, LOCK_SH | LOCK_NB) &&
+ errno == EWOULDBLOCK)
+ goto fail;
+ else if (!lock)
diff --git a/0169-UPBZ-1353357-json-output.patch b/0169-UPBZ-1353357-json-output.patch
new file mode 100644
index 0000000..14fa840
--- /dev/null
+++ b/0169-UPBZ-1353357-json-output.patch
@@ -0,0 +1,549 @@
+---
+ libmultipath/print.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++
+ libmultipath/print.h | 61 ++++++++++++
+ multipathd/cli.c | 3
+ multipathd/cli.h | 2
+ multipathd/cli_handlers.c | 93 +++++++++++++++++++
+ multipathd/cli_handlers.h | 2
+ multipathd/main.c | 2
+ multipathd/multipathd.8 | 9 +
+ 8 files changed, 393 insertions(+), 1 deletion(-)
+
+Index: multipath-tools-130222/libmultipath/print.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/print.c
++++ multipath-tools-130222/libmultipath/print.c
+@@ -269,6 +269,61 @@ snprint_multipath_vpr (char * buff, size
+ pp->vendor_id, pp->product_id);
+ }
+
++
++static int
++snprint_multipath_vend (char * buff, size_t len, struct multipath * mpp)
++{
++ struct pathgroup * pgp;
++ struct path * pp;
++ int i, j;
++
++ vector_foreach_slot(mpp->pg, pgp, i) {
++ if (!pgp)
++ continue;
++ vector_foreach_slot(pgp->paths, pp, j) {
++ if (strlen(pp->vendor_id))
++ return snprintf(buff, len, "%s", pp->vendor_id);
++ }
++ }
++ return snprintf(buff, len, "##");
++}
++
++static int
++snprint_multipath_prod (char * buff, size_t len, struct multipath * mpp)
++{
++ struct pathgroup * pgp;
++ struct path * pp;
++ int i, j;
++
++ vector_foreach_slot(mpp->pg, pgp, i) {
++ if (!pgp)
++ continue;
++ vector_foreach_slot(pgp->paths, pp, j) {
++ if (strlen(pp->product_id))
++ return snprintf(buff, len, "%s", pp->product_id);
++ }
++ }
++ return snprintf(buff, len, "##");
++}
++
++static int
++snprint_multipath_rev (char * buff, size_t len, struct multipath * mpp)
++{
++ struct pathgroup * pgp;
++ struct path * pp;
++ int i, j;
++
++ vector_foreach_slot(mpp->pg, pgp, i) {
++ if (!pgp)
++ continue;
++ vector_foreach_slot(pgp->paths, pp, j) {
++ if (strlen(pp->rev))
++ return snprintf(buff, len, "%s", pp->rev);
++ }
++ }
++ return snprintf(buff, len, "##");
++}
++
+ static int
+ snprint_action (char * buff, size_t len, struct multipath * mpp)
+ {
+@@ -561,6 +616,9 @@ struct multipath_data mpd[] = {
+ {'3', "total_q_time", 0, snprint_total_q_time},
+ {'4', "q_timeouts", 0, snprint_q_timeouts},
+ {'s', "vend/prod/rev", 0, snprint_multipath_vpr},
++ {'v', "vend", 0, snprint_multipath_vend},
++ {'p', "prod", 0, snprint_multipath_prod},
++ {'e', "rev", 0, snprint_multipath_rev},
+ {0, NULL, 0 , NULL}
+ };
+
+@@ -983,6 +1041,170 @@ snprint_multipath_topology (char * buff,
+ return fwd;
+ }
+
++static int
++snprint_json (char * buff, int len, int indent, char *json_str)
++{
++ int fwd = 0, i;
++
++ for (i = 0; i < indent; i++) {
++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_INDENT);
++ if (fwd > len)
++ return fwd;
++ }
++
++ fwd += snprintf(buff + fwd, len - fwd, "%s", json_str);
++ return fwd;
++}
++
++static int
++snprint_json_header (char * buff, int len)
++{
++ int fwd = 0;
++
++ fwd += snprint_json(buff, len, 0, PRINT_JSON_START_ELEM);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_START_VERSION,
++ PRINT_JSON_MAJOR_VERSION, PRINT_JSON_MINOR_VERSION);
++ return fwd;
++}
++
++static int
++snprint_json_elem_footer (char * buff, int len, int indent, int last)
++{
++ int fwd = 0, i;
++
++ for (i = 0; i < indent; i++) {
++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_INDENT);
++ if (fwd > len)
++ return fwd;
++ }
++
++ if (last == 1)
++ fwd += snprintf(buff + fwd, len - fwd, "%s", PRINT_JSON_END_LAST_ELEM);
++ else
++ fwd += snprintf(buff + fwd, len - fwd, "%s", PRINT_JSON_END_ELEM);
++ return fwd;
++}
++
++static int
++snprint_multipath_fields_json (char * buff, int len,
++ struct multipath * mpp, int last)
++{
++ int i, j, fwd = 0;
++ struct path *pp;
++ struct pathgroup *pgp;
++
++ fwd += snprint_multipath(buff, len, PRINT_JSON_MAP, mpp, 0);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 2, PRINT_JSON_START_GROUPS);
++ if (fwd > len)
++ return fwd;
++
++ vector_foreach_slot (mpp->pg, pgp, i) {
++
++ pgp->selector = mpp->selector;
++ fwd += snprint_pathgroup(buff + fwd, len - fwd, PRINT_JSON_GROUP, pgp);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_GROUP_NUM, i + 1);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 3, PRINT_JSON_START_PATHS);
++ if (fwd > len)
++ return fwd;
++
++ vector_foreach_slot (pgp->paths, pp, j) {
++ fwd += snprint_path(buff + fwd, len - fwd, PRINT_JSON_PATH, pp, 0);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json_elem_footer(buff + fwd,
++ len - fwd, 3, j + 1 == VECTOR_SIZE(pgp->paths));
++ if (fwd > len)
++ return fwd;
++ }
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json_elem_footer(buff + fwd,
++ len - fwd, 2, i + 1 == VECTOR_SIZE(mpp->pg));
++ if (fwd > len)
++ return fwd;
++ }
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY);
++ if (fwd > len)
++ return fwd;
++
++ fwd += snprint_json_elem_footer(buff + fwd, len - fwd, 1, last);
++ return fwd;
++}
++
++int
++snprint_multipath_map_json (char * buff, int len,
++ struct multipath * mpp, int last){
++ int fwd = 0;
++
++ fwd += snprint_json_header(buff, len);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_START_MAP);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_multipath_fields_json(buff + fwd, len - fwd, mpp, 1);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, "\n");
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_LAST);
++ if (fwd > len)
++ return len;
++ return fwd;
++}
++
++int
++snprint_multipath_topology_json (char * buff, int len, struct vectors * vecs)
++{
++ int i, fwd = 0;
++ struct multipath * mpp;
++
++ fwd += snprint_json_header(buff, len);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 1, PRINT_JSON_START_MAPS);
++ if (fwd > len)
++ return len;
++
++ vector_foreach_slot(vecs->mpvec, mpp, i) {
++ fwd += snprint_multipath_fields_json(buff + fwd, len - fwd,
++ mpp, i + 1 == VECTOR_SIZE(vecs->mpvec));
++ if (fwd > len)
++ return len;
++ }
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY);
++ if (fwd > len)
++ return len;
++
++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_LAST);
++ if (fwd > len)
++ return len;
++ return fwd;
++}
++
+ static int
+ snprint_hwentry (char * buff, int len, struct hwentry * hwe)
+ {
+Index: multipath-tools-130222/libmultipath/print.h
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/print.h
++++ multipath-tools-130222/libmultipath/print.h
+@@ -7,6 +7,63 @@
+ #define PRINT_MAP_PROPS "size=%S features='%f' hwhandler='%h' wp=%r"
+ #define PRINT_PG_INDENT "policy='%s' prio=%p status=%t"
+
++#define PRINT_JSON_MULTIPLIER 5
++#define PRINT_JSON_MAJOR_VERSION 0
++#define PRINT_JSON_MINOR_VERSION 1
++#define PRINT_JSON_START_VERSION " \"major_version\": %d,\n" \
++ " \"minor_version\": %d,\n"
++#define PRINT_JSON_START_ELEM "{\n"
++#define PRINT_JSON_START_MAP " \"map\":"
++#define PRINT_JSON_START_MAPS "\"maps\": ["
++#define PRINT_JSON_START_PATHS "\"paths\": ["
++#define PRINT_JSON_START_GROUPS "\"path_groups\": ["
++#define PRINT_JSON_END_ELEM "},"
++#define PRINT_JSON_END_LAST_ELEM "}"
++#define PRINT_JSON_END_LAST "}\n"
++#define PRINT_JSON_END_ARRAY "]\n"
++#define PRINT_JSON_INDENT " "
++#define PRINT_JSON_MAP "{\n" \
++ " \"name\" : \"%n\",\n" \
++ " \"uuid\" : \"%w\",\n" \
++ " \"sysfs\" : \"%d\",\n" \
++ " \"failback\" : \"%F\",\n" \
++ " \"queueing\" : \"%Q\",\n" \
++ " \"paths\" : %N,\n" \
++ " \"write_prot\" : \"%r\",\n" \
++ " \"dm_st\" : \"%t\",\n" \
++ " \"features\" : \"%f\",\n" \
++ " \"hwhandler\" : \"%h\",\n" \
++ " \"action\" : \"%A\",\n" \
++ " \"path_faults\" : %0,\n" \
++ " \"vend\" : \"%v\",\n" \
++ " \"prod\" : \"%p\",\n" \
++ " \"rev\" : \"%e\",\n" \
++ " \"switch_grp\" : %1,\n" \
++ " \"map_loads\" : %2,\n" \
++ " \"total_q_time\" : %3,\n" \
++ " \"q_timeouts\" : %4,"
++
++#define PRINT_JSON_GROUP "{\n" \
++ " \"selector\" : \"%s\",\n" \
++ " \"pri\" : %p,\n" \
++ " \"dm_st\" : \"%t\","
++
++#define PRINT_JSON_GROUP_NUM " \"group\" : %d,\n"
++
++#define PRINT_JSON_PATH "{\n" \
++ " \"dev\" : \"%d\",\n"\
++ " \"dev_t\" : \"%D\",\n" \
++ " \"dm_st\" : \"%t\",\n" \
++ " \"dev_st\" : \"%o\",\n" \
++ " \"chk_st\" : \"%T\",\n" \
++ " \"checker\" : \"%c\",\n" \
++ " \"pri\" : %p,\n" \
++ " \"host_wwnn\" : \"%N\",\n" \
++ " \"target_wwnn\" : \"%n\",\n" \
++ " \"host_wwpn\" : \"%R\",\n" \
++ " \"target_wwpn\" : \"%r\",\n" \
++ " \"host_adapter\" : \"%a\""
++
+ #define MAX_LINE_LEN 80
+ #define MAX_LINES 64
+ #define MAX_FIELD_LEN 64
+@@ -41,6 +98,10 @@ int snprint_path (char *, int, char *, s
+ int snprint_multipath (char *, int, char *, struct multipath *, int);
+ int snprint_multipath_topology (char *, int, struct multipath * mpp,
+ int verbosity);
++int snprint_multipath_topology_json (char * buff, int len,
++ struct vectors * vecs);
++int snprint_multipath_map_json (char * buff, int len,
++ struct multipath * mpp, int last);
+ int snprint_defaults (char *, int);
+ int snprint_blacklist (char *, int);
+ int snprint_blacklist_except (char *, int);
+Index: multipath-tools-130222/multipathd/cli.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli.c
++++ multipath-tools-130222/multipathd/cli.c
+@@ -189,6 +189,7 @@ load_keys (void)
+ r += add_key(keys, "setprstatus", SETPRSTATUS, 0);
+ r += add_key(keys, "unsetprstatus", UNSETPRSTATUS, 0);
+ r += add_key(keys, "format", FMT, 1);
++ r += add_key(keys, "json", JSON, 0);
+
+ if (r) {
+ free_keys(keys);
+@@ -473,8 +474,10 @@ cli_init (void) {
+ add_handler(LIST+MAPS+FMT, NULL);
+ add_handler(LIST+MAPS+RAW+FMT, NULL);
+ add_handler(LIST+MAPS+TOPOLOGY, NULL);
++ add_handler(LIST+MAPS+JSON, NULL);
+ add_handler(LIST+TOPOLOGY, NULL);
+ add_handler(LIST+MAP+TOPOLOGY, NULL);
++ add_handler(LIST+MAP+JSON, NULL);
+ add_handler(LIST+CONFIG, NULL);
+ add_handler(LIST+BLACKLIST, NULL);
+ add_handler(LIST+DEVICES, NULL);
+Index: multipath-tools-130222/multipathd/cli.h
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli.h
++++ multipath-tools-130222/multipathd/cli.h
+@@ -36,6 +36,7 @@ enum {
+ __SETPRSTATUS,
+ __UNSETPRSTATUS,
+ __FMT,
++ __JSON,
+ };
+
+ #define LIST (1 << __LIST)
+@@ -74,6 +75,7 @@ enum {
+ #define SETPRSTATUS (1ULL << __SETPRSTATUS)
+ #define UNSETPRSTATUS (1ULL << __UNSETPRSTATUS)
+ #define FMT (1ULL << __FMT)
++#define JSON (1ULL << __JSON)
+
+ #define INITIAL_REPLY_LEN 1200
+
+Index: multipath-tools-130222/multipathd/cli_handlers.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli_handlers.c
++++ multipath-tools-130222/multipathd/cli_handlers.c
+@@ -127,6 +127,70 @@ show_maps_topology (char ** r, int * len
+ }
+
+ int
++show_maps_json (char ** r, int * len, struct vectors * vecs)
++{
++ int i;
++ struct multipath * mpp;
++ char * c;
++ char * reply;
++ unsigned int maxlen = INITIAL_REPLY_LEN *
++ PRINT_JSON_MULTIPLIER * VECTOR_SIZE(vecs->mpvec);
++ int again = 1;
++
++ vector_foreach_slot(vecs->mpvec, mpp, i) {
++ if (update_multipath(vecs, mpp->alias, 0)) {
++ return 1;
++ }
++ }
++
++ reply = MALLOC(maxlen);
++
++ while (again) {
++ if (!reply)
++ return 1;
++
++ c = reply;
++
++ c += snprint_multipath_topology_json(c, maxlen, vecs);
++ again = ((c - reply) == maxlen);
++
++ REALLOC_REPLY(reply, again, maxlen);
++ }
++ *r = reply;
++ *len = (int)(c - reply);
++ return 0;
++}
++
++int
++show_map_json (char ** r, int * len, struct multipath * mpp,
++ struct vectors * vecs)
++{
++ char * c;
++ char * reply;
++ unsigned int maxlen = INITIAL_REPLY_LEN;
++ int again = 1;
++
++ if (update_multipath(vecs, mpp->alias, 0))
++ return 1;
++ reply = MALLOC(maxlen);
++
++ while (again) {
++ if (!reply)
++ return 1;
++
++ c = reply;
++
++ c += snprint_multipath_map_json(c, maxlen, mpp, 1);
++ again = ((c - reply) == maxlen);
++
++ REALLOC_REPLY(reply, again, maxlen);
++ }
++ *r = reply;
++ *len = (int)(c - reply);
++ return 0;
++}
++
++int
+ show_config (char ** r, int * len)
+ {
+ char * c;
+@@ -239,6 +303,35 @@ cli_list_maps_topology (void * v, char *
+ }
+
+ int
++cli_list_map_json (void * v, char ** reply, int * len, void * data)
++{
++ struct multipath * mpp;
++ struct vectors * vecs = (struct vectors *)data;
++ char * param = get_keyparam(v, MAP);
++
++ param = convert_dev(param, 0);
++ get_path_layout(vecs->pathvec, 0);
++ mpp = find_mp_by_str(vecs->mpvec, param);
++
++ if (!mpp)
++ return 1;
++
++ condlog(3, "list multipath json %s (operator)", param);
++
++ return show_map_json(reply, len, mpp, vecs);
++}
++
++int
++cli_list_maps_json (void * v, char ** reply, int * len, void * data)
++{
++ struct vectors * vecs = (struct vectors *)data;
++
++ condlog(3, "list multipaths json (operator)");
++
++ return show_maps_json(reply, len, vecs);
++}
++
++int
+ cli_list_wildcards (void * v, char ** reply, int * len, void * data)
+ {
+ char * c;
+Index: multipath-tools-130222/multipathd/cli_handlers.h
+===================================================================
+--- multipath-tools-130222.orig/multipathd/cli_handlers.h
++++ multipath-tools-130222/multipathd/cli_handlers.h
+@@ -10,6 +10,8 @@ int cli_list_maps_status (void * v, char
+ int cli_list_maps_stats (void * v, char ** reply, int * len, void * data);
+ int cli_list_map_topology (void * v, char ** reply, int * len, void * data);
+ int cli_list_maps_topology (void * v, char ** reply, int * len, void * data);
++int cli_list_map_json (void * v, char ** reply, int * len, void * data);
++int cli_list_maps_json (void * v, char ** reply, int * len, void * data);
+ int cli_list_config (void * v, char ** reply, int * len, void * data);
+ int cli_list_blacklist (void * v, char ** reply, int * len, void * data);
+ int cli_list_devices (void * v, char ** reply, int * len, void * data);
+Index: multipath-tools-130222/multipathd/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/main.c
++++ multipath-tools-130222/multipathd/main.c
+@@ -981,7 +981,9 @@ uxlsnrloop (void * ap)
+ set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw);
+ set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology);
+ set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology);
++ set_handler_callback(LIST+MAPS+JSON, cli_list_maps_json);
+ set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology);
++ set_handler_callback(LIST+MAP+JSON, cli_list_map_json);
+ set_handler_callback(LIST+CONFIG, cli_list_config);
+ set_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
+ set_handler_callback(LIST+DEVICES, cli_list_devices);
+Index: multipath-tools-130222/multipathd/multipathd.8
+===================================================================
+--- multipath-tools-130222.orig/multipathd/multipathd.8
++++ multipath-tools-130222/multipathd/multipathd.8
+@@ -53,11 +53,15 @@ using a format string with multipath for
+ Show the status of all multipath devices that the multipathd is monitoring.
+ .TP
+ .B list|show maps|multipaths stats
+-Show some statistics of all multipath devices that the multipathd is monitoring.
++Show some statistics of all multipath devices that multipathd is monitoring.
+ .TP
+ .B list|show maps|multipaths topology
+ Show the current multipath topology. Same as "multipath \-ll".
+ .TP
++.B list|show maps|multipaths json
++Show the multipath devices that multipathd is monitoring, using JSON
++formatted output.
++.TP
+ .B list|show topology
+ Show the current multipath topology. Same as "multipath \-ll".
+ .TP
+@@ -65,6 +69,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 map|multipath $map json
++Show a single multipath device specified by $map, using JSON formatted output.
++.TP
+ .B list|show wildcards
+ Show the format wildcards used in interactive commands taking $format
+ .TP
diff --git a/0170-UPBZ-1352925-fix-typo.patch b/0170-UPBZ-1352925-fix-typo.patch
new file mode 100644
index 0000000..2521c3d
--- /dev/null
+++ b/0170-UPBZ-1352925-fix-typo.patch
@@ -0,0 +1,26 @@
+---
+ multipath/main.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+Index: multipath-tools-130222/multipath/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipath/main.c
++++ multipath-tools-130222/multipath/main.c
+@@ -286,7 +286,7 @@ configure (void)
+ if (failed == 2 && conf->cmd == CMD_VALID_PATH)
+ printf("%s is not a valid multipath device path\n", conf->dev);
+ else
+- condlog(3, "scope is nul");
++ condlog(3, "scope is null");
+ goto out;
+ }
+ if (conf->cmd == CMD_REMOVE_WWID) {
+@@ -358,7 +358,7 @@ configure (void)
+
+
+ if (conf->cmd == CMD_VALID_PATH) {
+- /* This only happens if find_multipaths is and
++ /* This only happens if find_multipaths and
+ * ignore_wwids is set.
+ * If there is currently a multipath device matching
+ * the refwwid, or there is more than one path matching
diff --git a/0171-UPBZ-1356651-allow-zero-size.patch b/0171-UPBZ-1356651-allow-zero-size.patch
new file mode 100644
index 0000000..0fe05b5
--- /dev/null
+++ b/0171-UPBZ-1356651-allow-zero-size.patch
@@ -0,0 +1,79 @@
+---
+ libmultipath/discovery.c | 5 +++++
+ libmultipath/structs_vec.c | 2 +-
+ multipathd/main.c | 26 +++++---------------------
+ 3 files changed, 11 insertions(+), 22 deletions(-)
+
+Index: multipath-tools-130222/libmultipath/discovery.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/discovery.c
++++ multipath-tools-130222/libmultipath/discovery.c
+@@ -1188,6 +1188,11 @@ pathinfo (struct path *pp, vector hwtabl
+ if (pp->state == PATH_UNCHECKED ||
+ pp->state == PATH_WILD)
+ goto blank;
++ if (pp->state == PATH_UP && !pp->size) {
++ condlog(3, "%s: device size is 0, "
++ "path unuseable", pp->dev);
++ pp->state = PATH_GHOST;
++ }
+ } else {
+ condlog(3, "%s: path inaccessible", pp->dev);
+ pp->chkrstate = pp->state = path_state;
+Index: multipath-tools-130222/libmultipath/structs_vec.c
+===================================================================
+--- multipath-tools-130222.orig/libmultipath/structs_vec.c
++++ multipath-tools-130222/libmultipath/structs_vec.c
+@@ -551,7 +551,7 @@ int update_multipath (struct vectors *ve
+
+ if (pp->state != PATH_DOWN) {
+ int oldstate = pp->state;
+- condlog(2, "%s: mark as failed", pp->dev_t);
++ condlog(2, "%s: mark as failed", pp->dev);
+ mpp->stat_path_failures++;
+ pp->state = PATH_DOWN;
+ if (oldstate == PATH_UP ||
+Index: multipath-tools-130222/multipathd/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/main.c
++++ multipath-tools-130222/multipathd/main.c
+@@ -538,15 +538,10 @@ ev_add_path (struct path * pp, struct ve
+ pp->mpp = mpp;
+ rescan:
+ if (mpp) {
+- if ((!pp->size) || (mpp->size != pp->size)) {
+- if (!pp->size)
+- condlog(0, "%s: failed to add new path %s, "
+- "device size is 0",
+- mpp->alias, pp->dev);
+- else
+- condlog(0, "%s: failed to add new path %s, "
+- "device size mismatch",
+- mpp->alias, pp->dev);
++ if (pp->size && mpp->size != pp->size) {
++ condlog(0, "%s: failed to add new path %s, "
++ "device size mismatch",
++ mpp->alias, pp->dev);
+ int i = find_slot(vecs->pathvec, (void *)pp);
+ if (i != -1)
+ vector_del_slot(vecs->pathvec, i);
+@@ -563,18 +558,7 @@ rescan:
+ verify_paths(mpp, vecs, NULL);
+ mpp->flush_on_last_del = FLUSH_UNDEF;
+ mpp->action = ACT_RELOAD;
+- }
+- else {
+- if (!pp->size) {
+- condlog(0, "%s: failed to create new map,"
+- " device size is 0 ", pp->dev);
+- int i = find_slot(vecs->pathvec, (void *)pp);
+- if (i != -1)
+- vector_del_slot(vecs->pathvec, i);
+- free_path(pp);
+- return 1;
+- }
+-
++ } else {
+ if (!should_multipath(pp, vecs->pathvec)) {
+ orphan_path(pp);
+ return 0;
diff --git a/0172-RHBZ-1350931-no-active-add.patch b/0172-RHBZ-1350931-no-active-add.patch
new file mode 100644
index 0000000..4e79e32
--- /dev/null
+++ b/0172-RHBZ-1350931-no-active-add.patch
@@ -0,0 +1,37 @@
+---
+ multipathd/main.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+Index: multipath-tools-130222/multipathd/main.c
+===================================================================
+--- multipath-tools-130222.orig/multipathd/main.c
++++ multipath-tools-130222/multipathd/main.c
+@@ -530,9 +530,15 @@ ev_add_path (struct path * pp, struct ve
+ }
+ mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid);
+ if (mpp && mpp->wait_for_udev) {
+- mpp->wait_for_udev = 2;
+- orphan_path(pp);
+- return 0;
++ if (pathcount(mpp, PATH_UP) == 0 &&
++ (pathcount(mpp, PATH_GHOST) == 0 ||
++ pp->tpgs == TPGS_IMPLICIT))
++ mpp->force_udev_reload = 1;
++ else {
++ mpp->wait_for_udev = 2;
++ orphan_path(pp);
++ return 0;
++ }
+ }
+
+ pp->mpp = mpp;
+@@ -551,7 +557,8 @@ rescan:
+
+ condlog(4,"%s: adopting all paths for path %s",
+ mpp->alias, pp->dev);
+- mpp->force_udev_reload = !pathcount(mpp, PATH_WILD);
++ if (pathcount(mpp, PATH_WILD) == 0)
++ mpp->force_udev_reload = 1;
+ if (adopt_paths(vecs->pathvec, mpp, 1))
+ goto fail; /* leave path added to pathvec */
+
diff --git a/device-mapper-multipath.spec b/device-mapper-multipath.spec
index b1a066c..6a4b517 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: 82%{?dist}
+Release: 83%{?dist}
License: GPL+
Group: System Environment/Base
URL: http://christophe.varoqui.free.fr/
@@ -167,6 +167,19 @@ Patch0156: 0156-UPBZ-1313324-dont-fail-discovery.patch
Patch0157: 0157-RHBZ-1319853-multipath-c-error-msg.patch
Patch0158: 0158-RHBZ-1318581-timestamp-doc-fix.patch
Patch0159: 0159-UPBZ-1255885-udev-waits.patch
+Patch0160: 0160-RH-udev-flags.patch
+Patch0161: 0161-RHBZ-1311659-no-kpartx.patch
+Patch0162: 0162-RHBZ-1333331-huawei-config.patch
+Patch0163: 0163-UPBZ-1333492-resize-map.patch
+Patch0164: 0164-RHBZ-1311463-dos-part-rollover.patch
+Patch0165: 0165-UPBZ-1341748-MSA-2040-conf.patch
+Patch0166: 0166-RHBZ-1323429-dont-allow-new-wwid.patch
+Patch0167: 0167-RHBZ-1335176-fix-show-cmds.patch
+Patch0168: 0168-RHBZ-1347769-shared-lock.patch
+Patch0169: 0169-UPBZ-1353357-json-output.patch
+Patch0170: 0170-UPBZ-1352925-fix-typo.patch
+Patch0171: 0171-UPBZ-1356651-allow-zero-size.patch
+Patch0172: 0172-RHBZ-1350931-no-active-add.patch
# runtime
Requires: %{name}-libs = %{version}-%{release}
@@ -379,6 +392,19 @@ kpartx manages partition creation and removal for device-mapper devices.
%patch0157 -p1
%patch0158 -p1
%patch0159 -p1
+%patch0160 -p1
+%patch0161 -p1
+%patch0162 -p1
+%patch0163 -p1
+%patch0164 -p1
+%patch0165 -p1
+%patch0166 -p1
+%patch0167 -p1
+%patch0168 -p1
+%patch0169 -p1
+%patch0170 -p1
+%patch0171 -p1
+%patch0172 -p1
cp %{SOURCE1} .
%build
@@ -480,6 +506,42 @@ fi
%{_mandir}/man8/kpartx.8.gz
%changelog
+* Fri Jul 22 2016 Benjamin Marzinski <bmarzins@redhat.com> 0.4.9-83
+- Modify 0135-RHBZ-1299600-path-dev-uevents.patch
+ * trigger uevents when adding wwids for existing devices during startup
+- Refresh 0136-RHBZ-1304687-wait-for-map-add.patch
+- Refresh 0150-RHBZ-1253913-fix-startup-msg.patch
+- Modify 0159-UPBZ-1255885-udev-waits.patch
+ * fix bug in failure path
+- Add 0160-RH-udev-flags.patch
+- Add 0161-RHBZ-1311659-no-kpartx.patch
+ * skip_kpartx option disables kpartx running on multipath devices
+- Add 0162-RHBZ-1333331-huawei-config.patch
+ * Add default config for Huawei XSG1 array
+- Add 0163-UPBZ-1333492-resize-map.patch
+ * restore old size if resize fails
+- Add 0164-RHBZ-1311463-dos-part-rollover.patch
+ * fix incorrect partition size due to 4k device size rollover
+- Add 0165-UPBZ-1341748-MSA-2040-conf.patch
+ * Add default config for MSA 2040 array
+- Add 0166-RHBZ-1323429-dont-allow-new-wwid.patch
+ * don't allow path wwid to change while it is in use
+- Add 0167-RHBZ-1335176-fix-show-cmds.patch
+ * and new show multipath format wildcard, 'f' to sho number of failures.
+ This will hopefully be useful for tracking what happens to multipath
+ devices for bz #1335176
+- Add 0168-RHBZ-1347769-shared-lock.patch
+ * make multipath lock the path devices with a shared lock
+- Add 0169-UPBZ-1353357-json-output.patch
+ * add mulitpathd json output command
+- Add 0170-UPBZ-1352925-fix-typo.patch
+- Add 0171-UPBZ-1356651-allow-zero-size.patch
+ * Allow zero-sized paths to be added to a multipath device
+- Add 0172-RHBZ-1350931-no-active-add.patch
+ * Allow paths to be added to a new map if no active paths exist. Also
+ fixes 1351430
+
+
* Thu Apr 21 2016 Benjamin Marzinski <bmarzins@redhat.com> 0.4.9-82
- Modify 0005-RH-add-mpathconf.patch
* changed warning message