diff --git a/0000-libmultipath-remove-last-of-rbd-code.patch b/0000-libmultipath-remove-last-of-rbd-code.patch new file mode 100644 index 0000000..7f26eb8 --- /dev/null +++ b/0000-libmultipath-remove-last-of-rbd-code.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 1 Jun 2018 16:30:44 -0500 +Subject: [PATCH] libmultipath: remove last of rbd code + +My previous patch to remove the rbd code missed a little bit. + +Signed-off-by: Benjamin Marzinski +--- + kpartx/del-part-nodes.rules | 2 +- + libmultipath/structs.h | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/kpartx/del-part-nodes.rules b/kpartx/del-part-nodes.rules +index 17bc505..0ceecf5 100644 +--- a/kpartx/del-part-nodes.rules ++++ b/kpartx/del-part-nodes.rules +@@ -10,7 +10,7 @@ + # or create an udev rule file that sets ENV{DONT_DEL_PART_NODES}="1". + + SUBSYSTEM!="block", GOTO="end_del_part_nodes" +-KERNEL!="sd*|dasd*|rbd*", GOTO="end_del_part_nodes" ++KERNEL!="sd*|dasd*", GOTO="end_del_part_nodes" + ACTION!="add|change", GOTO="end_del_part_nodes" + ENV{DEVTYPE}=="partition", GOTO="end_del_part_nodes" + +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index e5b698b..ca14315 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -61,7 +61,6 @@ enum sysfs_buses { + SYSFS_BUS_IDE, + SYSFS_BUS_CCW, + SYSFS_BUS_CCISS, +- SYSFS_BUS_RBD, + SYSFS_BUS_NVME, + }; + +-- +2.7.4 + diff --git a/0001-libmultipath-fix-detect-alua-corner-case.patch b/0001-libmultipath-fix-detect-alua-corner-case.patch new file mode 100644 index 0000000..6d6fa64 --- /dev/null +++ b/0001-libmultipath-fix-detect-alua-corner-case.patch @@ -0,0 +1,35 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 8 Jun 2018 17:12:37 -0500 +Subject: [PATCH] libmultipath: fix detect alua corner case + +If retain_attach_hw_handler = no, then the paths tpgs state will never +be checked, and the multipath device will always select the alua +handler, if no other handler is selected. the paths tpgs state +should be checked, regardless of the retain_hwhandler value. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/propsel.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c +index af3ed62..fdb5953 100644 +--- a/libmultipath/propsel.c ++++ b/libmultipath/propsel.c +@@ -420,9 +420,11 @@ int select_hwhandler(struct config *conf, struct multipath *mp) + bool all_tpgs = true; + + dh_state = &handler[2]; ++ ++ vector_foreach_slot(mp->paths, pp, i) ++ all_tpgs = all_tpgs && (pp->tpgs > 0); + if (mp->retain_hwhandler != RETAIN_HWHANDLER_OFF) { + vector_foreach_slot(mp->paths, pp, i) { +- all_tpgs = all_tpgs && (pp->tpgs > 0); + if (get_dh_state(pp, dh_state, sizeof(handler) - 2) > 0 + && strcmp(dh_state, "detached")) { + memcpy(handler, "1 ", 2); +-- +2.7.4 + diff --git a/0002-multipath-fix-setting-conf-version.patch b/0002-multipath-fix-setting-conf-version.patch new file mode 100644 index 0000000..624f45e --- /dev/null +++ b/0002-multipath-fix-setting-conf-version.patch @@ -0,0 +1,39 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 8 Jun 2018 17:23:07 -0500 +Subject: [PATCH] multipath: fix setting conf->version + +Commit d3b71498 stopped multipath from setting conf->version. Instead, +it was always being set to 0.0.0. Multipathd was still setting this +correctly. + +Fixes: d3b71498 "multipath: fix rcu thread cancellation hang" +Signed-off-by: Benjamin Marzinski +--- + libmultipath/devmapper.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index f2befad..8136d15 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -245,13 +245,13 @@ void libmp_dm_init(void) + int verbosity; + unsigned int version[3]; + ++ if (dm_prereq(version)) ++ exit(1); + conf = get_multipath_config(); + verbosity = conf->verbosity; +- memcpy(version, conf->version, sizeof(version)); ++ memcpy(conf->version, version, sizeof(version)); + put_multipath_config(conf); + dm_init(verbosity); +- if (dm_prereq(version)) +- exit(1); + dm_udev_set_sync_support(libmp_dm_udev_sync); + } + +-- +2.7.4 + diff --git a/0003-mpathpersist-add-param-alltgpt-option.patch b/0003-mpathpersist-add-param-alltgpt-option.patch new file mode 100644 index 0000000..8485d37 --- /dev/null +++ b/0003-mpathpersist-add-param-alltgpt-option.patch @@ -0,0 +1,152 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 26 Jun 2018 16:30:11 -0500 +Subject: [PATCH] mpathpersist: add --param-alltgpt option + +From the limited testing I've been able to do, commit 5b54e772 +"mpathpersist: add all_tg_pt option", does appear to enable +--param-alltgpt to work correctly on devices that accept the ALL_TG_PT +flag, so I've added the option to mpathpersist. + +Signed-off-by: Benjamin Marzinski +--- + libmpathpersist/mpath_persist.c | 10 ++++------ + mpathpersist/main.c | 11 ++++++++--- + mpathpersist/main.h | 1 + + mpathpersist/mpathpersist.8 | 4 ++++ + multipath/multipath.conf.5 | 8 +++++--- + 5 files changed, 22 insertions(+), 12 deletions(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index 6e9e67f..61818e0 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -466,11 +466,14 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope, + int rc; + int count=0; + int status = MPATH_PR_SUCCESS; ++ int all_tg_pt; + uint64_t sa_key = 0; + + if (!mpp) + return MPATH_PR_DMMP_ERROR; + ++ all_tg_pt = (mpp->all_tg_pt == ALL_TG_PT_ON || ++ paramp->sa_flags & MPATH_F_ALL_TG_PT_MASK); + active_pathcount = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST); + + if (active_pathcount == 0) { +@@ -478,10 +481,6 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope, + return MPATH_PR_DMMP_ERROR; + } + +- if ( paramp->sa_flags & MPATH_F_ALL_TG_PT_MASK ) { +- condlog (1, "Warning: ALL_TG_PT is set. Configuration not supported"); +- } +- + struct threadinfo thread[active_pathcount]; + int hosts[active_pathcount]; + +@@ -518,8 +517,7 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope, + condlog (1, "%s: %s path not up. Skip.", mpp->wwid, pp->dev); + continue; + } +- if (mpp->all_tg_pt == ALL_TG_PT_ON && +- pp->sg_id.host_no != -1) { ++ if (all_tg_pt && pp->sg_id.host_no != -1) { + for (k = 0; k < count; k++) { + if (pp->sg_id.host_no == hosts[k]) { + condlog(3, "%s: %s host %d matches skip.", pp->wwid, pp->dev, pp->sg_id.host_no); +diff --git a/mpathpersist/main.c b/mpathpersist/main.c +index 5b37f3a..99151fe 100644 +--- a/mpathpersist/main.c ++++ b/mpathpersist/main.c +@@ -118,7 +118,7 @@ int main (int argc, char * argv[]) + { + int option_index = 0; + +- c = getopt_long (argc, argv, "v:Cd:hHioZK:S:PAT:skrGILcRX:l:", ++ c = getopt_long (argc, argv, "v:Cd:hHioYZK:S:PAT:skrGILcRX:l:", + long_options, &option_index); + if (c == -1) + break; +@@ -158,6 +158,10 @@ int main (int argc, char * argv[]) + prout_flag = 1; + break; + ++ case 'Y': ++ param_alltgpt = 1; ++ ++num_prout_param; ++ break; + case 'Z': + param_aptpl = 1; + ++num_prout_param; +@@ -443,9 +447,9 @@ int main (int argc, char * argv[]) + } + + if (param_alltgpt) +- paramp->sa_flags |= 0x4; ++ paramp->sa_flags |= MPATH_F_ALL_TG_PT_MASK; + if (param_aptpl) +- paramp->sa_flags |= 0x1; ++ paramp->sa_flags |= MPATH_F_APTPL_MASK; + + if (num_transport) + { +@@ -698,6 +702,7 @@ static void usage(void) + " --hex|-H output response in hex\n" + " --in|-i request PR In command \n" + " --out|-o request PR Out command\n" ++ " --param-alltgpt|-Y PR Out parameter 'ALL_TG_PT\n" + " --param-aptpl|-Z PR Out parameter 'APTPL'\n" + " --read-keys|-k PR In: Read Keys\n" + " --param-sark=SARK|-S SARK PR Out parameter service " +diff --git a/mpathpersist/main.h b/mpathpersist/main.h +index 5c0e089..beb8a21 100644 +--- a/mpathpersist/main.h ++++ b/mpathpersist/main.h +@@ -6,6 +6,7 @@ static struct option long_options[] = { + {"hex", 0, NULL, 'H'}, + {"in", 0, NULL, 'i'}, + {"out", 0, NULL, 'o'}, ++ {"param-alltgpt", 0, NULL, 'Y'}, + {"param-aptpl", 0, NULL, 'Z'}, + {"param-rk", 1, NULL, 'K'}, + {"param-sark", 1, NULL, 'S'}, +diff --git a/mpathpersist/mpathpersist.8 b/mpathpersist/mpathpersist.8 +index a8982e6..885491d 100644 +--- a/mpathpersist/mpathpersist.8 ++++ b/mpathpersist/mpathpersist.8 +@@ -87,6 +87,10 @@ Request PR In command. + Request PR Out command. + . + .TP ++.B \--param-alltgpt|\-Y ++PR Out parameter 'ALL_TG_PT'. ++. ++.TP + .B \--param-aptpl|\-Z + PR Out parameter 'APTPL'. + . +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index e4b25a0..fb863fd 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -756,9 +756,11 @@ The default is: \fB\fR + . + .TP + .B all_tg_pt +-This must be set to \fByes\fR to successfully use mpathpersist on arrays that +-automatically set and clear registration keys on all target ports from a +-host, instead of per target port per host. ++Set the 'all targets ports' flag when registering keys with mpathpersist. Some ++arrays automatically set and clear registration keys on all target ports from a ++host, instead of per target port per host. The ALL_TG_PT flag must be set to ++successfully use mpathpersist on these arrays. Setting this option is identical ++to calling mpathpersist with \fI--param-alltgpt\fR + .RS + .TP + The default is: \fBno\fR +-- +2.7.4 + diff --git a/0004-libmutipath-remove-unused-IDE-bus-type.patch b/0004-libmutipath-remove-unused-IDE-bus-type.patch new file mode 100644 index 0000000..5dda5a7 --- /dev/null +++ b/0004-libmutipath-remove-unused-IDE-bus-type.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 26 Jun 2018 16:45:48 -0500 +Subject: [PATCH] libmutipath: remove unused IDE bus type + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/structs.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index ca14315..0a2623a 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -58,7 +58,6 @@ enum failback_mode { + enum sysfs_buses { + SYSFS_BUS_UNDEF, + SYSFS_BUS_SCSI, +- SYSFS_BUS_IDE, + SYSFS_BUS_CCW, + SYSFS_BUS_CCISS, + SYSFS_BUS_NVME, +-- +2.7.4 + diff --git a/0005-multipathd-add-new-protocol-path-wildcard.patch b/0005-multipathd-add-new-protocol-path-wildcard.patch new file mode 100644 index 0000000..479788e --- /dev/null +++ b/0005-multipathd-add-new-protocol-path-wildcard.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 26 Jun 2018 17:04:57 -0500 +Subject: [PATCH] multipathd: add new protocol path wildcard + +This patch adds a new path wildcard 'P', that will print the path's +protocol. For scsi devices, it will additionally print the transport +protocol being used. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/print.c | 43 +++++++++++++++++++++++++++++++++++++++++++ + libmultipath/print.h | 2 ++ + 2 files changed, 45 insertions(+) + +diff --git a/libmultipath/print.c b/libmultipath/print.c +index 222d270..ecfcb48 100644 +--- a/libmultipath/print.c ++++ b/libmultipath/print.c +@@ -638,6 +638,48 @@ snprint_path_failures(char * buff, size_t len, const struct path * pp) + return snprint_int(buff, len, pp->failcount); + } + ++/* if you add a protocol string bigger than "scsi:unspec" you must ++ * also change PROTOCOL_BUF_SIZE */ ++int ++snprint_path_protocol(char * buff, size_t len, const struct path * pp) ++{ ++ switch (pp->bus) { ++ case SYSFS_BUS_SCSI: ++ switch (pp->sg_id.proto_id) { ++ case SCSI_PROTOCOL_FCP: ++ return snprintf(buff, len, "scsi:fcp"); ++ case SCSI_PROTOCOL_SPI: ++ return snprintf(buff, len, "scsi:spi"); ++ case SCSI_PROTOCOL_SSA: ++ return snprintf(buff, len, "scsi:ssa"); ++ case SCSI_PROTOCOL_SBP: ++ return snprintf(buff, len, "scsi:sbp"); ++ case SCSI_PROTOCOL_SRP: ++ return snprintf(buff, len, "scsi:srp"); ++ case SCSI_PROTOCOL_ISCSI: ++ return snprintf(buff, len, "scsi:iscsi"); ++ case SCSI_PROTOCOL_SAS: ++ return snprintf(buff, len, "scsi:sas"); ++ case SCSI_PROTOCOL_ADT: ++ return snprintf(buff, len, "scsi:adt"); ++ case SCSI_PROTOCOL_ATA: ++ return snprintf(buff, len, "scsi:ata"); ++ case SCSI_PROTOCOL_UNSPEC: ++ default: ++ return snprintf(buff, len, "scsi:unspec"); ++ } ++ case SYSFS_BUS_CCW: ++ return snprintf(buff, len, "ccw"); ++ case SYSFS_BUS_CCISS: ++ return snprintf(buff, len, "cciss"); ++ case SYSFS_BUS_NVME: ++ return snprintf(buff, len, "nvme"); ++ case SYSFS_BUS_UNDEF: ++ default: ++ return snprintf(buff, len, "undef"); ++ } ++} ++ + struct multipath_data mpd[] = { + {'n', "name", 0, snprint_name}, + {'w', "uuid", 0, snprint_multipath_uuid}, +@@ -687,6 +729,7 @@ struct path_data pd[] = { + {'a', "host adapter", 0, snprint_host_adapter}, + {'G', "foreign", 0, snprint_path_foreign}, + {'0', "failures", 0, snprint_path_failures}, ++ {'P', "protocol", 0, snprint_path_protocol}, + {0, NULL, 0 , NULL} + }; + +diff --git a/libmultipath/print.h b/libmultipath/print.h +index 608b7d5..e2fb865 100644 +--- a/libmultipath/print.h ++++ b/libmultipath/print.h +@@ -133,6 +133,8 @@ int snprint_host_wwnn (char *, size_t, const struct path *); + int snprint_host_wwpn (char *, size_t, const struct path *); + int snprint_tgt_wwnn (char *, size_t, const struct path *); + int snprint_tgt_wwpn (char *, size_t, const struct path *); ++#define PROTOCOL_BUF_SIZE sizeof("scsi:unspec") ++int snprint_path_protocol(char *, size_t, const struct path *); + + void _print_multipath_topology (const struct gen_multipath * gmp, + int verbosity); +-- +2.7.4 + diff --git a/0006-libmultipath-add-protocol-blacklist-option.patch b/0006-libmultipath-add-protocol-blacklist-option.patch new file mode 100644 index 0000000..16a1899 --- /dev/null +++ b/0006-libmultipath-add-protocol-blacklist-option.patch @@ -0,0 +1,425 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 28 Jun 2018 13:16:11 -0500 +Subject: [PATCH] libmultipath: add "protocol" blacklist option. + +Multiple users have requested an easy way to setup blacklists that do +things such as blacklisting all non FC and iSCSI devices. Currently +there is no easy way to do this, without knowing in advance what the +devices are. Looking into the udev property values, I didn't see a +consistent set of values that would worked for all the different types +of requests like this (which would have allowed us to solve this by +extending the "property" blacklist option to allow comparing values, +instead of just keywords). + +Instead I've opted to allow multipath to blacklist/whitelist devices +by the protocol strings printed by "multipathd: add new protocol path +wildcard". This check happens after multipath checks the "device" +keyword, and before it checks wwid. This gives users an easily +understandible method to set up these types of blacklists, without +needing to know the exact arrays being used. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/blacklist.c | 51 ++++++++++++++++++++++++++++++++++++++-------- + libmultipath/blacklist.h | 3 +++ + libmultipath/config.c | 15 ++++++++++++++ + libmultipath/config.h | 2 ++ + libmultipath/dict.c | 14 +++++++++++-- + libmultipath/discovery.c | 5 +++-- + libmultipath/print.c | 31 ++++++++++++++++++++++++++++ + multipath/multipath.conf.5 | 16 +++++++++++++-- + 8 files changed, 123 insertions(+), 14 deletions(-) + +diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c +index 361c603..fdd36f7 100644 +--- a/libmultipath/blacklist.c ++++ b/libmultipath/blacklist.c +@@ -12,6 +12,8 @@ + #include "structs.h" + #include "config.h" + #include "blacklist.h" ++#include "structs_vec.h" ++#include "print.h" + + int store_ble(vector blist, char * str, int origin) + { +@@ -240,12 +242,14 @@ setup_default_blist (struct config * conf) + condlog(3, "%s: %s %s %s", dev, (M), wwid, (S)); \ + else if (env) \ + condlog(3, "%s: %s %s %s", dev, (M), env, (S)); \ ++ else if (protocol) \ ++ condlog(3, "%s: %s %s %s", dev, (M), protocol, (S)); \ + else \ + condlog(3, "%s: %s %s", dev, (M), (S)) + + void + log_filter (const char *dev, char *vendor, char *product, char *wwid, +- const char *env, int r) ++ const char *env, const char *protocol, int r) + { + /* + * Try to sort from most likely to least. +@@ -265,6 +269,9 @@ log_filter (const char *dev, char *vendor, char *product, char *wwid, + case MATCH_PROPERTY_BLIST: + LOG_BLIST("udev property", "blacklisted"); + break; ++ case MATCH_PROTOCOL_BLIST: ++ LOG_BLIST("protocol", "blacklisted"); ++ break; + case MATCH_DEVICE_BLIST_EXCEPT: + LOG_BLIST("vendor/product", "whitelisted"); + break; +@@ -280,6 +287,9 @@ log_filter (const char *dev, char *vendor, char *product, char *wwid, + case MATCH_PROPERTY_BLIST_MISSING: + LOG_BLIST("blacklisted,", "udev property missing"); + break; ++ case MATCH_PROTOCOL_BLIST_EXCEPT: ++ LOG_BLIST("protocol", "whitelisted"); ++ break; + } + } + +@@ -299,7 +309,7 @@ int + filter_device (vector blist, vector elist, char * vendor, char * product) + { + int r = _filter_device(blist, elist, vendor, product); +- log_filter(NULL, vendor, product, NULL, NULL, r); ++ log_filter(NULL, vendor, product, NULL, NULL, NULL, r); + return r; + } + +@@ -319,7 +329,7 @@ int + filter_devnode (vector blist, vector elist, char * dev) + { + int r = _filter_devnode(blist, elist, dev); +- log_filter(dev, NULL, NULL, NULL, NULL, r); ++ log_filter(dev, NULL, NULL, NULL, NULL, NULL, r); + return r; + } + +@@ -339,7 +349,29 @@ int + filter_wwid (vector blist, vector elist, char * wwid, char * dev) + { + int r = _filter_wwid(blist, elist, wwid); +- log_filter(dev, NULL, NULL, wwid, NULL, r); ++ log_filter(dev, NULL, NULL, wwid, NULL, NULL, r); ++ return r; ++} ++ ++static int ++_filter_protocol (vector blist, vector elist, const char * protocol_str) ++{ ++ if (_blacklist_exceptions(elist, protocol_str)) ++ return MATCH_PROTOCOL_BLIST_EXCEPT; ++ if (_blacklist(blist, protocol_str)) ++ return MATCH_PROTOCOL_BLIST; ++ return 0; ++} ++ ++int ++filter_protocol(vector blist, vector elist, struct path * pp) ++{ ++ char buf[PROTOCOL_BUF_SIZE]; ++ int r; ++ ++ snprint_path_protocol(buf, sizeof(buf), pp); ++ r = _filter_protocol(blist, elist, buf); ++ log_filter(pp->dev, NULL, NULL, NULL, NULL, buf, r); + return r; + } + +@@ -351,7 +383,6 @@ _filter_path (struct config * conf, struct path * pp) + r = filter_property(conf, pp->udev); + if (r > 0) + return r; +- + r = _filter_devnode(conf->blist_devnode, conf->elist_devnode,pp->dev); + if (r > 0) + return r; +@@ -359,6 +390,9 @@ _filter_path (struct config * conf, struct path * pp) + pp->vendor_id, pp->product_id); + if (r > 0) + return r; ++ r = filter_protocol(conf->blist_protocol, conf->elist_protocol, pp); ++ if (r > 0) ++ return r; + r = _filter_wwid(conf->blist_wwid, conf->elist_wwid, pp->wwid); + return r; + } +@@ -367,7 +401,8 @@ int + filter_path (struct config * conf, struct path * pp) + { + int r=_filter_path(conf, pp); +- log_filter(pp->dev, pp->vendor_id, pp->product_id, pp->wwid, NULL, r); ++ log_filter(pp->dev, pp->vendor_id, pp->product_id, pp->wwid, NULL, ++ NULL, r); + return r; + } + +@@ -402,7 +437,7 @@ filter_property(struct config * conf, struct udev_device * udev) + + r = _filter_property(conf, env); + if (r) { +- log_filter(devname, NULL, NULL, NULL, env, r); ++ log_filter(devname, NULL, NULL, NULL, env, NULL, r); + return r; + } + } +@@ -411,7 +446,7 @@ filter_property(struct config * conf, struct udev_device * udev) + * This is the inverse of the 'normal' matching; + * the environment variable _has_ to match. + */ +- log_filter(devname, NULL, NULL, NULL, NULL, ++ log_filter(devname, NULL, NULL, NULL, NULL, NULL, + MATCH_PROPERTY_BLIST_MISSING); + return MATCH_PROPERTY_BLIST_MISSING; + } +diff --git a/libmultipath/blacklist.h b/libmultipath/blacklist.h +index 0b028d4..f7beef2 100644 +--- a/libmultipath/blacklist.h ++++ b/libmultipath/blacklist.h +@@ -10,10 +10,12 @@ + #define MATCH_DEVNODE_BLIST 3 + #define MATCH_PROPERTY_BLIST 4 + #define MATCH_PROPERTY_BLIST_MISSING 5 ++#define MATCH_PROTOCOL_BLIST 6 + #define MATCH_WWID_BLIST_EXCEPT -MATCH_WWID_BLIST + #define MATCH_DEVICE_BLIST_EXCEPT -MATCH_DEVICE_BLIST + #define MATCH_DEVNODE_BLIST_EXCEPT -MATCH_DEVNODE_BLIST + #define MATCH_PROPERTY_BLIST_EXCEPT -MATCH_PROPERTY_BLIST ++#define MATCH_PROTOCOL_BLIST_EXCEPT -MATCH_PROTOCOL_BLIST + + struct blentry { + char * str; +@@ -36,6 +38,7 @@ int filter_wwid (vector, vector, char *, char *); + int filter_device (vector, vector, char *, char *); + int filter_path (struct config *, struct path *); + int filter_property(struct config *, struct udev_device *); ++int filter_protocol(vector, vector, struct path *); + int store_ble (vector, char *, int); + int set_ble_device (vector, char *, char *, int); + void free_blacklist (vector); +diff --git a/libmultipath/config.c b/libmultipath/config.c +index afa309d..0aef186 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -623,11 +623,13 @@ free_config (struct config * conf) + free_blacklist(conf->blist_devnode); + free_blacklist(conf->blist_wwid); + free_blacklist(conf->blist_property); ++ free_blacklist(conf->blist_protocol); + free_blacklist_device(conf->blist_device); + + free_blacklist(conf->elist_devnode); + free_blacklist(conf->elist_wwid); + free_blacklist(conf->elist_property); ++ free_blacklist(conf->elist_protocol); + free_blacklist_device(conf->elist_device); + + free_mptable(conf->mptable); +@@ -780,6 +782,12 @@ load_config (char * file) + if (!conf->blist_property) + goto out; + } ++ if (conf->blist_protocol == NULL) { ++ conf->blist_protocol = vector_alloc(); ++ ++ if (!conf->blist_protocol) ++ goto out; ++ } + + if (conf->elist_devnode == NULL) { + conf->elist_devnode = vector_alloc(); +@@ -807,6 +815,13 @@ load_config (char * file) + if (!conf->elist_property) + goto out; + } ++ if (conf->elist_protocol == NULL) { ++ conf->elist_protocol = vector_alloc(); ++ ++ if (!conf->elist_protocol) ++ goto out; ++ } ++ + if (setup_default_blist(conf)) + goto out; + +diff --git a/libmultipath/config.h b/libmultipath/config.h +index 6bd42f0..7d0cd9a 100644 +--- a/libmultipath/config.h ++++ b/libmultipath/config.h +@@ -210,10 +210,12 @@ struct config { + vector blist_wwid; + vector blist_device; + vector blist_property; ++ vector blist_protocol; + vector elist_devnode; + vector elist_wwid; + vector elist_device; + vector elist_property; ++ vector elist_protocol; + }; + + extern struct udev * udev; +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index 15e7582..32524d5 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -1291,9 +1291,12 @@ blacklist_handler(struct config *conf, vector strvec) + conf->blist_device = vector_alloc(); + if (!conf->blist_property) + conf->blist_property = vector_alloc(); ++ if (!conf->blist_protocol) ++ conf->blist_protocol = vector_alloc(); + + if (!conf->blist_devnode || !conf->blist_wwid || +- !conf->blist_device || !conf->blist_property) ++ !conf->blist_device || !conf->blist_property || ++ !conf->blist_protocol) + return 1; + + return 0; +@@ -1310,9 +1313,12 @@ blacklist_exceptions_handler(struct config *conf, vector strvec) + conf->elist_device = vector_alloc(); + if (!conf->elist_property) + conf->elist_property = vector_alloc(); ++ if (!conf->elist_protocol) ++ conf->elist_protocol = vector_alloc(); + + if (!conf->elist_devnode || !conf->elist_wwid || +- !conf->elist_device || !conf->elist_property) ++ !conf->elist_device || !conf->elist_property || ++ !conf->elist_protocol) + return 1; + + return 0; +@@ -1356,6 +1362,8 @@ declare_ble_handler(blist_wwid) + declare_ble_handler(elist_wwid) + declare_ble_handler(blist_property) + declare_ble_handler(elist_property) ++declare_ble_handler(blist_protocol) ++declare_ble_handler(elist_protocol) + + static int + snprint_def_uxsock_timeout(struct config *conf, char * buff, int len, +@@ -1627,6 +1635,7 @@ init_keywords(vector keywords) + install_keyword_multi("devnode", &ble_blist_devnode_handler, &snprint_ble_simple); + install_keyword_multi("wwid", &ble_blist_wwid_handler, &snprint_ble_simple); + install_keyword_multi("property", &ble_blist_property_handler, &snprint_ble_simple); ++ install_keyword_multi("protocol", &ble_blist_protocol_handler, &snprint_ble_simple); + install_keyword_multi("device", &ble_device_handler, NULL); + install_sublevel(); + install_keyword("vendor", &ble_blist_device_vendor_handler, &snprint_bled_vendor); +@@ -1636,6 +1645,7 @@ init_keywords(vector keywords) + install_keyword_multi("devnode", &ble_elist_devnode_handler, &snprint_ble_simple); + install_keyword_multi("wwid", &ble_elist_wwid_handler, &snprint_ble_simple); + install_keyword_multi("property", &ble_elist_property_handler, &snprint_ble_simple); ++ install_keyword_multi("protocol", &ble_elist_protocol_handler, &snprint_ble_simple); + install_keyword_multi("device", &ble_except_device_handler, NULL); + install_sublevel(); + install_keyword("vendor", &ble_elist_device_vendor_handler, &snprint_bled_vendor); +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 573d98b..e58a3fa 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1887,9 +1887,10 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + + if (mask & DI_BLACKLIST && mask & DI_SYSFS) { + if (filter_device(conf->blist_device, conf->elist_device, +- pp->vendor_id, pp->product_id) > 0) { ++ pp->vendor_id, pp->product_id) > 0 || ++ filter_protocol(conf->blist_protocol, conf->elist_protocol, ++ pp) > 0) + return PATHINFO_SKIPPED; +- } + } + + path_state = path_offline(pp); +diff --git a/libmultipath/print.c b/libmultipath/print.c +index ecfcb48..9da6a77 100644 +--- a/libmultipath/print.c ++++ b/libmultipath/print.c +@@ -1688,6 +1688,19 @@ int snprint_blacklist_report(struct config *conf, char *buff, int len) + + if ((len - fwd - threshold) <= 0) + return len; ++ fwd += snprintf(buff + fwd, len - fwd, "protocol rules:\n" ++ "- blacklist:\n"); ++ if (!snprint_blacklist_group(buff, len, &fwd, &conf->blist_protocol)) ++ return len; ++ ++ if ((len - fwd - threshold) <= 0) ++ return len; ++ fwd += snprintf(buff + fwd, len - fwd, "- exceptions:\n"); ++ if (snprint_blacklist_group(buff, len, &fwd, &conf->elist_protocol) == 0) ++ return len; ++ ++ if ((len - fwd - threshold) <= 0) ++ return len; + fwd += snprintf(buff + fwd, len - fwd, "wwid rules:\n" + "- blacklist:\n"); + if (snprint_blacklist_group(buff, len, &fwd, &conf->blist_wwid) == 0) +@@ -1761,6 +1774,15 @@ static int snprint_blacklist(const struct config *conf, char *buff, int len) + if (fwd >= len) + return len; + } ++ vector_foreach_slot (conf->blist_protocol, ble, i) { ++ kw = find_keyword(conf->keywords, rootkw->sub, "protocol"); ++ if (!kw) ++ return 0; ++ fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n", ++ kw, ble); ++ if (fwd >= len) ++ return len; ++ } + rootkw = find_keyword(conf->keywords, rootkw->sub, "device"); + if (!rootkw) + return 0; +@@ -1838,6 +1860,15 @@ static int snprint_blacklist_except(const struct config *conf, + if (fwd >= len) + return len; + } ++ vector_foreach_slot (conf->elist_protocol, ele, i) { ++ kw = find_keyword(conf->keywords, rootkw->sub, "protocol"); ++ if (!kw) ++ return 0; ++ fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n", ++ kw, ele); ++ if (fwd >= len) ++ return len; ++ } + rootkw = find_keyword(conf->keywords, rootkw->sub, "device"); + if (!rootkw) + return 0; +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index fb863fd..6333366 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -1205,9 +1205,21 @@ The default \fIblacklist exception\fR is: \fB(SCSI_IDENT_|ID_WWN)\fR, causing + well-behaved SCSI devices and devices that provide a WWN (World Wide Number) + to be included, and all others to be excluded. + .RE ++.TP ++.B protocol ++Regular expression for the protocol of a device to be excluded/included. ++.RS ++.PP ++The protocol strings that multipath recognizes are \fIscsi:fcp\fR, ++\fIscsi:spi\fR, \fIscsi:ssa\fR, \fIscsi:sbp\fR, \fIscsi:srp\fR, ++\fIscsi:iscsi\fR, \fIscsi:sas\fR, \fIscsi:adt\fR, \fIscsi:ata\fR, ++\fIscsi:unspec\fR, \fIccw\fR, \fIcciss\fR, \fInvme\fR, and \fIundef\fR. ++The protocol that a path is using can be viewed by running ++\fBmultipathd show paths format "%d %P"\fR ++.RE + .LP +-For every device, these 4 blacklist criteria are evaluated in the the order +-"property, dev\%node, device, wwid". If a device turns out to be ++For every device, these 5 blacklist criteria are evaluated in the the order ++"property, dev\%node, device, protocol, wwid". If a device turns out to be + blacklisted by any criterion, it's excluded from handling by multipathd, and + the later criteria aren't evaluated any more. For each + criterion, the whitelist takes precedence over the blacklist if a device +-- +2.7.4 + diff --git a/0007-libmultipath-remove-_filter_-blacklist-functions.patch b/0007-libmultipath-remove-_filter_-blacklist-functions.patch new file mode 100644 index 0000000..b8e8e07 --- /dev/null +++ b/0007-libmultipath-remove-_filter_-blacklist-functions.patch @@ -0,0 +1,296 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 3 Jul 2018 19:15:03 -0500 +Subject: [PATCH] libmultipath: remove _filter_* blacklist functions + +The one point of these functions was for _filter_path(), and that wasn't +improved by using them. Since filter_path() only printed one message at +the end, you could have situations where the wwid was blacklisted, but +the blacklist message included the vendor/product instead. Also, the +protocol and property messages were printed twice, and if the device was +on multiple whitelists, only the last one is printed. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/blacklist.c | 168 +++++++++++++++++++---------------------------- + libmultipath/blacklist.h | 2 +- + libmultipath/configure.c | 2 +- + libmultipath/discovery.c | 2 +- + 4 files changed, 71 insertions(+), 103 deletions(-) + +diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c +index fdd36f7..318ec03 100644 +--- a/libmultipath/blacklist.c ++++ b/libmultipath/blacklist.c +@@ -294,161 +294,129 @@ log_filter (const char *dev, char *vendor, char *product, char *wwid, + } + + int +-_filter_device (vector blist, vector elist, char * vendor, char * product) ++filter_device (vector blist, vector elist, char * vendor, char * product, ++ char * dev) + { +- if (!vendor || !product) +- return 0; +- if (_blacklist_exceptions_device(elist, vendor, product)) +- return MATCH_DEVICE_BLIST_EXCEPT; +- if (_blacklist_device(blist, vendor, product)) +- return MATCH_DEVICE_BLIST; +- return 0; +-} ++ int r = MATCH_NOTHING; + +-int +-filter_device (vector blist, vector elist, char * vendor, char * product) +-{ +- int r = _filter_device(blist, elist, vendor, product); +- log_filter(NULL, vendor, product, NULL, NULL, NULL, r); +- return r; +-} ++ if (vendor && product) { ++ if (_blacklist_exceptions_device(elist, vendor, product)) ++ r = MATCH_DEVICE_BLIST_EXCEPT; ++ else if (_blacklist_device(blist, vendor, product)) ++ r = MATCH_DEVICE_BLIST; ++ } + +-int +-_filter_devnode (vector blist, vector elist, char * dev) +-{ +- if (!dev) +- return 0; +- if (_blacklist_exceptions(elist, dev)) +- return MATCH_DEVNODE_BLIST_EXCEPT; +- if (_blacklist(blist, dev)) +- return MATCH_DEVNODE_BLIST; +- return 0; ++ log_filter(dev, vendor, product, NULL, NULL, NULL, r); ++ return r; + } + + int + filter_devnode (vector blist, vector elist, char * dev) + { +- int r = _filter_devnode(blist, elist, dev); ++ int r = MATCH_NOTHING; ++ ++ if (dev) { ++ if (_blacklist_exceptions(elist, dev)) ++ r = MATCH_DEVNODE_BLIST_EXCEPT; ++ else if (_blacklist(blist, dev)) ++ r = MATCH_DEVNODE_BLIST; ++ } ++ + log_filter(dev, NULL, NULL, NULL, NULL, NULL, r); + return r; + } + + int +-_filter_wwid (vector blist, vector elist, char * wwid) +-{ +- if (!wwid) +- return 0; +- if (_blacklist_exceptions(elist, wwid)) +- return MATCH_WWID_BLIST_EXCEPT; +- if (_blacklist(blist, wwid)) +- return MATCH_WWID_BLIST; +- return 0; +-} +- +-int + filter_wwid (vector blist, vector elist, char * wwid, char * dev) + { +- int r = _filter_wwid(blist, elist, wwid); ++ int r = MATCH_NOTHING; ++ ++ if (wwid) { ++ if (_blacklist_exceptions(elist, wwid)) ++ r = MATCH_WWID_BLIST_EXCEPT; ++ else if (_blacklist(blist, wwid)) ++ r = MATCH_WWID_BLIST; ++ } ++ + log_filter(dev, NULL, NULL, wwid, NULL, NULL, r); + return r; + } + +-static int +-_filter_protocol (vector blist, vector elist, const char * protocol_str) +-{ +- if (_blacklist_exceptions(elist, protocol_str)) +- return MATCH_PROTOCOL_BLIST_EXCEPT; +- if (_blacklist(blist, protocol_str)) +- return MATCH_PROTOCOL_BLIST; +- return 0; +-} +- + int + filter_protocol(vector blist, vector elist, struct path * pp) + { + char buf[PROTOCOL_BUF_SIZE]; +- int r; ++ int r = MATCH_NOTHING; ++ ++ if (pp) { ++ snprint_path_protocol(buf, sizeof(buf), pp); ++ ++ if (_blacklist_exceptions(elist, buf)) ++ r = MATCH_PROTOCOL_BLIST_EXCEPT; ++ else if (_blacklist(blist, buf)) ++ r = MATCH_PROTOCOL_BLIST; ++ } + +- snprint_path_protocol(buf, sizeof(buf), pp); +- r = _filter_protocol(blist, elist, buf); + log_filter(pp->dev, NULL, NULL, NULL, NULL, buf, r); + return r; + } + + int +-_filter_path (struct config * conf, struct path * pp) ++filter_path (struct config * conf, struct path * pp) + { + int r; + + r = filter_property(conf, pp->udev); + if (r > 0) + return r; +- r = _filter_devnode(conf->blist_devnode, conf->elist_devnode,pp->dev); ++ r = filter_devnode(conf->blist_devnode, conf->elist_devnode, pp->dev); + if (r > 0) + return r; +- r = _filter_device(conf->blist_device, conf->elist_device, +- pp->vendor_id, pp->product_id); ++ r = filter_device(conf->blist_device, conf->elist_device, ++ pp->vendor_id, pp->product_id, pp->dev); + if (r > 0) + return r; + r = filter_protocol(conf->blist_protocol, conf->elist_protocol, pp); + if (r > 0) + return r; +- r = _filter_wwid(conf->blist_wwid, conf->elist_wwid, pp->wwid); ++ r = filter_wwid(conf->blist_wwid, conf->elist_wwid, pp->wwid, pp->dev); + return r; + } + + int +-filter_path (struct config * conf, struct path * pp) +-{ +- int r=_filter_path(conf, pp); +- log_filter(pp->dev, pp->vendor_id, pp->product_id, pp->wwid, NULL, +- NULL, r); +- return r; +-} +- +-int +-_filter_property (struct config *conf, const char *env) +-{ +- if (_blacklist_exceptions(conf->elist_property, env)) +- return MATCH_PROPERTY_BLIST_EXCEPT; +- if (_blacklist(conf->blist_property, env)) +- return MATCH_PROPERTY_BLIST; +- +- return 0; +-} +- +-int + filter_property(struct config * conf, struct udev_device * udev) + { + const char *devname = udev_device_get_sysname(udev); + struct udev_list_entry *list_entry; +- int r; +- +- if (!udev) +- return 0; +- +- udev_list_entry_foreach(list_entry, ++ const char *env = NULL; ++ int r = MATCH_NOTHING; ++ ++ if (udev) { ++ /* ++ * This is the inverse of the 'normal' matching; ++ * the environment variable _has_ to match. ++ */ ++ r = MATCH_PROPERTY_BLIST_MISSING; ++ udev_list_entry_foreach(list_entry, + udev_device_get_properties_list_entry(udev)) { +- const char *env; +- +- env = udev_list_entry_get_name(list_entry); +- if (!env) +- continue; + +- r = _filter_property(conf, env); +- if (r) { +- log_filter(devname, NULL, NULL, NULL, env, NULL, r); +- return r; ++ env = udev_list_entry_get_name(list_entry); ++ if (!env) ++ continue; ++ if (_blacklist_exceptions(conf->elist_property, env)) { ++ r = MATCH_PROPERTY_BLIST_EXCEPT; ++ break; ++ } ++ if (_blacklist(conf->blist_property, env)) { ++ r = MATCH_PROPERTY_BLIST; ++ break; ++ } ++ env = NULL; + } + } + +- /* +- * This is the inverse of the 'normal' matching; +- * the environment variable _has_ to match. +- */ +- log_filter(devname, NULL, NULL, NULL, NULL, NULL, +- MATCH_PROPERTY_BLIST_MISSING); +- return MATCH_PROPERTY_BLIST_MISSING; ++ log_filter(devname, NULL, NULL, NULL, env, NULL, r); ++ return r; + } + + static void free_ble(struct blentry *ble) +diff --git a/libmultipath/blacklist.h b/libmultipath/blacklist.h +index f7beef2..18903b6 100644 +--- a/libmultipath/blacklist.h ++++ b/libmultipath/blacklist.h +@@ -35,7 +35,7 @@ int setup_default_blist (struct config *); + int alloc_ble_device (vector); + int filter_devnode (vector, vector, char *); + int filter_wwid (vector, vector, char *, char *); +-int filter_device (vector, vector, char *, char *); ++int filter_device (vector, vector, char *, char *, char *); + int filter_path (struct config *, struct path *); + int filter_property(struct config *, struct udev_device *); + int filter_protocol(vector, vector, struct path *); +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 5c54f9b..09c3dcf 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -1030,7 +1030,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + invalid = 1; + pthread_cleanup_pop(1); + if (invalid) { +- orphan_path(pp1, "wwid blacklisted"); ++ orphan_path(pp1, "blacklisted"); + continue; + } + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index e58a3fa..0b1855d 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1887,7 +1887,7 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + + if (mask & DI_BLACKLIST && mask & DI_SYSFS) { + if (filter_device(conf->blist_device, conf->elist_device, +- pp->vendor_id, pp->product_id) > 0 || ++ pp->vendor_id, pp->product_id, pp->dev) > 0 || + filter_protocol(conf->blist_protocol, conf->elist_protocol, + pp) > 0) + return PATHINFO_SKIPPED; +-- +2.7.4 + diff --git a/0008-multipath-tests-change-to-work-with-old-make-version.patch b/0008-multipath-tests-change-to-work-with-old-make-version.patch new file mode 100644 index 0000000..186015a --- /dev/null +++ b/0008-multipath-tests-change-to-work-with-old-make-version.patch @@ -0,0 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 3 Jul 2018 19:59:33 -0500 +Subject: [PATCH] multipath tests: change to work with old make versions + +the $(file <) operation only works with make 4.2 and above. I tried +running the tests on an old machine and it failed. The $shell function +can do the same thing and multipath has been using that in its +Makefiles for a while. + +Signed-off-by: Benjamin Marzinski +--- + tests/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/Makefile b/tests/Makefile +index 78755ed..d293c87 100644 +--- a/tests/Makefile ++++ b/tests/Makefile +@@ -51,4 +51,4 @@ COLON:=: + $(multipathdir)/libmultipath.so Makefile + $(CC) $(CFLAGS) -o $@ $(LDFLAGS) $< $($@_TESTDEPS) $($@_OBJDEPS) \ + $(LIBDEPS) $($@_LIBDEPS) \ +- $(file <$<.wrap) $(foreach dep,$($@_TESTDEPS),$(file <$(dep).wrap)) ++ $(shell cat $<.wrap) $(foreach dep,$($@_TESTDEPS),$(shell cat $(dep).wrap)) +-- +2.7.4 + diff --git a/0009-multipath-tests-add-blacklist-tests.patch b/0009-multipath-tests-add-blacklist-tests.patch new file mode 100644 index 0000000..cf7eff8 --- /dev/null +++ b/0009-multipath-tests-add-blacklist-tests.patch @@ -0,0 +1,559 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 12 Jul 2018 17:53:38 -0500 +Subject: [PATCH] multipath tests: add blacklist tests + +These are tests to validate the filter_* blacklist functions. They not +only verify that the device is correctly blacklisted/whitelisted, but +they also verify the log messages that are printed out. + +Signed-off-by: Benjamin Marzinski +--- + tests/Makefile | 4 +- + tests/blacklist.c | 512 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 515 insertions(+), 1 deletion(-) + create mode 100644 tests/blacklist.c + +diff --git a/tests/Makefile b/tests/Makefile +index d293c87..98b5c93 100644 +--- a/tests/Makefile ++++ b/tests/Makefile +@@ -3,7 +3,7 @@ include ../Makefile.inc + CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir) + LIBDEPS += -L$(multipathdir) -lmultipath -lcmocka + +-TESTS := uevent parser util dmevents hwtable ++TESTS := uevent parser util dmevents hwtable blacklist + + .SILENT: $(TESTS:%=%.o) + .PRECIOUS: $(TESTS:%=%-test) +@@ -23,6 +23,8 @@ hwtable-test_TESTDEPS := test-lib.o + hwtable-test_OBJDEPS := ../libmultipath/discovery.o ../libmultipath/blacklist.o \ + ../libmultipath/prio.o ../libmultipath/callout.o ../libmultipath/structs.o + hwtable-test_LIBDEPS := -ludev -lpthread -ldl ++blacklist-test_OBJDEPS := ../libmultipath/blacklist.o ++blacklist-test_LIBDEPS := -ludev + + %.out: %-test + @echo == running $< == +diff --git a/tests/blacklist.c b/tests/blacklist.c +new file mode 100644 +index 0000000..a55c1c0 +--- /dev/null ++++ b/tests/blacklist.c +@@ -0,0 +1,512 @@ ++/* ++ * Copyright (c) 2018 Benjamin Marzinski, Redhat ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * 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 for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ */ ++#include ++#include ++#include ++#include ++#include "globals.c" ++#include "blacklist.h" ++#include "log.h" ++ ++struct udev_device { ++ const char *sysname; ++ char *property_list[]; ++}; ++ ++const char * ++__wrap_udev_device_get_sysname(struct udev_device *udev_device) ++{ ++ assert_non_null(udev_device); ++ assert_non_null(udev_device->sysname); ++ return udev_device->sysname; ++} ++ ++struct udev_list_entry * ++__wrap_udev_device_get_properties_list_entry(struct udev_device *udev_device) ++{ ++ assert_non_null(udev_device); ++ if (!udev_device->property_list) ++ return NULL; ++ if (!*udev_device->property_list) ++ return NULL; ++ return (struct udev_list_entry *)udev_device->property_list; ++} ++ ++struct udev_list_entry * ++__wrap_udev_list_entry_get_next(struct udev_list_entry *list_entry) ++{ ++ assert_non_null(list_entry); ++ if (!*((char **)list_entry + 1)) ++ return NULL; ++ return (struct udev_list_entry *)(((char **)list_entry) + 1); ++} ++ ++const char * ++__wrap_udev_list_entry_get_name(struct udev_list_entry *list_entry) ++{ ++ return *(const char **)list_entry; ++} ++ ++void __wrap_dlog (int sink, int prio, const char * fmt, ...) ++{ ++ char buff[MAX_MSG_SIZE]; ++ va_list ap; ++ ++ assert_int_equal(prio, mock_type(int)); ++ va_start(ap, fmt); ++ vsnprintf(buff, MAX_MSG_SIZE, fmt, ap); ++ va_end(ap); ++ assert_string_equal(buff, mock_ptr_type(char *)); ++} ++ ++void expect_condlog(int prio, char *string) ++{ ++ will_return(__wrap_dlog, prio); ++ will_return(__wrap_dlog, string); ++} ++ ++vector blist_devnode_sdb; ++vector blist_all; ++vector blist_device_foo_bar; ++vector blist_device_all; ++vector blist_wwid_xyzzy; ++vector blist_protocol_fcp; ++vector blist_property_wwn; ++ ++static int setup(void **state) ++{ ++ blist_devnode_sdb = vector_alloc(); ++ if (!blist_devnode_sdb || ++ store_ble(blist_devnode_sdb, strdup("sdb"), ORIGIN_CONFIG)) ++ return -1; ++ ++ blist_all = vector_alloc(); ++ if (!blist_all || store_ble(blist_all, strdup(".*"), ORIGIN_CONFIG)) ++ return -1; ++ ++ blist_device_foo_bar = vector_alloc(); ++ if (!blist_device_foo_bar || alloc_ble_device(blist_device_foo_bar) || ++ set_ble_device(blist_device_foo_bar, strdup("foo"), strdup("bar"), ++ ORIGIN_CONFIG)) ++ return -1; ++ ++ blist_device_all = vector_alloc(); ++ if (!blist_device_all || alloc_ble_device(blist_device_all) || ++ set_ble_device(blist_device_all, strdup(".*"), strdup(".*"), ++ ORIGIN_CONFIG)) ++ return -1; ++ ++ blist_wwid_xyzzy = vector_alloc(); ++ if (!blist_wwid_xyzzy || ++ store_ble(blist_wwid_xyzzy, strdup("xyzzy"), ORIGIN_CONFIG)) ++ return -1; ++ ++ blist_protocol_fcp = vector_alloc(); ++ if (!blist_protocol_fcp || ++ store_ble(blist_protocol_fcp, strdup("scsi:fcp"), ORIGIN_CONFIG)) ++ return -1; ++ ++ blist_property_wwn = vector_alloc(); ++ if (!blist_property_wwn || ++ store_ble(blist_property_wwn, strdup("ID_WWN"), ORIGIN_CONFIG)) ++ return -1; ++ ++ return 0; ++} ++ ++static int teardown(void **state) ++{ ++ free_blacklist(blist_devnode_sdb); ++ free_blacklist(blist_all); ++ free_blacklist_device(blist_device_foo_bar); ++ free_blacklist_device(blist_device_all); ++ free_blacklist(blist_wwid_xyzzy); ++ free_blacklist(blist_protocol_fcp); ++ free_blacklist(blist_property_wwn); ++ return 0; ++} ++ ++static int reset_blists(void **state) ++{ ++ conf.blist_devnode = NULL; ++ conf.blist_wwid = NULL; ++ conf.blist_property = NULL; ++ conf.blist_protocol = NULL; ++ conf.blist_device = NULL; ++ conf.elist_devnode = NULL; ++ conf.elist_wwid = NULL; ++ conf.elist_property = NULL; ++ conf.elist_protocol = NULL; ++ conf.elist_device = NULL; ++ return 0; ++} ++ ++static void test_devnode_blacklist(void **state) ++{ ++ expect_condlog(3, "sdb: device node name blacklisted\n"); ++ assert_int_equal(filter_devnode(blist_devnode_sdb, NULL, "sdb"), ++ MATCH_DEVNODE_BLIST); ++} ++ ++static void test_devnode_whitelist(void **state) ++{ ++ expect_condlog(3, "sdb: device node name whitelisted\n"); ++ assert_int_equal(filter_devnode(blist_all, blist_devnode_sdb, "sdb"), ++ MATCH_DEVNODE_BLIST_EXCEPT); ++ expect_condlog(3, "sdc: device node name blacklisted\n"); ++ assert_int_equal(filter_devnode(blist_all, blist_devnode_sdb, "sdc"), ++ MATCH_DEVNODE_BLIST); ++} ++ ++static void test_devnode_missing(void **state) ++{ ++ assert_int_equal(filter_devnode(blist_devnode_sdb, NULL, "sdc"), ++ MATCH_NOTHING); ++} ++ ++static void test_device_blacklist(void **state) ++{ ++ expect_condlog(3, "sdb: (foo:bar) vendor/product blacklisted\n"); ++ assert_int_equal(filter_device(blist_device_foo_bar, NULL, "foo", ++ "bar", "sdb"), ++ MATCH_DEVICE_BLIST); ++} ++ ++static void test_device_whitelist(void **state) ++{ ++ expect_condlog(3, "sdb: (foo:bar) vendor/product whitelisted\n"); ++ assert_int_equal(filter_device(blist_device_all, blist_device_foo_bar, ++ "foo", "bar", "sdb"), ++ MATCH_DEVICE_BLIST_EXCEPT); ++ expect_condlog(3, "sdb: (foo:baz) vendor/product blacklisted\n"); ++ assert_int_equal(filter_device(blist_device_all, blist_device_foo_bar, ++ "foo", "baz", "sdb"), ++ MATCH_DEVICE_BLIST); ++} ++ ++static void test_device_missing(void **state) ++{ ++ assert_int_equal(filter_device(blist_device_foo_bar, NULL, "foo", ++ "baz", "sdb"), ++ MATCH_NOTHING); ++} ++ ++static void test_wwid_blacklist(void **state) ++{ ++ expect_condlog(3, "sdb: wwid xyzzy blacklisted\n"); ++ assert_int_equal(filter_wwid(blist_wwid_xyzzy, NULL, "xyzzy", "sdb"), ++ MATCH_WWID_BLIST); ++} ++ ++static void test_wwid_whitelist(void **state) ++{ ++ expect_condlog(3, "sdb: wwid xyzzy whitelisted\n"); ++ assert_int_equal(filter_wwid(blist_all, blist_wwid_xyzzy, ++ "xyzzy", "sdb"), ++ MATCH_WWID_BLIST_EXCEPT); ++ expect_condlog(3, "sdb: wwid plugh blacklisted\n"); ++ assert_int_equal(filter_wwid(blist_all, blist_wwid_xyzzy, ++ "plugh", "sdb"), ++ MATCH_WWID_BLIST); ++} ++ ++static void test_wwid_missing(void **state) ++{ ++ assert_int_equal(filter_wwid(blist_wwid_xyzzy, NULL, "plugh", "sdb"), ++ MATCH_NOTHING); ++} ++ ++static void test_protocol_blacklist(void **state) ++{ ++ struct path pp = { .dev = "sdb", .bus = SYSFS_BUS_SCSI, ++ .sg_id.proto_id = SCSI_PROTOCOL_FCP }; ++ expect_condlog(3, "sdb: protocol scsi:fcp blacklisted\n"); ++ assert_int_equal(filter_protocol(blist_protocol_fcp, NULL, &pp), ++ MATCH_PROTOCOL_BLIST); ++} ++ ++static void test_protocol_whitelist(void **state) ++{ ++ struct path pp1 = { .dev = "sdb", .bus = SYSFS_BUS_SCSI, ++ .sg_id.proto_id = SCSI_PROTOCOL_FCP }; ++ struct path pp2 = { .dev = "sdb", .bus = SYSFS_BUS_SCSI, ++ .sg_id.proto_id = SCSI_PROTOCOL_ISCSI }; ++ expect_condlog(3, "sdb: protocol scsi:fcp whitelisted\n"); ++ assert_int_equal(filter_protocol(blist_all, blist_protocol_fcp, &pp1), ++ MATCH_PROTOCOL_BLIST_EXCEPT); ++ expect_condlog(3, "sdb: protocol scsi:iscsi blacklisted\n"); ++ assert_int_equal(filter_protocol(blist_all, blist_protocol_fcp, &pp2), ++ MATCH_PROTOCOL_BLIST); ++} ++ ++static void test_protocol_missing(void **state) ++{ ++ struct path pp = { .dev = "sdb", .bus = SYSFS_BUS_SCSI, ++ .sg_id.proto_id = SCSI_PROTOCOL_ISCSI }; ++ assert_int_equal(filter_protocol(blist_protocol_fcp, NULL, &pp), ++ MATCH_NOTHING); ++} ++ ++static void test_property_blacklist(void **state) ++{ ++ static struct udev_device udev = { "sdb", { "ID_FOO", "ID_WWN", "ID_BAR", NULL } }; ++ conf.blist_property = blist_property_wwn; ++ expect_condlog(3, "sdb: udev property ID_WWN blacklisted\n"); ++ assert_int_equal(filter_property(&conf, &udev), MATCH_PROPERTY_BLIST); ++} ++ ++/* the property check works different in that you check all the property ++ * names, so setting a blacklist value will blacklist the device if any ++ * of the property on the blacklist are found before the property names ++ * in the whitelist. This might be worth changing. although it would ++ * force multipath to go through the properties twice */ ++static void test_property_whitelist(void **state) ++{ ++ static struct udev_device udev = { "sdb", { "ID_FOO", "ID_WWN", "ID_BAR", NULL } }; ++ conf.elist_property = blist_property_wwn; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ assert_int_equal(filter_property(&conf, &udev), ++ MATCH_PROPERTY_BLIST_EXCEPT); ++} ++ ++static void test_property_missing(void **state) ++{ ++ static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", NULL } }; ++ conf.blist_property = blist_property_wwn; ++ expect_condlog(3, "sdb: blacklisted, udev property missing\n"); ++ assert_int_equal(filter_property(&conf, &udev), ++ MATCH_PROPERTY_BLIST_MISSING); ++} ++ ++struct udev_device test_udev = { "sdb", { "ID_FOO", "ID_WWN", "ID_BAR", NULL } }; ++ ++struct path test_pp = { .dev = "sdb", .bus = SYSFS_BUS_SCSI, .udev = &test_udev, ++ .sg_id.proto_id = SCSI_PROTOCOL_FCP, .vendor_id = "foo", ++ .product_id = "bar", .wwid = "xyzzy" }; ++ ++static void test_filter_path_property(void **state) ++{ ++ conf.blist_property = blist_property_wwn; ++ expect_condlog(3, "sdb: udev property ID_WWN blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_PROPERTY_BLIST); ++} ++ ++static void test_filter_path_devnode(void **state) ++{ ++ /* always must include property elist, to avoid "missing property" ++ * blacklisting */ ++ conf.elist_property = blist_property_wwn; ++ conf.blist_devnode = blist_devnode_sdb; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ expect_condlog(3, "sdb: device node name blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_DEVNODE_BLIST); ++} ++ ++static void test_filter_path_device(void **state) ++{ ++ /* always must include property elist, to avoid "missing property" ++ * blacklisting */ ++ conf.elist_property = blist_property_wwn; ++ conf.blist_device = blist_device_foo_bar; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ expect_condlog(3, "sdb: (foo:bar) vendor/product blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_DEVICE_BLIST); ++} ++ ++static void test_filter_path_protocol(void **state) ++{ ++ conf.elist_property = blist_property_wwn; ++ conf.blist_protocol = blist_protocol_fcp; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ expect_condlog(3, "sdb: protocol scsi:fcp blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_PROTOCOL_BLIST); ++} ++ ++static void test_filter_path_wwid(void **state) ++{ ++ conf.elist_property = blist_property_wwn; ++ conf.blist_wwid = blist_wwid_xyzzy; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ expect_condlog(3, "sdb: wwid xyzzy blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_WWID_BLIST); ++} ++ ++struct udev_device miss_udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", NULL } }; ++ ++struct path miss1_pp = { .dev = "sdc", .bus = SYSFS_BUS_SCSI, ++ .udev = &miss_udev, ++ .sg_id.proto_id = SCSI_PROTOCOL_ISCSI, ++ .vendor_id = "foo", .product_id = "baz", ++ .wwid = "plugh" }; ++ ++struct path miss2_pp = { .dev = "sdc", .bus = SYSFS_BUS_SCSI, ++ .udev = &test_udev, ++ .sg_id.proto_id = SCSI_PROTOCOL_ISCSI, ++ .vendor_id = "foo", .product_id = "baz", ++ .wwid = "plugh" }; ++ ++static void test_filter_path_missing1(void **state) ++{ ++ conf.blist_property = blist_property_wwn; ++ conf.blist_devnode = blist_devnode_sdb; ++ conf.blist_device = blist_device_foo_bar; ++ conf.blist_protocol = blist_protocol_fcp; ++ conf.blist_wwid = blist_wwid_xyzzy; ++ expect_condlog(3, "sdb: blacklisted, udev property missing\n"); ++ assert_int_equal(filter_path(&conf, &miss1_pp), ++ MATCH_PROPERTY_BLIST_MISSING); ++} ++ ++/* This one matches the property whitelist, to test the other missing ++ * functions */ ++static void test_filter_path_missing2(void **state) ++{ ++ conf.elist_property = blist_property_wwn; ++ conf.blist_devnode = blist_devnode_sdb; ++ conf.blist_device = blist_device_foo_bar; ++ conf.blist_protocol = blist_protocol_fcp; ++ conf.blist_wwid = blist_wwid_xyzzy; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ assert_int_equal(filter_path(&conf, &miss2_pp), ++ MATCH_NOTHING); ++} ++ ++static void test_filter_path_whitelist(void **state) ++{ ++ conf.elist_property = blist_property_wwn; ++ conf.elist_devnode = blist_devnode_sdb; ++ conf.elist_device = blist_device_foo_bar; ++ conf.elist_protocol = blist_protocol_fcp; ++ conf.elist_wwid = blist_wwid_xyzzy; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ expect_condlog(3, "sdb: device node name whitelisted\n"); ++ expect_condlog(3, "sdb: (foo:bar) vendor/product whitelisted\n"); ++ expect_condlog(3, "sdb: protocol scsi:fcp whitelisted\n"); ++ expect_condlog(3, "sdb: wwid xyzzy whitelisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), ++ MATCH_WWID_BLIST_EXCEPT); ++} ++ ++static void test_filter_path_whitelist_property(void **state) ++{ ++ conf.blist_property = blist_property_wwn; ++ conf.elist_devnode = blist_devnode_sdb; ++ conf.elist_device = blist_device_foo_bar; ++ conf.elist_protocol = blist_protocol_fcp; ++ conf.elist_wwid = blist_wwid_xyzzy; ++ expect_condlog(3, "sdb: udev property ID_WWN blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_PROPERTY_BLIST); ++} ++ ++static void test_filter_path_whitelist_devnode(void **state) ++{ ++ conf.elist_property = blist_property_wwn; ++ conf.blist_devnode = blist_devnode_sdb; ++ conf.elist_device = blist_device_foo_bar; ++ conf.elist_protocol = blist_protocol_fcp; ++ conf.elist_wwid = blist_wwid_xyzzy; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ expect_condlog(3, "sdb: device node name blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_DEVNODE_BLIST); ++} ++ ++static void test_filter_path_whitelist_device(void **state) ++{ ++ conf.elist_property = blist_property_wwn; ++ conf.elist_devnode = blist_devnode_sdb; ++ conf.blist_device = blist_device_foo_bar; ++ conf.elist_protocol = blist_protocol_fcp; ++ conf.elist_wwid = blist_wwid_xyzzy; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ expect_condlog(3, "sdb: device node name whitelisted\n"); ++ expect_condlog(3, "sdb: (foo:bar) vendor/product blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_DEVICE_BLIST); ++} ++ ++static void test_filter_path_whitelist_protocol(void **state) ++{ ++ conf.elist_property = blist_property_wwn; ++ conf.elist_devnode = blist_devnode_sdb; ++ conf.elist_device = blist_device_foo_bar; ++ conf.blist_protocol = blist_protocol_fcp; ++ conf.elist_wwid = blist_wwid_xyzzy; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ expect_condlog(3, "sdb: device node name whitelisted\n"); ++ expect_condlog(3, "sdb: (foo:bar) vendor/product whitelisted\n"); ++ expect_condlog(3, "sdb: protocol scsi:fcp blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_PROTOCOL_BLIST); ++} ++ ++static void test_filter_path_whitelist_wwid(void **state) ++{ ++ conf.elist_property = blist_property_wwn; ++ conf.elist_devnode = blist_devnode_sdb; ++ conf.elist_device = blist_device_foo_bar; ++ conf.elist_protocol = blist_protocol_fcp; ++ conf.blist_wwid = blist_wwid_xyzzy; ++ expect_condlog(3, "sdb: udev property ID_WWN whitelisted\n"); ++ expect_condlog(3, "sdb: device node name whitelisted\n"); ++ expect_condlog(3, "sdb: (foo:bar) vendor/product whitelisted\n"); ++ expect_condlog(3, "sdb: protocol scsi:fcp whitelisted\n"); ++ expect_condlog(3, "sdb: wwid xyzzy blacklisted\n"); ++ assert_int_equal(filter_path(&conf, &test_pp), MATCH_WWID_BLIST); ++} ++ ++#define test_and_reset(x) cmocka_unit_test_teardown((x), reset_blists) ++ ++int test_blacklist(void) ++{ ++ const struct CMUnitTest tests[] = { ++ cmocka_unit_test(test_devnode_blacklist), ++ cmocka_unit_test(test_devnode_whitelist), ++ cmocka_unit_test(test_devnode_missing), ++ cmocka_unit_test(test_device_blacklist), ++ cmocka_unit_test(test_device_whitelist), ++ cmocka_unit_test(test_device_missing), ++ cmocka_unit_test(test_wwid_blacklist), ++ cmocka_unit_test(test_wwid_whitelist), ++ cmocka_unit_test(test_wwid_missing), ++ cmocka_unit_test(test_protocol_blacklist), ++ cmocka_unit_test(test_protocol_whitelist), ++ cmocka_unit_test(test_protocol_missing), ++ test_and_reset(test_property_blacklist), ++ test_and_reset(test_property_whitelist), ++ test_and_reset(test_property_missing), ++ test_and_reset(test_filter_path_property), ++ test_and_reset(test_filter_path_devnode), ++ test_and_reset(test_filter_path_device), ++ test_and_reset(test_filter_path_protocol), ++ test_and_reset(test_filter_path_wwid), ++ test_and_reset(test_filter_path_missing1), ++ test_and_reset(test_filter_path_missing2), ++ test_and_reset(test_filter_path_whitelist), ++ test_and_reset(test_filter_path_whitelist_property), ++ test_and_reset(test_filter_path_whitelist_devnode), ++ test_and_reset(test_filter_path_whitelist_device), ++ test_and_reset(test_filter_path_whitelist_protocol), ++ test_and_reset(test_filter_path_whitelist_wwid), ++ }; ++ return cmocka_run_group_tests(tests, setup, teardown); ++} ++ ++int main(void) ++{ ++ int ret = 0; ++ ret += test_blacklist(); ++ return ret; ++} +-- +2.7.4 + diff --git a/0010-mpathpersist-add-missing-param-rk-usage-info.patch b/0010-mpathpersist-add-missing-param-rk-usage-info.patch new file mode 100644 index 0000000..e05d9e6 --- /dev/null +++ b/0010-mpathpersist-add-missing-param-rk-usage-info.patch @@ -0,0 +1,25 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 16 Jul 2018 16:43:57 -0500 +Subject: [PATCH] mpathpersist: add missing --param-rk usage info + +Signed-off-by: Benjamin Marzinski +--- + mpathpersist/main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/mpathpersist/main.c b/mpathpersist/main.c +index 99151fe..0e4d3f2 100644 +--- a/mpathpersist/main.c ++++ b/mpathpersist/main.c +@@ -705,6 +705,7 @@ static void usage(void) + " --param-alltgpt|-Y PR Out parameter 'ALL_TG_PT\n" + " --param-aptpl|-Z PR Out parameter 'APTPL'\n" + " --read-keys|-k PR In: Read Keys\n" ++ " --param-rk=RK|-K RK PR Out parameter reservation key\n" + " --param-sark=SARK|-S SARK PR Out parameter service " + "action\n" + " reservation key (SARK is in " +-- +2.7.4 + diff --git a/0011-change-order-of-multipath.rules.patch b/0011-change-order-of-multipath.rules.patch new file mode 100644 index 0000000..90de0e7 --- /dev/null +++ b/0011-change-order-of-multipath.rules.patch @@ -0,0 +1,39 @@ +From 4340aca696857c1077b00ff6bdc0454a07929aad Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 15 May 2015 18:14:09 -0500 +Subject: [PATCH] change order of multipath.rules + +At least for RedHat, the rule that calls scsi_id is +60-persistent-storage.rules, so the multipath rule needs to come +after this. + +Signed-off-by: Benjamin Marzinski +--- + multipath/Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/multipath/Makefile b/multipath/Makefile +index 0828a8f..b9bbb3c 100644 +--- a/multipath/Makefile ++++ b/multipath/Makefile +@@ -24,7 +24,7 @@ install: + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) + $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) +- $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules ++ $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) +@@ -33,7 +33,7 @@ install: + uninstall: + $(RM) $(DESTDIR)$(bindir)/$(EXEC) + $(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules +- $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules ++ $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules + $(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz + $(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz + +-- +1.8.3.1 + diff --git a/0012-RH-Remove-the-property-blacklist-exception-builtin.patch b/0012-RH-Remove-the-property-blacklist-exception-builtin.patch new file mode 100644 index 0000000..87eba36 --- /dev/null +++ b/0012-RH-Remove-the-property-blacklist-exception-builtin.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 2 Jul 2014 12:49:53 -0500 +Subject: [PATCH] RH: Remove the property blacklist exception builtin + +Multipath set the default property blacklist exceptions to +(ID_SCSI_VPD|ID_WWN). This has the effect of blacklisting some internal +devices. These devices may never have multiple paths, but it is nice +to be able to set multipath up on them all the same. This patch simply +removes the default, and makes it so that if no property +blacklist_exception is given, then devices aren't failed for not matching +it. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/blacklist.c | 12 ++++-------- + multipath/multipath.conf.5 | 14 ++++++-------- + 2 files changed, 10 insertions(+), 16 deletions(-) + +diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c +index 318ec03..c0cfbca 100644 +--- a/libmultipath/blacklist.c ++++ b/libmultipath/blacklist.c +@@ -204,12 +204,6 @@ setup_default_blist (struct config * conf) + if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT)) + return 1; + +- str = STRDUP("(SCSI_IDENT_|ID_WWN)"); +- if (!str) +- return 1; +- if (store_ble(conf->elist_property, str, ORIGIN_DEFAULT)) +- return 1; +- + vector_foreach_slot (conf->hwtable, hwe, i) { + if (hwe->bl_product) { + if (find_blacklist_device(conf->blist_device, +@@ -394,9 +388,11 @@ filter_property(struct config * conf, struct udev_device * udev) + if (udev) { + /* + * This is the inverse of the 'normal' matching; +- * the environment variable _has_ to match. ++ * the environment variable _has_ to match ++ * if a whitelist is present. + */ +- r = MATCH_PROPERTY_BLIST_MISSING; ++ if (VECTOR_SIZE(conf->elist_property)) ++ r = MATCH_PROPERTY_BLIST_MISSING; + udev_list_entry_foreach(list_entry, + udev_device_get_properties_list_entry(udev)) { + +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index 6333366..3dab26b 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -1195,16 +1195,14 @@ keywords. Both are regular expressions. For a full description of these keywords + Regular expression for an udev property. All + devices that have matching udev properties will be excluded/included. + The handling of the \fIproperty\fR keyword is special, +-because devices \fBmust\fR have at least one whitelisted udev property; ++because if a property blacklist_exception is set, devices \fBmust\fR have at ++least one whitelisted udev property; + otherwise they're treated as blacklisted, and the message + "\fIblacklisted, udev property missing\fR" is displayed in the logs. +-. +-.RS +-.PP +-The default \fIblacklist exception\fR is: \fB(SCSI_IDENT_|ID_WWN)\fR, causing +-well-behaved SCSI devices and devices that provide a WWN (World Wide Number) +-to be included, and all others to be excluded. +-.RE ++For example, setting the property blacklist_exception to ++\fB(SCSI_IDENT_|ID_WWN)\fR, will cause well-behaved SCSI devices and devices ++that provide a WWN (World Wide Number) to be included, and all others to be ++excluded. This works to exclude most non-multipathable devices. + .TP + .B protocol + Regular expression for the protocol of a device to be excluded/included. +-- +2.7.4 + diff --git a/6000-libmultipath-fix-set_int-error-path.patch b/6000-libmultipath-fix-set_int-error-path.patch new file mode 100644 index 0000000..0cdcfbd --- /dev/null +++ b/6000-libmultipath-fix-set_int-error-path.patch @@ -0,0 +1,34 @@ +From 8f9ac30dcb144d4ce79f88e8a01fba0968da3a07 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Oct 2018 18:03:03 -0500 +Subject: [PATCH] libmultipath: fix set_int error path + +set_int() wasn't checking if the line actually had a value before +converting it to an integer. Found by coverity. Also, it should +be using set_value(). + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/dict.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index 32524d5f..bf4701ee 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -33,7 +33,10 @@ set_int(vector strvec, void *ptr) + int *int_ptr = (int *)ptr; + char * buff; + +- buff = VECTOR_SLOT(strvec, 1); ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ + *int_ptr = atoi(buff); + + return 0; +-- +2.11.0 + diff --git a/6001-libmultipath-free-allocated-value-in-set_int.patch b/6001-libmultipath-free-allocated-value-in-set_int.patch new file mode 100644 index 0000000..5dfa3c7 --- /dev/null +++ b/6001-libmultipath-free-allocated-value-in-set_int.patch @@ -0,0 +1,28 @@ +From 5e71f6eb17cbb119f0f995f234bf1887a4f77058 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 11 Oct 2018 15:43:47 -0500 +Subject: [PATCH] libmultipath: free allocated value in set_int + +set_int() needs to free the buffer it got back from set_value() + +Fixes: 8f9ac30d ("libmultipath: fix set_int error path") +Signed-off-by: Benjamin Marzinski +--- + libmultipath/dict.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index bf4701ee..c3f5a6e6 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -39,6 +39,7 @@ set_int(vector strvec, void *ptr) + + *int_ptr = atoi(buff); + ++ FREE(buff); + return 0; + } + +-- +2.11.0 + diff --git a/6002-libmultipath-fix-memory-issue-in-path_latency-prio.patch b/6002-libmultipath-fix-memory-issue-in-path_latency-prio.patch new file mode 100644 index 0000000..e490a8a --- /dev/null +++ b/6002-libmultipath-fix-memory-issue-in-path_latency-prio.patch @@ -0,0 +1,32 @@ +From c3b739527258dae7ebe4b5d083a33ce527675082 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Oct 2018 18:03:07 -0500 +Subject: [PATCH] libmultipath: fix memory issue in path_latency prio + +The path_latency prioriziter was assuming that prepare_directio_read() +always succeeds. However, it doesn't, and when it fails, the prioritizer +used buf without it pointing to alloced memory. Found by coverity. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/prioritizers/path_latency.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/prioritizers/path_latency.c b/libmultipath/prioritizers/path_latency.c +index 765265c0..eeee01e1 100644 +--- a/libmultipath/prioritizers/path_latency.c ++++ b/libmultipath/prioritizers/path_latency.c +@@ -237,7 +237,8 @@ int getprio(struct path *pp, char *args, unsigned int timeout) + lg_maxavglatency = log(MAX_AVG_LATENCY) / lg_base; + lg_minavglatency = log(MIN_AVG_LATENCY) / lg_base; + +- prepare_directio_read(pp->fd, &blksize, &buf, &restore_flags); ++ if (prepare_directio_read(pp->fd, &blksize, &buf, &restore_flags) < 0) ++ return PRIO_UNDEF; + + temp = io_num; + while (temp-- > 0) { +-- +2.11.0 + diff --git a/6003-libmultipath-fix-null-dereference-int-alloc_path_group.patch b/6003-libmultipath-fix-null-dereference-int-alloc_path_group.patch new file mode 100644 index 0000000..50e5ac1 --- /dev/null +++ b/6003-libmultipath-fix-null-dereference-int-alloc_path_group.patch @@ -0,0 +1,31 @@ +From 156b75082c7c5d5aa832e500cf4175c3f943fa22 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Oct 2018 18:03:08 -0500 +Subject: [PATCH] libmultipath: fix null dereference int alloc_path_group + +If all_pathgroup failed to allocate a vector for pgp->paths, instead of +failing after it freed pgp, it would set pgp to NULL and then +dereference it. This patch fixes that. Found by coverity. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/structs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/structs.c b/libmultipath/structs.c +index ae847d61..caa178a6 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -165,7 +165,7 @@ alloc_pathgroup (void) + + if (!pgp->paths) { + FREE(pgp); +- pgp = NULL; ++ return NULL; + } + + dm_pathgroup_to_gen(pgp)->ops = &dm_gen_pathgroup_ops; +-- +2.11.0 + diff --git a/6004-multipath-fix-max-array-size-in-print_cmd_valid.patch b/6004-multipath-fix-max-array-size-in-print_cmd_valid.patch new file mode 100644 index 0000000..4f08d48 --- /dev/null +++ b/6004-multipath-fix-max-array-size-in-print_cmd_valid.patch @@ -0,0 +1,31 @@ +From b25493d8fa13c2d7a346e0b18ad4756aa733ff8d Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Oct 2018 18:03:10 -0500 +Subject: [PATCH] multipath: fix max array size in print_cmd_valid + +The code is attempting to verify that 0 <= k < 3 +However, sizeof(val) is 12, assuming 4 byte integers. The check needs to +take integer size into account. Found by coverity. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipath/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/multipath/main.c b/multipath/main.c +index fc5bf169..d5aad952 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -482,7 +482,7 @@ static int print_cmd_valid(int k, const vector pathvec, + struct timespec until; + struct path *pp; + +- if (k < 0 || k >= sizeof(vals)) ++ if (k < 0 || k >= (sizeof(vals) / sizeof(int))) + return 1; + + if (k == 2) { +-- +2.11.0 + diff --git a/6005-multipathd-minor-fixes.patch b/6005-multipathd-minor-fixes.patch new file mode 100644 index 0000000..844810e --- /dev/null +++ b/6005-multipathd-minor-fixes.patch @@ -0,0 +1,41 @@ +From b31f8f5a21a90fb9087c02e00b6b69934a5bbdd5 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Oct 2018 18:03:12 -0500 +Subject: [PATCH] multipathd: minor fixes + +In update_multipath(), conf is set again in a couple of lines, and +nothing uses it before then, so there's no point in setting it twice. +Also, in ev_remove_path(), strncpy() could end up unterminated, so +use strlcpy() instead. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index ba796ab1..cd963043 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -429,7 +429,7 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset) + continue; + + if (pp->state != PATH_DOWN) { +- struct config *conf = get_multipath_config(); ++ struct config *conf; + int oldstate = pp->state; + int checkint; + +@@ -1097,7 +1097,7 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map) + /* + * flush_map will fail if the device is open + */ +- strncpy(alias, mpp->alias, WWID_SIZE); ++ strlcpy(alias, mpp->alias, WWID_SIZE); + if (mpp->flush_on_last_del == FLUSH_ENABLED) { + condlog(2, "%s Last path deleted, disabling queueing", mpp->alias); + mpp->retry_tick = 0; +-- +2.11.0 + diff --git a/6006-multipathd-fix-memory-leak-on-error-in-configure.patch b/6006-multipathd-fix-memory-leak-on-error-in-configure.patch new file mode 100644 index 0000000..cb94629 --- /dev/null +++ b/6006-multipathd-fix-memory-leak-on-error-in-configure.patch @@ -0,0 +1,68 @@ +From 3b8da487d534eb49c8c59d1a9c2d6199c0716572 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 9 Oct 2018 18:03:14 -0500 +Subject: [PATCH] multipathd: fix memory leak on error in configure + +If configure fails after allocing mpvec, it must free it. Found by +coverity. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 463b1b82..04dce04c 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -2278,7 +2278,7 @@ configure (struct vectors * vecs) + ret = path_discovery(vecs->pathvec, DI_ALL); + if (ret < 0) { + condlog(0, "configure failed at path discovery"); +- return 1; ++ goto fail; + } + + vector_foreach_slot (vecs->pathvec, pp, i){ +@@ -2295,7 +2295,7 @@ configure (struct vectors * vecs) + } + if (map_discovery(vecs)) { + condlog(0, "configure failed at map discovery"); +- return 1; ++ goto fail; + } + + /* +@@ -2309,7 +2309,7 @@ configure (struct vectors * vecs) + force_reload = FORCE_RELOAD_YES; + if (ret) { + condlog(0, "configure failed while coalescing paths"); +- return 1; ++ goto fail; + } + + /* +@@ -2318,7 +2318,7 @@ configure (struct vectors * vecs) + */ + if (coalesce_maps(vecs, mpvec)) { + condlog(0, "configure failed while coalescing maps"); +- return 1; ++ goto fail; + } + + dm_lib_release(); +@@ -2354,6 +2354,10 @@ configure (struct vectors * vecs) + i--; + } + return 0; ++ ++fail: ++ vector_free(mpvec); ++ return 1; + } + + int +-- +2.11.0 + diff --git a/6007-multipathd-check-for-NULL-udevice-in-cli_add_path.patch b/6007-multipathd-check-for-NULL-udevice-in-cli_add_path.patch new file mode 100644 index 0000000..801cbae --- /dev/null +++ b/6007-multipathd-check-for-NULL-udevice-in-cli_add_path.patch @@ -0,0 +1,32 @@ +From e7a3324274578d63cdef23bb08410df20e0de862 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 10 Oct 2018 13:01:09 -0500 +Subject: [PATCH] multipathd: check for NULL udevice in cli_add_path + +If cli_add_path can't get a udevice for the path, it should fail +immediately, instead of continuing with a NULL udevice, since it will +fail in store_pathinfo() anyway. + +Signed-off-by: Benjamin Marzinski +--- + multipathd/cli_handlers.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index bb164726..75000807 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -720,6 +720,10 @@ cli_add_path (void * v, char ** reply, int * len, void * data) + udevice = udev_device_new_from_subsystem_sysname(udev, + "block", + param); ++ if (!udevice) { ++ condlog(0, "%s: can't find path", param); ++ return 1; ++ } + conf = get_multipath_config(); + pthread_cleanup_push(put_multipath_config, conf); + r = store_pathinfo(vecs->pathvec, conf, +-- +2.11.0 + diff --git a/6008-kpartx-fix-apparent-out-of-bounds-access.patch b/6008-kpartx-fix-apparent-out-of-bounds-access.patch new file mode 100644 index 0000000..f0f5db9 --- /dev/null +++ b/6008-kpartx-fix-apparent-out-of-bounds-access.patch @@ -0,0 +1,28 @@ +From 2578838d077ecd7f4555e90df019053e7131e151 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 8 Jan 2019 23:54:00 +0100 +Subject: [PATCH] kpartx(coverity): fix apparent out-of-bounds access + +This was a false positive. + +Signed-off-by: Martin Wilck +--- + kpartx/dasd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kpartx/dasd.c b/kpartx/dasd.c +index fb358add..61b609a5 100644 +--- a/kpartx/dasd.c ++++ b/kpartx/dasd.c +@@ -190,7 +190,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns) + memcpy (&vlabel, data, sizeof(vlabel)); + else { + bzero(&vlabel,4); +- memcpy (&vlabel.vollbl, data, sizeof(vlabel) - 4); ++ memcpy ((char *)&vlabel + 4, data, sizeof(vlabel) - 4); + } + vtoc_ebcdic_dec(vlabel.vollbl, type, 4); + +-- +2.11.0 + diff --git a/6009-libmultipath-fix-apparent-overflow.patch b/6009-libmultipath-fix-apparent-overflow.patch new file mode 100644 index 0000000..921cea9 --- /dev/null +++ b/6009-libmultipath-fix-apparent-overflow.patch @@ -0,0 +1,28 @@ +From 7d30130a5d53629e7c3420aa58018c75fa9dbeef Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 8 Jan 2019 23:54:02 +0100 +Subject: [PATCH] libmultipath(coverity): fix apparent overflow + +"preferred_path" contains always "0" or "1". + +Signed-off-by: Martin Wilck +--- + libmultipath/discovery.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 7f983a63..3fd79a36 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -520,7 +520,7 @@ sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen) + /* Parse error, ignore */ + return 0; + } +- return preferred; ++ return !!preferred; + } + + static void +-- +2.11.0 + diff --git a/6010-libmultipath-fix-int-overflow-in-sysfs_set_scsi_tmo.patch b/6010-libmultipath-fix-int-overflow-in-sysfs_set_scsi_tmo.patch new file mode 100644 index 0000000..4284271 --- /dev/null +++ b/6010-libmultipath-fix-int-overflow-in-sysfs_set_scsi_tmo.patch @@ -0,0 +1,27 @@ +From 3044fc0bd953faf71bfa6ebd98f2084f6ae1772b Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 8 Jan 2019 23:54:04 +0100 +Subject: [PATCH] libmultipath(coverity): fix int overflow in + sysfs_set_scsi_tmo + +Signed-off-by: Martin Wilck +--- + libmultipath/discovery.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 3fd79a36..1748eebb 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -711,7 +711,7 @@ sysfs_set_scsi_tmo (struct multipath *mpp, int checkint) + int dev_loss_tmo = mpp->dev_loss; + + if (mpp->no_path_retry > 0) { +- uint64_t no_path_retry_tmo = mpp->no_path_retry * checkint; ++ uint64_t no_path_retry_tmo = (uint64_t)mpp->no_path_retry * checkint; + + if (no_path_retry_tmo > MAX_DEV_LOSS_TMO) + no_path_retry_tmo = MAX_DEV_LOSS_TMO; +-- +2.11.0 + diff --git a/6011-libmultipath-fix-enum-misuse-for-find_multipaths.patch b/6011-libmultipath-fix-enum-misuse-for-find_multipaths.patch new file mode 100644 index 0000000..05c3b2c --- /dev/null +++ b/6011-libmultipath-fix-enum-misuse-for-find_multipaths.patch @@ -0,0 +1,26 @@ +From fb87e6e9d5778c9b2874496ff6e44c0001a3c228 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 8 Jan 2019 23:54:05 +0100 +Subject: [PATCH] libmultipath(coverity): fix "enum misuse" for find_multipaths + +Signed-off-by: Martin Wilck +--- + libmultipath/dict.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index fd29abca..eaad4f18 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -327,7 +327,7 @@ def_find_multipaths_handler(struct config *conf, vector strvec) + int i; + + if (set_yes_no_undef(strvec, &conf->find_multipaths) == 0 && +- conf->find_multipaths != YNU_UNDEF) ++ conf->find_multipaths != FIND_MULTIPATHS_UNDEF) + return 0; + + buff = set_value(strvec); +-- +2.11.0 + diff --git a/6012-libmultipath-fix-possible-NULL-dereference.patch b/6012-libmultipath-fix-possible-NULL-dereference.patch new file mode 100644 index 0000000..b21fbf7 --- /dev/null +++ b/6012-libmultipath-fix-possible-NULL-dereference.patch @@ -0,0 +1,28 @@ +From 7ec04256a56709963e8b954fc6036ca6ba1db137 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Tue, 8 Jan 2019 23:54:09 +0100 +Subject: [PATCH] libmultipath(coverity): fix possible NULL dereference + +coverity warns that recv_packet may set reply to NULL. + +Signed-off-by: Martin Wilck +--- + libmultipath/configure.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 39d2a956..af4d78de 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -1041,7 +1041,7 @@ int check_daemon(void) + if (recv_packet(fd, &reply, timeout) != 0) + goto out; + +- if (strstr(reply, "shutdown")) ++ if (reply && strstr(reply, "shutdown")) + goto out_free; + + ret = 1; +-- +2.11.0 + diff --git a/6013-multipathd-fix-mpp-hwe-handling-when-paths-are-freed.patch b/6013-multipathd-fix-mpp-hwe-handling-when-paths-are-freed.patch new file mode 100644 index 0000000..5de6b6d --- /dev/null +++ b/6013-multipathd-fix-mpp-hwe-handling-when-paths-are-freed.patch @@ -0,0 +1,109 @@ +multipathd: fix mpp->hwe handling when paths are freed + +Commit 1f962693 didn't deal with all of cases where a path that was part +of a multipath device could be removed. verify_paths() removes any path +that no longer exists in sysfs. mpp->hwe needs to be updated here as +well, since verify_paths() could remove the path whose hwe vector is +pointed to by mpp->hwe. Also, now that extract_hwe_from_path() is +called in verify_paths(), the extract_hwe_from_path() calls that +happened immediately after verify_paths() can be dropped. + +The other part of this fix is mostly cosmetic. In ev_add_path(), if +domap() fails after the path is added to the multipath device and +verify_paths() is called, the code can loop back to the rescan label. If +the size of the path or the multipath device changed in the interim, +ev_add_path() would remove the path, without updating mpp->hwe; but +there is no way for the size to change. Just to make that clearer in the +code, I've moved the size check to before the rescan label so it only +happens once. + +Fixes: 1f962693 "multipathd: fix mpp->hwe handling on path removal" +Cc: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/structs_vec.c | 7 +++++++ + multipathd/main.c | 22 ++++++++-------------- + 2 files changed, 15 insertions(+), 14 deletions(-) + +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index 828aef2..2808efe 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -418,6 +418,12 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs) + vector_del_slot(mpp->paths, i); + i--; + ++ /* Make sure mpp->hwe doesn't point to freed memory. ++ * We call extract_hwe_from_path() below to restore ++ * mpp->hwe ++ */ ++ if (mpp->hwe == pp->hwe) ++ mpp->hwe = NULL; + if ((j = find_slot(vecs->pathvec, + (void *)pp)) != -1) + vector_del_slot(vecs->pathvec, j); +@@ -427,6 +433,7 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs) + mpp->alias, pp->dev, pp->dev_t); + } + } ++ extract_hwe_from_path(mpp); + return count; + } + +diff --git a/multipathd/main.c b/multipathd/main.c +index 8de0871..872843c 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -472,7 +472,6 @@ retry: + verify_paths(mpp, vecs); + mpp->action = ACT_RELOAD; + +- extract_hwe_from_path(mpp); + if (setup_map(mpp, params, PARAMS_SIZE, vecs)) { + condlog(0, "%s: failed to setup new map in update", mpp->alias); + retries = -1; +@@ -948,6 +947,14 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map) + goto fail; /* leave path added to pathvec */ + } + mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); ++ if (mpp && 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); ++ free_path(pp); ++ return 1; ++ } + if (mpp && mpp->wait_for_udev && + (pathcount(mpp, PATH_UP) > 0 || + (pathcount(mpp, PATH_GHOST) > 0 && pp->tpgs != TPGS_IMPLICIT && +@@ -962,18 +969,6 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map) + pp->mpp = mpp; + rescan: + if (mpp) { +- 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); +- clear_ref_from_mpp(pp, vecs); +- free_path(pp); +- return 1; +- } +- + condlog(4,"%s: adopting all paths for path %s", + mpp->alias, pp->dev); + if (adopt_paths(vecs->pathvec, mpp)) +@@ -981,7 +976,6 @@ rescan: + + verify_paths(mpp, vecs); + mpp->action = ACT_RELOAD; +- extract_hwe_from_path(mpp); + } else { + if (!should_multipath(pp, vecs->pathvec, vecs->mpvec)) { + orphan_path(pp, "only one path"); +-- +2.19.1 + diff --git a/6014-fix-syntax-error.patch b/6014-fix-syntax-error.patch new file mode 100644 index 0000000..8a4f6d5 --- /dev/null +++ b/6014-fix-syntax-error.patch @@ -0,0 +1,25 @@ +From 8e4c5a421ee351fe667b0bf8b99e691ab5c9c13b Mon Sep 17 00:00:00 2001 +From: wangjufeng +Date: Fri, 1 Nov 2019 16:48:49 +0800 +Subject: [PATCH] fix syntax error + +--- + Makefile.inc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.inc b/Makefile.inc +index 5ff69a3..3744aa4 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -40,7 +40,7 @@ endif + + ifndef SYSTEMD + ifeq ($(shell systemctl --version > /dev/null 2>&1 && echo 1), 1) +- SYSTEMD = $(shell systemctl --version 2> /dev/null | sed -n 's/systemd \([0-9]*\)/\1/p') ++ SYSTEMD = $(shell systemctl --version 2> /dev/null | sed -n 's/systemd\([0-9]*\)/\1/p' | awk '{print $$1}') + endif + endif + +-- +2.19.1 + diff --git a/6020-multipathd-ignore-failed-wwid-recheck.patch b/6020-multipathd-ignore-failed-wwid-recheck.patch new file mode 100644 index 0000000..2cca42e --- /dev/null +++ b/6020-multipathd-ignore-failed-wwid-recheck.patch @@ -0,0 +1,74 @@ +author Benjamin Marzinski +Sat, 30 Mar 2019 14:05:56 +0800 (01:05 -0500) +committer Christophe Varoqui +Thu, 18 Apr 2019 19:03:34 +0800 (13:03 +0200) +commit 3ad48a0bc002f3d1b2a27eafecfd7fbb390bfb94 +multipathd: ignore failed wwid recheck + +If disable_changed_wwids is set, when multipathd gets a change event on +a path, it verifies that the wwid hasn't changed in uev_update_path(). +If get_uid() failed, uev_update_path treated this as a wwid change to 0. +This could cause paths to suddenly be dropped due to an issue with +getting the wwid. Even if get_uid() failed because the path was down, +it no change uevent happend when it later became active, multipathd +would continue to ignore the path. Also, scsi_uid_fallback() clears the +failure return if it doesn't attempt to fallback, causing get_uid() +to return success, when it actually failed. + +Multipathd should neither set nor clear wwid_changed if get_uid() +returned failure. Also, scsi_uid_fallback() should retain the old return +value if it doesn't attempt to fallback. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 6 +++--- + multipathd/main.c | 6 ++++-- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 1369f38..a852843 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1862,9 +1862,9 @@ get_vpd_uid(struct path * pp) + } + + static ssize_t scsi_uid_fallback(struct path *pp, int path_state, +- const char **origin) ++ const char **origin, ssize_t old_len) + { +- ssize_t len = 0; ++ ssize_t len = old_len; + int retrigger; + struct config *conf; + +@@ -1935,7 +1935,7 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev) + origin = "sysfs"; + } + if (len <= 0 && pp->bus == SYSFS_BUS_SCSI) +- len = scsi_uid_fallback(pp, path_state, &origin); ++ len = scsi_uid_fallback(pp, path_state, &origin, len); + } + if ( len < 0 ) { + condlog(1, "%s: failed to get %s uid: %s", +diff --git a/multipathd/main.c b/multipathd/main.c +index 872843c..49d1469 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1246,9 +1246,11 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + char wwid[WWID_SIZE]; + + strcpy(wwid, pp->wwid); +- get_uid(pp, pp->state, uev->udev); ++ rc = get_uid(pp, pp->state, uev->udev); + +- if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { ++ if (rc != 0) ++ strcpy(pp->wwid, wwid); ++ else if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { + condlog(0, "%s: path wwid changed from '%s' to '%s'. %s", + uev->kernel, wwid, pp->wwid, + (disable_changed_wwids ? "disallowing" : +-- +2.19.1 + + diff --git a/6021-libmultipath-group_by_prio-fix-signedness-bug.patch b/6021-libmultipath-group_by_prio-fix-signedness-bug.patch new file mode 100644 index 0000000..7248399 --- /dev/null +++ b/6021-libmultipath-group_by_prio-fix-signedness-bug.patch @@ -0,0 +1,30 @@ +From a358e60548ddb4631ed1b4ea404f71e1ea8f57e5 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Thu, 11 Apr 2019 12:49:20 +0200 +Subject: [PATCH 1/8] libmultipath: group_by_prio: fix signedness bug + +pp->priority can be negative, so we we shouldn't compare +it with an unsigned int. + +Signed-off-by: Martin Wilck +--- + libmultipath/pgpolicies.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c +index ac2596a..660768a 100644 +--- a/libmultipath/pgpolicies.c ++++ b/libmultipath/pgpolicies.c +@@ -312,7 +312,7 @@ out: + int group_by_prio(struct multipath *mp) + { + int i; +- unsigned int prio; ++ int prio; + struct path * pp; + struct pathgroup * pgp; + vector pathvec = NULL; +-- +1.8.3.1 + + diff --git a/6022-multipathd-handle-NULL-return-from-genhelp_handler.patch b/6022-multipathd-handle-NULL-return-from-genhelp_handler.patch new file mode 100644 index 0000000..e3ed6b6 --- /dev/null +++ b/6022-multipathd-handle-NULL-return-from-genhelp_handler.patch @@ -0,0 +1,44 @@ +From dc8b964a03a547eb8dc62b317f9f168a35943ebf Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 17 May 2019 11:14:10 -0500 +Subject: [PATCH 2/8] multipathd: handle NULL return from genhelp_handler + +parse_cmd() wasn't checking if genhelp_handler() returned NULL. It was simply +assuming that it got a string. On NULL, it now returns an error. Found by +Coverity. + +Signed-off-by: Benjamin Marzinski +--- + multipathd/cli.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/multipathd/cli.c b/multipathd/cli.c +index a75afe3..ff17a5b 100644 +--- a/multipathd/cli.c ++++ b/multipathd/cli.c +@@ -465,6 +465,8 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data, int timeout ) + + if (r) { + *reply = genhelp_handler(cmd, r); ++ if (*reply == NULL) ++ return EINVAL; + *len = strlen(*reply) + 1; + return 0; + } +@@ -472,9 +474,11 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data, int timeout ) + h = find_handler(fingerprint(cmdvec)); + + if (!h || !h->fn) { ++ free_keys(cmdvec); + *reply = genhelp_handler(cmd, EINVAL); ++ if (*reply == NULL) ++ return EINVAL; + *len = strlen(*reply) + 1; +- free_keys(cmdvec); + return 0; + } + +-- +1.8.3.1 + + diff --git a/6023-libmultipath-fix-parsing-of-VPD-83-type-1-T10-vendor.patch b/6023-libmultipath-fix-parsing-of-VPD-83-type-1-T10-vendor.patch new file mode 100644 index 0000000..9f53777 --- /dev/null +++ b/6023-libmultipath-fix-parsing-of-VPD-83-type-1-T10-vendor.patch @@ -0,0 +1,50 @@ +From 552bcf2f6245cbce4326455e28ab7c1160871978 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 24 Jun 2019 11:27:40 +0200 +Subject: [PATCH 3/8] libmultipath: fix parsing of VPD 83 type 1 (T10 vendor + ID) + +In the buffer overflow case, the code would set p_len = out_len - len - 2, +then len = len + plen = out_len - 2, and check if len >= out_len - 1, +which is never the case. Rather, set p_len = out_len - len -1, and +check the length again before appending the underscore. + +Fixes: 18176202e75c "Read wwid from sysfs vpg_pg83 attribute" +Signed-off-by: Martin Wilck +--- + libmultipath/discovery.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index a852843..9e99d9d 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1151,8 +1151,11 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + p = vpd; + while ((p = memchr(vpd, ' ', vpd_len))) { + p_len = p - vpd; +- if (len + p_len > out_len - 1) +- p_len = out_len - len - 2; ++ if (len + p_len > out_len - 1) { ++ condlog(1, "%s: WWID overflow, type 1, %d/%lu bytes required", ++ __func__, len + p_len, out_len); ++ p_len = out_len - len - 1; ++ } + memcpy(out + len, vpd, p_len); + len += p_len; + if (len >= out_len - 1) { +@@ -1161,6 +1164,10 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + } + out[len] = '_'; + len ++; ++ if (len >= out_len - 1) { ++ out[len] = '\0'; ++ break; ++ } + vpd = p; + vpd_len -= p_len; + while (vpd && *vpd == ' ') { +-- +1.8.3.1 + + diff --git a/6024-libmultipath-Fix-buffer-overflow-in-parse_vpd_pg80.patch b/6024-libmultipath-Fix-buffer-overflow-in-parse_vpd_pg80.patch new file mode 100644 index 0000000..627443f --- /dev/null +++ b/6024-libmultipath-Fix-buffer-overflow-in-parse_vpd_pg80.patch @@ -0,0 +1,31 @@ +From c00ee906582b87aeced4b2fb0caa011edb5cbc17 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 24 Jun 2019 11:27:41 +0200 +Subject: [PATCH 4/8] libmultipath: Fix buffer overflow in parse_vpd_pg80() + +We set out[len] = '\0' later, thus we should set len to no more then +out_len - 1. + +Fixes: 756ef73b7197 "Separate out vpd parsing functions" +Signed-off-by: Martin Wilck +--- + libmultipath/discovery.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 9e99d9d..416823b 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -999,7 +999,7 @@ parse_vpd_pg80(const unsigned char *in, char *out, size_t out_len) + if (len >= out_len) { + condlog(2, "vpd pg80 overflow, %d/%d bytes required", + len, (int)out_len); +- len = out_len; ++ len = out_len - 1; + } + if (len > 0) { + memcpy(out, in + 4, len); +-- +1.8.3.1 + + diff --git a/6025-libmultipath-fix-another-WWID-overflow-in-parse_vpd_.patch b/6025-libmultipath-fix-another-WWID-overflow-in-parse_vpd_.patch new file mode 100644 index 0000000..abeb26d --- /dev/null +++ b/6025-libmultipath-fix-another-WWID-overflow-in-parse_vpd_.patch @@ -0,0 +1,31 @@ +From f39a97d2972e3959985c2771f1fc53c45897acfb Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 24 Jun 2019 11:27:43 +0200 +Subject: [PATCH 5/8] libmultipath: fix another WWID overflow in + parse_vpd_pg83() + +This one is an obvious typo. + +Fixes: 18176202e75c "Read wwid from sysfs vpg_pg83 attribute" +Signed-off-by: Martin Wilck +--- + libmultipath/discovery.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 416823b..c57369c 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1136,7 +1136,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + len = 1; + vpd += 4; + vpd_len -= 4; +- if (vpd_len > out_len + 2) ++ if (vpd_len > out_len - 2) + vpd_len = out_len - 2; + memcpy(out, vpd, vpd_len); + len = vpd_len + 1; +-- +1.8.3.1 + + diff --git a/6026-libmultipath-fix-possible-WWID-overflow-in-parse_vpd.patch b/6026-libmultipath-fix-possible-WWID-overflow-in-parse_vpd.patch new file mode 100644 index 0000000..256de9a --- /dev/null +++ b/6026-libmultipath-fix-possible-WWID-overflow-in-parse_vpd.patch @@ -0,0 +1,66 @@ +From e8a63834f966cc605429c5b2ab3edc79a46c3bff Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 24 Jun 2019 11:27:42 +0200 +Subject: [PATCH 6/8] libmultipath: fix possible WWID overflow in + parse_vpd_pg83() + +We have to check the remaining length before printing to the +output buffer, not afterwards. + +Fixes: 18176202e75c "Read wwid from sysfs vpg_pg83 attribute" +Signed-off-by: Martin Wilck +--- + libmultipath/discovery.c | 16 +++------------- + 1 file changed, 3 insertions(+), 13 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index c57369c..34d425b 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1098,11 +1098,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + int i; + + len = sprintf(out, "%d", vpd_type); +- for (i = 0; i < vpd_len; i++) { ++ for (i = 0; i < vpd_len && len < out_len - 2; i++) { + len += sprintf(out + len, + "%02x", vpd[i]); +- if (len >= out_len) +- break; + } + } else if (vpd_type == 0x8) { + if (!memcmp("eui.", vpd, 4)) { +@@ -1110,27 +1108,19 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + len = 1; + vpd += 4; + vpd_len -= 4; +- for (i = 0; i < vpd_len; i++) { ++ for (i = 0; i < vpd_len && len < out_len - 1; i++) { + len += sprintf(out + len, "%c", + tolower(vpd[i])); +- if (len >= out_len) +- break; + } +- len = vpd_len + 1; +- out[len] = '\0'; + } else if (!memcmp("naa.", vpd, 4)) { + out[0] = '3'; + len = 1; + vpd += 4; + vpd_len -= 4; +- for (i = 0; i < vpd_len; i++) { ++ for (i = 0; i < vpd_len && len < out_len - 1; i++) { + len += sprintf(out + len, "%c", + tolower(vpd[i])); +- if (len >= out_len) +- break; + } +- len = vpd_len + 1; +- out[len] = '\0'; + } else { + out[0] = '8'; + len = 1; +-- +1.8.3.1 + + diff --git a/6027-libmultipath-fix-parsing-of-SCSI-name-string-iqn-for.patch b/6027-libmultipath-fix-parsing-of-SCSI-name-string-iqn-for.patch new file mode 100644 index 0000000..e2973af --- /dev/null +++ b/6027-libmultipath-fix-parsing-of-SCSI-name-string-iqn-for.patch @@ -0,0 +1,34 @@ +From 02748f3907fc95fbbf368ffda4ffb4bbf60f948d Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 24 Jun 2019 11:27:44 +0200 +Subject: [PATCH 7/8] libmultipath: fix parsing of SCSI name string, iqn format + +Do not overwrite the leading '8'. + +Signed-off-by: Martin Wilck +--- + libmultipath/discovery.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 34d425b..a4769ee 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1123,12 +1123,11 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len, + } + } else { + out[0] = '8'; +- len = 1; + vpd += 4; + vpd_len -= 4; + if (vpd_len > out_len - 2) + vpd_len = out_len - 2; +- memcpy(out, vpd, vpd_len); ++ memcpy(out + 1, vpd, vpd_len); + len = vpd_len + 1; + out[len] = '\0'; + } +-- +1.8.3.1 + + diff --git a/6028-libmultipath-fix-double-free-in-pgpolicyfn-error-pat.patch b/6028-libmultipath-fix-double-free-in-pgpolicyfn-error-pat.patch new file mode 100644 index 0000000..aa13194 --- /dev/null +++ b/6028-libmultipath-fix-double-free-in-pgpolicyfn-error-pat.patch @@ -0,0 +1,81 @@ +From 27039be7cfd551646425b0ebc43a87e86484c370 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 23 Aug 2019 12:48:50 -0500 +Subject: [PATCH 8/8] libmultipath: fix double free in pgpolicyfn error paths + +In the pgpolicy functions, if an error is encountered after +alloc_pathgroup() is called, but before the path group is added to a +multipath device with add_pathgroup(), the pathgroup needs to be cleaned +up by calling free_pathgroup(). However, after the pathgroup has been +added to the multipath device, calling free_pgvec() will clean it up. In +this case, if free_pathgroup() is called first, the recently added +pathgroup will be freed twice. + +Reviewed-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/pgpolicies.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c +index 660768a..9acf46a 100644 +--- a/libmultipath/pgpolicies.c ++++ b/libmultipath/pgpolicies.c +@@ -125,7 +125,7 @@ int group_by_node_name(struct multipath * mp) + + /* feed the first path */ + if (store_path(pgp->paths, pp)) +- goto out2; ++ goto out1; + + bitmap[i] = 1; + +@@ -139,7 +139,7 @@ int group_by_node_name(struct multipath * mp) + if (!strncmp(pp->tgt_node_name, pp2->tgt_node_name, + NODE_NAME_SIZE)) { + if (store_path(pgp->paths, pp2)) +- goto out2; ++ goto out1; + + bitmap[j] = 1; + } +@@ -201,7 +201,7 @@ int group_by_serial(struct multipath * mp) + + /* feed the first path */ + if (store_path(pgp->paths, pp)) +- goto out2; ++ goto out1; + + bitmap[i] = 1; + +@@ -214,7 +214,7 @@ int group_by_serial(struct multipath * mp) + + if (0 == strcmp(pp->serial, pp2->serial)) { + if (store_path(pgp->paths, pp2)) +- goto out2; ++ goto out1; + + bitmap[j] = 1; + } +@@ -258,7 +258,7 @@ int one_path_per_group(struct multipath *mp) + goto out1; + + if (store_path(pgp->paths, pp)) +- goto out1; ++ goto out; + } + sort_pathgroups(mp); + free_pathvec(mp->paths, KEEP_PATHS); +@@ -379,7 +379,7 @@ int group_by_prio(struct multipath *mp) + vector_foreach_slot(pathvec, pp, i) { + if (pp->priority == prio) { + if (store_path(pgp->paths, pp)) +- goto out2; ++ goto out1; + + vector_del_slot(pathvec, i); + i--; +-- +1.8.3.1 + + diff --git a/9000-fix-segfault-when-mount-or-umount-VIMS-with-reservation-conflict.patch b/9000-fix-segfault-when-mount-or-umount-VIMS-with-reservation-conflict.patch new file mode 100644 index 0000000..e144e9d --- /dev/null +++ b/9000-fix-segfault-when-mount-or-umount-VIMS-with-reservation-conflict.patch @@ -0,0 +1,17 @@ +diff -uNr a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +--- a/libmpathpersist/mpath_persist.c 2017-05-24 11:01:39.000000000 +0800 ++++ b/libmpathpersist/mpath_persist.c 2017-05-24 11:02:22.000000000 +0800 +@@ -510,10 +510,10 @@ + if (!rollback && (thread[i].param.status == MPATH_PR_RESERV_CONFLICT)){ + rollback = 1; + sa_key = 0; +- for (i = 0; i < 8; ++i){ +- if (i > 0) ++ for (j = 0; j < 8; ++j){ ++ if (j > 0) + sa_key <<= 8; +- sa_key |= paramp->sa_key[i]; ++ sa_key |= paramp->sa_key[j]; + } + status = MPATH_PR_RESERV_CONFLICT ; + } diff --git a/9001-fix-multipathd-resize-when-not-all-paths-size-are-equal.patch b/9001-fix-multipathd-resize-when-not-all-paths-size-are-equal.patch new file mode 100644 index 0000000..955eceb --- /dev/null +++ b/9001-fix-multipathd-resize-when-not-all-paths-size-are-equal.patch @@ -0,0 +1,37 @@ +--- multipath-tools-130222-patched/multipathd/cli_handlers.c 2017-10-12 19:19:08.000000000 +0800 ++++ multipath-tools-130222-patched1/multipathd/cli_handlers.c 2017-10-17 14:43:43.000000000 +0800 +@@ -593,9 +593,10 @@ + char * mapname = get_keyparam(v, MAP); + struct multipath *mpp; + int minor; +- unsigned long long size; ++ unsigned long long size, sz; + struct pathgroup *pgp; + struct path *pp; ++ int i,j; + + mapname = convert_dev(mapname, 0); + condlog(2, "%s: resize map (operator)", mapname); +@@ -627,6 +628,22 @@ + mapname); + return 1; + } ++ ++ vector_foreach_slot (mpp->pg, pgp, i) { ++ vector_foreach_slot (pgp->paths, pp, j) { ++ if (!pp->udev || sysfs_get_size(pp, &sz)) { ++ condlog(0, "%s: couldn't get size for sysfs. cannot resize", ++ mapname); ++ return 1; ++ } ++ if (size != sz) { ++ condlog(0, "%s: not all path sizes are equal, please check. cannot resize", ++ mapname); ++ return 1; ++ } ++ } ++ } ++ + if (size == mpp->size) { + condlog(0, "%s: map is still the same size (%llu)", mapname, + mpp->size); diff --git a/9002-multipathd-disable-queueing-for-recreated-map-in-uev.patch b/9002-multipathd-disable-queueing-for-recreated-map-in-uev.patch new file mode 100644 index 0000000..a2cba95 --- /dev/null +++ b/9002-multipathd-disable-queueing-for-recreated-map-in-uev.patch @@ -0,0 +1,55 @@ +From 4098378d2e976c9b371ae6bf83e802fb32187f50 Mon Sep 17 00:00:00 2001 +From: sunguoshuai +Date: Tue, 22 Jan 2019 21:29:56 -0500 +Subject: [PATCH] multipathd: disable queueing for recreated map in + uev_remove_map + +reason:disable queueing for recreated map in uev_remove_map +--- + multipathd/main.c | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index cc493c1..9dd74ad 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -647,7 +647,7 @@ uev_add_map (struct uevent * uev, struct vectors * vecs) + char *alias; + int major = -1, minor = -1, rc; + +- condlog(3, "%s: add map (uevent)", uev->kernel); ++ condlog(2, "%s: add map (uevent)", uev->kernel); + alias = uevent_get_dm_name(uev); + if (!alias) { + condlog(3, "%s: No DM_NAME in uevent", uev->kernel); +@@ -766,7 +766,26 @@ uev_remove_map (struct uevent * uev, struct vectors * vecs) + mpp->alias, mpp->dmi->minor, minor); + goto out; + } +- ++ /* ++ * There may be a race window here: ++ * 1. all paths gone, causing map flushed both from multipathd and kernel ++ * 2. paths regenerated, causing multipathd creating the map again. ++ * 1 will generate a remove uevent which can be handled after 2, ++ * so we can disable queueing for the map created by 2 here temporarily ++ * and let the change uevent (generated by 2) calling uev_add_map ++ * ->setup_multipath to set queueing again. This can prevent ++ * the deadlock in this race window. ++ * ++ * The possible deadlock is: all udevd workers hangs in ++ * devices because of queue_if_no_path, so no udevd workers ++ * can handle new event and since multipathd will remove the map, ++ * the checkerloop cannot check this map's retry tick timeout ++ * and cancel the io hang which makes the udevd worker hang forever. ++ * multipathd cannot receive any uevent from udevd because all ++ * udevd workers hang there so the map cannot be recreated ++ * again which makes a deadlock. ++ */ ++ dm_queue_if_no_path(alias, 0); + orphan_paths(vecs->pathvec, mpp); + remove_map_and_stop_waiter(mpp, vecs); + out: +-- +1.8.3.1 + diff --git a/9003-avoid-handling-paths-repeatedly-in-coalesce-paths.patch b/9003-avoid-handling-paths-repeatedly-in-coalesce-paths.patch new file mode 100644 index 0000000..d60f7d9 --- /dev/null +++ b/9003-avoid-handling-paths-repeatedly-in-coalesce-paths.patch @@ -0,0 +1,88 @@ +From 6c79d35c3d351323d18b63d76450fcfbb6ef5b56 Mon Sep 17 00:00:00 2001 +From: sunguoshuai +Date: Tue, 22 Jan 2019 22:00:35 -0500 +Subject: [PATCH] Module: fix lun expansion failure when there is offline path + +reason:fix lun expansion failure when there is offline path +--- + libmultipath/configure.c | 11 +++++++++++ + libmultipath/structs.c | 1 + + libmultipath/structs.h | 1 + + libmultipath/structs_vec.c | 1 + + 4 files changed, 14 insertions(+) + +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 09c3dcf..1b1cc55 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -1021,6 +1021,7 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + } + vector_foreach_slot (pathvec, pp1, k) { + int invalid = 0; ++ condlog(3, "%s %s: start coalesce", pp1->dev, pp1->dev_t); + /* skip this path for some reason */ + + /* 1. if path has no unique id or wwid blacklisted */ +@@ -1053,6 +1054,12 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + orphan_path(pp1, "only one path"); + continue; + } ++ /* if path is handled before */ ++ if (pp1->handled) { ++ condlog(3, "%s: skip handled path.", pp1->dev_t); ++ continue; ++ } ++ + + /* + * at this point, we know we really got a new mp +@@ -1071,6 +1078,10 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + + for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) { + pp2 = VECTOR_SLOT(pathvec, i); ++ if (pp2->handled) ++ continue; ++ ++ + + if (strcmp(pp1->wwid, pp2->wwid)) + continue; +diff --git a/libmultipath/structs.c b/libmultipath/structs.c +index ae847d6..99435c1 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -100,6 +100,7 @@ alloc_path (void) + pp->fd = -1; + pp->tpgs = TPGS_UNDEF; + pp->priority = PRIO_UNDEF; ++ pp->handled = 0; + checker_clear(&pp->checker); + dm_path_to_gen(pp)->ops = &dm_gen_path_ops; + pp->hwe = vector_alloc(); +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index 0a2623a..d667cb7 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -277,6 +277,7 @@ struct path { + struct checker checker; + struct multipath * mpp; + int fd; ++ int handled; + int initialized; + int retriggers; + int wwid_changed; +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index f87d69d..fba38c0 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -388,6 +388,7 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs) + return 0; + + vector_foreach_slot (mpp->paths, pp, i) { ++ pp->handled = 1; + /* + * see if path is in sysfs + */ +-- +1.8.3.1 + diff --git a/9004-fix-bugs-backported-from-next-branch.patch b/9004-fix-bugs-backported-from-next-branch.patch new file mode 100644 index 0000000..dda642b --- /dev/null +++ b/9004-fix-bugs-backported-from-next-branch.patch @@ -0,0 +1,154 @@ +From a9b5625e0dba3b76832b17c6fbb34840f1a91653 Mon Sep 17 00:00:00 2001 +From: sunguoshuai +Date: Wed, 23 Jan 2019 01:57:33 -0500 +Subject: [PATCH] fix bugs backported from next branch + +reason:fix bugs backported from next branch +--- + libmultipath/prioritizers/alua.c | 4 ++++ + libmultipath/prioritizers/emc.c | 2 +- + libmultipath/prioritizers/hds.c | 20 ++++++++++++-------- + libmultipath/structs_vec.c | 4 +++- + multipathd/main.c | 5 +++++ + 5 files changed, 25 insertions(+), 10 deletions(-) + +diff --git a/libmultipath/prioritizers/alua.c b/libmultipath/prioritizers/alua.c +index 03d0a0e..1400b11 100644 +--- a/libmultipath/prioritizers/alua.c ++++ b/libmultipath/prioritizers/alua.c +@@ -128,15 +128,19 @@ int getprio (struct path * pp, char * args, unsigned int timeout) + switch(-rc) { + case ALUA_PRIO_NOT_SUPPORTED: + condlog(0, "%s: alua not supported", pp->dev); ++ rc = 0; + break; + case ALUA_PRIO_RTPG_FAILED: + condlog(0, "%s: couldn't get target port group", pp->dev); ++ rc = 0; + break; + case ALUA_PRIO_GETAAS_FAILED: + condlog(0, "%s: couldn't get asymmetric access state", pp->dev); ++ rc = 0; + break; + case ALUA_PRIO_TPGS_FAILED: + condlog(3, "%s: couldn't get supported alua states", pp->dev); ++ rc = 0; + break; + } + } +diff --git a/libmultipath/prioritizers/emc.c b/libmultipath/prioritizers/emc.c +index a2f7487..c5382e0 100644 +--- a/libmultipath/prioritizers/emc.c ++++ b/libmultipath/prioritizers/emc.c +@@ -19,7 +19,7 @@ int emc_clariion_prio(const char *dev, int fd, unsigned int timeout) + unsigned char inqCmdBlk[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xC0, 0, + sizeof(sense_buffer), 0}; + struct sg_io_hdr io_hdr; +- int ret = PRIO_UNDEF; ++ int ret = 0; + + memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); + memset(&sense_buffer, 0, 128); +diff --git a/libmultipath/prioritizers/hds.c b/libmultipath/prioritizers/hds.c +index 70fb5d1..56d182b 100644 +--- a/libmultipath/prioritizers/hds.c ++++ b/libmultipath/prioritizers/hds.c +@@ -98,10 +98,12 @@ int hds_modular_prio (const char *dev, int fd, unsigned int timeout) + unsigned char *inqBuffp = inqBuff; + unsigned char sense_buffer[32]; + sg_io_hdr_t io_hdr; ++ int ret = 0; + + if ((ioctl (fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) { + pp_hds_log(0, "can't use SG ioctl interface"); +- return -1; ++ goto out; ++ + } + + memset (&io_hdr, 0, sizeof (sg_io_hdr_t)); +@@ -118,11 +120,11 @@ int hds_modular_prio (const char *dev, int fd, unsigned int timeout) + + if (ioctl (fd, SG_IO, &io_hdr) < 0) { + pp_hds_log(0, "SG_IO error"); +- return -1; ++ goto out; + } + if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) { + pp_hds_log(0, "SCSI error"); +- return -1; ++ goto out; + } + + snprintf (vendor, 9, "%.8s", inqBuffp + 8); +@@ -144,11 +146,11 @@ int hds_modular_prio (const char *dev, int fd, unsigned int timeout) + switch (ldev[3]) { + case '0': case '2': case '4': case '6': case '8': case 'A': case 'C': case 'E': + pp_hds_log(4, "CTRL EVEN, LDEV EVEN, PRIO 1"); +- return 1; ++ ret = 1; + break; + case '1': case '3': case '5': case '7': case '9': case 'B': case 'D': case 'F': + pp_hds_log(4, "CTRL EVEN, LDEV ODD, PRIO 0"); +- return 0; ++ ret = 0; + break; + } + break; +@@ -156,16 +158,18 @@ int hds_modular_prio (const char *dev, int fd, unsigned int timeout) + switch (ldev[3]) { + case '0': case '2': case '4': case '6': case '8': case 'A': case 'C': case 'E': + pp_hds_log(4, "CTRL ODD, LDEV EVEN, PRIO 0"); +- return 0; ++ ret = 0; + break; + case '1': case '3': case '5': case '7': case '9': case 'B': case 'D': case 'F': + pp_hds_log(4, "CTRL ODD, LDEV ODD, PRIO 1"); +- return 1; ++ ret = 1; + break; + } + break; + } +- return -1; ++ ++out: ++ return ret; + } + + int getprio (struct path * pp, char * args, unsigned int timeout) +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index fba38c0..d85eb5f 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -32,8 +32,10 @@ int update_mpp_paths(struct multipath *mpp, vector pathvec) + return 0; + + if (!mpp->paths && +- !(mpp->paths = vector_alloc())) ++ !(mpp->paths = vector_alloc())) { ++ condlog(2, "mpp->paths alloc failed"); + return 1; ++ } + + vector_foreach_slot (mpp->pg, pgp, i) { + vector_foreach_slot (pgp->paths, pp, j) { +diff --git a/multipathd/main.c b/multipathd/main.c +index 9dd74ad..7a80688 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1624,6 +1624,11 @@ enable_group(struct path * pp) + + pgp = VECTOR_SLOT(pp->mpp->pg, pp->pgindex - 1); + ++ if (!pgp) { ++ condlog(2, "%s: pgp is NULL", pp->mpp->alias); ++ return; ++ } ++ + if (pgp->status == PGSTATE_DISABLED) { + condlog(2, "%s: enable group #%i", pp->mpp->alias, pp->pgindex); + dm_enablegroup(pp->mpp->alias, pp->pgindex); +-- +2.19.1 + diff --git a/9005-bugfix-fix-change-reservation-key-to-uint8-for-memcmp.patch b/9005-bugfix-fix-change-reservation-key-to-uint8-for-memcmp.patch new file mode 100644 index 0000000..af0ac0e --- /dev/null +++ b/9005-bugfix-fix-change-reservation-key-to-uint8-for-memcmp.patch @@ -0,0 +1,46 @@ +From aa3dbb9a4c7ba220139801533a27d99542d4e909 Mon Sep 17 00:00:00 2001 +From: sunguoshuai +Date: Wed, 23 Jan 2019 02:21:31 -0500 +Subject: [PATCH] fix change reservation key to uint8 for + memcmp + +reason:fix change reservation key to uint8 for memcmp +--- + libmpathpersist/mpath_persist.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index 691b4e1..a2907db 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -263,6 +263,9 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + int ret; + uint64_t prkey; + struct config *conf; ++ uint8_t uitmp[8] = {0}; ++ uint64_t uireservation = {0}; ++ int j; + + conf = get_multipath_config(); + conf->verbosity = verbose; +@@ -353,8 +356,15 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + } + } + +- if (memcmp(paramp->key, &mpp->reservation_key, 8) && +- memcmp(paramp->sa_key, &mpp->reservation_key, 8)) { ++ uireservation = get_be64(mpp->reservation_key); ++ for (j = 7; j >= 0; --j) { ++ uitmp[j] = (uireservation & 0xff); ++ uireservation >>= 8; ++ } ++ ++ if (memcmp(paramp->key, uitmp, 8) && ++ memcmp(paramp->sa_key, uitmp, 8)) { ++ + condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key)); + ret = MPATH_PR_SYNTAX_ERROR; + goto out1; +-- +1.8.3.1 + diff --git a/9006-bugfix-ignore-for-clear-mismatch-key.patch b/9006-bugfix-ignore-for-clear-mismatch-key.patch new file mode 100644 index 0000000..b76e188 --- /dev/null +++ b/9006-bugfix-ignore-for-clear-mismatch-key.patch @@ -0,0 +1,49 @@ +From de2078dd66a62ca7ba2ae6adc406311e830572fa Mon Sep 17 00:00:00 2001 +From: sunguoshuai +Date: Wed, 23 Jan 2019 02:38:00 -0500 +Subject: [PATCH] ignore for clear mismatch key + +reason:ignore for clear mismatch key +--- + libmpathpersist/mpath_persist.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index a2907db..27c848c 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -345,7 +345,8 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey && + ((!get_be64(mpp->reservation_key) && + rq_servact == MPATH_PROUT_REG_SA) || +- rq_servact == MPATH_PROUT_REG_IGN_SA)) { ++ rq_servact == MPATH_PROUT_REG_IGN_SA || ++ (!memcmp(paramp->key, &mpp->reservation_key, 8) && rq_servact == MPATH_PROUT_REG_SA))) { + memcpy(&mpp->reservation_key, paramp->sa_key, 8); + if (update_prkey_flags(alias, get_be64(mpp->reservation_key), + paramp->sa_flags)) { +@@ -362,12 +363,16 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + uireservation >>= 8; + } + +- if (memcmp(paramp->key, uitmp, 8) && +- memcmp(paramp->sa_key, uitmp, 8)) { ++ /* pass -I option */ ++ if (rq_servact != MPATH_PROUT_REG_IGN_SA) { ++ if (memcmp(paramp->key, uitmp, 8) && ++ memcmp(paramp->sa_key, uitmp, 8)) { ++ condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key)); ++ ret = MPATH_PR_SYNTAX_ERROR; ++ goto out1; ++ } ++ + +- condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key)); +- ret = MPATH_PR_SYNTAX_ERROR; +- goto out1; + } + + switch(rq_servact) +-- +1.8.3.1 + diff --git a/9007-bugfix-flush-and-sync-before-reboot.patch b/9007-bugfix-flush-and-sync-before-reboot.patch new file mode 100644 index 0000000..dd41184 --- /dev/null +++ b/9007-bugfix-flush-and-sync-before-reboot.patch @@ -0,0 +1,17 @@ +diff --git a/libmultipath/util.c b/libmultipath/util.c +index 8d8fcc8..3c284b7 100644 +--- a/libmultipath/util.c ++++ b/libmultipath/util.c +@@ -463,5 +463,12 @@ int safe_write(int fd, const void *buf, size_t count) + count -= r; + buf = (const char *)buf + r; + } ++ ++ /* sync->disk */ ++ if (fsync(fd) < 0) { ++ condlog(0, "failed to fsync fd :%d", fd); ++ return -errno; ++ } ++ + return 0; + } diff --git a/9008-bugfix-RH-remove-local-disk-from-pathvec.patch b/9008-bugfix-RH-remove-local-disk-from-pathvec.patch new file mode 100644 index 0000000..3aa00c4 --- /dev/null +++ b/9008-bugfix-RH-remove-local-disk-from-pathvec.patch @@ -0,0 +1,206 @@ +From f637f15dacc660f663a6cf36e3fe8f7a0cc9f9e4 Mon Sep 17 00:00:00 2001 +From: chenminhua +Date: Mon, 2 Apr 2018 04:01:04 -0400 +Subject: [PATCH] 1hostos-patch-upgrade:0330 hotpatch modify + +[Changelog]:add upgrade path +[Author]:chenminhua + +--- + libmultipath/discovery.c | 129 +++++++++++++++++++++++++++++++++++++-- + libmultipath/discovery.h | 1 + + multipathd/main.c | 4 ++ + 3 files changed, 128 insertions(+), 6 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 0b1855d..95eb3a0 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -34,6 +34,103 @@ + #include "prioritizers/alua_rtpg.h" + #include "foreign.h" + ++const char *conf_file = "/etc/multipath_private.conf"; ++static int conf_file_parsed = 0; ++static int should_remove_local_disk = 0; ++ ++static void parse_config() ++{ ++ FILE *fp = NULL; ++ char buffer[256] = {0}; ++ char *str = NULL; ++ char *p = NULL; ++ ++ fp = fopen(conf_file, "r"); ++ if (fp) { ++ while (fgets(buffer, sizeof(buffer), fp)) { ++ str = buffer; ++ /* skip the space */ ++ while (isspace(*str)) ++ str++; ++ /* skip the comment line */ ++ if (strncmp(str, "#", 1) == 0) ++ continue; ++ /* skip line feed */ ++ if((p = strchr(str, '\n')) != NULL) ++ *p = '\0'; ++ if (strstr(str, "remove_local_disk") != NULL && (p = strstr(str, "=")) != NULL){ ++ str = p + 1; ++ /* skip the space */ ++ while (isspace(*str)) ++ str++; ++ if (strcmp(str, "1") == 0){ ++ should_remove_local_disk = 1; ++ } ++ break; ++ } ++ } ++ fclose(fp); ++ fp = NULL; ++ } ++ conf_file_parsed = 1; ++} ++ ++static int get_should_remove_local_disk() ++{ ++ if (!conf_file_parsed) ++ parse_config(); ++ return should_remove_local_disk; ++} ++ ++/* Filter the local disks and remove them from pathvec */ ++static int ++transport (int h) ++{ ++ char buff[PATH_SIZE]; ++ int len, off; ++ struct stat a_stat; ++ ++ /* FC host */ ++ strcpy(buff, "/sys"); ++ strcat(buff, "/class/fc_host/"); ++ len = strlen(buff); ++ snprintf(buff + len, PATH_SIZE - len, "host%d", h); ++ if ((stat(buff, &a_stat) >= 0) && S_ISDIR(a_stat.st_mode)) { ++ return 0; ++ } ++ memset(buff, 0, PATH_SIZE); ++ ++ /* iSCSI device */ ++ strcpy(buff, "/sys"); ++ strcat(buff, "/class/iscsi_host/"); ++ off = strlen(buff); ++ snprintf(buff + off, PATH_SIZE - off, "host%d", h); ++ if ((stat(buff, &a_stat) >= 0) && S_ISDIR(a_stat.st_mode)) { ++ return 0; ++ } ++ return 1; ++} ++ ++int ++remove_local_path (vector pathvec, struct path *pp) ++{ ++ int i = -1; ++ ++ if(!get_should_remove_local_disk()){ ++ return 1; ++ } ++ ++ if (transport(pp->sg_id.host_no) == 0) { ++ return 1; ++ } ++ ++ if ((i = find_slot(pathvec, (void *)pp)) != -1) { ++ vector_del_slot(pathvec, i); ++ } ++ free_path(pp); ++ return 0; ++} ++ + int + alloc_path_with_pathinfo (struct config *conf, struct udev_device *udevice, + const char *wwid, int flag, struct path **pp_ptr) +@@ -118,6 +215,7 @@ path_discover (vector pathvec, struct config * conf, + { + struct path * pp; + const char * devname; ++ int err = 1; + + devname = udev_device_get_sysname(udevice); + if (!devname) +@@ -131,11 +229,22 @@ path_discover (vector pathvec, struct config * conf, + snprintf(devt, BLK_DEV_SIZE, "%d:%d", + major(devnum), minor(devnum)); + pp = find_path_by_devt(pathvec, devt); +- if (!pp) +- return store_pathinfo(pathvec, conf, +- udevice, flag, NULL); ++ if (!pp) { ++ err = store_pathinfo(pathvec, conf, ++ udevice, flag, &pp); ++ if (err == 1) ++ return 1; ++ if (err == 0) ++ remove_local_path(pathvec, pp); ++ return 0; ++ } + } +- return pathinfo(pp, conf, flag); ++ err = pathinfo(pp, conf, flag); ++ if (err) ++ return err; ++ ++ remove_local_path(pathvec, pp); ++ return err; + } + + int +@@ -1882,8 +1991,16 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + /* + * fetch info available in sysfs + */ +- if (mask & DI_SYSFS && sysfs_pathinfo(pp, conf->hwtable)) +- return PATHINFO_FAILED; ++ if (mask & DI_SYSFS) { ++ if (sysfs_pathinfo(pp, conf->hwtable)) ++ return 1; ++ ++ /* free local device */ ++ if (transport(pp->sg_id.host_no)) { ++ condlog(3, "%s is a local device", pp->dev); ++ return 0; ++ } ++ } + + if (mask & DI_BLACKLIST && mask & DI_SYSFS) { + if (filter_device(conf->blist_device, conf->elist_device, +diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h +index 9aacf75..c4b1d25 100644 +--- a/libmultipath/discovery.h ++++ b/libmultipath/discovery.h +@@ -53,6 +53,7 @@ ssize_t sysfs_get_vpd (struct udev_device * udev, int pg, unsigned char * buff, + int sysfs_get_asymmetric_access_state(struct path *pp, + char *buff, int buflen); + int get_uid(struct path * pp, int path_state, struct udev_device *udev); ++int remove_local_path(vector pathvec, struct path *pp); + + /* + * discovery bitmask +diff --git a/multipathd/main.c b/multipathd/main.c +index 7a80688..c2757c4 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -917,6 +917,10 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map) + int start_waiter = 0; + int ret; + ++ /* if pp is local path,remove it and return 0. */ ++ if (!remove_local_path(vecs->pathvec, pp)) ++ return 0; ++ + /* + * need path UID to go any further + */ +-- +2.19.1 + diff --git a/9009-bugfix-lun-expansion-failure-when-there-is-offline-path.patch b/9009-bugfix-lun-expansion-failure-when-there-is-offline-path.patch new file mode 100644 index 0000000..8586f3d --- /dev/null +++ b/9009-bugfix-lun-expansion-failure-when-there-is-offline-path.patch @@ -0,0 +1,54 @@ +diff --git a/libmultipath/configure.c b/libmultipath/configure.c +index 1b1cc55..f66bd5b 100644 +--- a/libmultipath/configure.c ++++ b/libmultipath/configure.c +@@ -1054,11 +1054,18 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + orphan_path(pp1, "only one path"); + continue; + } +- /* if path is handled before */ +- if (pp1->handled) { +- condlog(3, "%s: skip handled path.", pp1->dev_t); +- continue; +- } ++ ++ /* if path is offline */ ++ if (pp1->state == PATH_DOWN) { ++ orphan_path(pp1, "skip offline path"); ++ continue; ++ } ++ ++ /* if path is handled before */ ++ if (pp1->handled) { ++ condlog(3, "%s: skip handled path.", pp1->dev_t); ++ continue; ++ } + + + /* +@@ -1086,6 +1093,9 @@ int coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, + if (strcmp(pp1->wwid, pp2->wwid)) + continue; + ++ if (!pp2->size || pp2->state == PATH_DOWN) ++ continue; ++ + if (!mpp->size && pp2->size) + mpp->size = pp2->size; + +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index d85eb5f..6c42824 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -394,8 +394,9 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs) + /* + * see if path is in sysfs + */ +- if (sysfs_attr_get_value(pp->udev, "dev", +- pp->dev_t, BLK_DEV_SIZE) < 0) { ++ if ((sysfs_attr_get_value(pp->udev, "dev", ++ pp->dev_t, BLK_DEV_SIZE) < 0) || ++ (pp->state == PATH_DOWN && pp->size != mpp->size)) { + if (pp->state != PATH_DOWN) { + condlog(1, "%s: removing valid path %s in state %d", + mpp->alias, pp->dev, pp->state); diff --git a/9010-bugfix-some-memory-leaks-issues-in-libmpathpersist.patch b/9010-bugfix-some-memory-leaks-issues-in-libmpathpersist.patch new file mode 100644 index 0000000..1b61be2 --- /dev/null +++ b/9010-bugfix-some-memory-leaks-issues-in-libmpathpersist.patch @@ -0,0 +1,162 @@ +diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c +index 27c848c..1e6a172 100644 +--- a/libmpathpersist/mpath_persist.c ++++ b/libmpathpersist/mpath_persist.c +@@ -199,6 +199,11 @@ int mpath_persistent_reserve_in (int fd, int rq_servact, + if (map_present && !dm_is_mpath(alias)){ + condlog( 0, "%s: not a multipath device.", alias); + ret = MPATH_PR_DMMP_ERROR; ++ if (curmp) ++ vector_free(curmp); ++ if (pathvec) ++ vector_free(pathvec); ++ + goto out; + } + +@@ -297,6 +302,10 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + if (map_present && !dm_is_mpath(alias)){ + condlog(3, "%s: not a multipath device.", alias); + ret = MPATH_PR_DMMP_ERROR; ++ if (curmp) ++ vector_free(curmp); ++ if (pathvec) ++ vector_free(pathvec); + goto out; + } + +@@ -321,7 +330,7 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, + goto out1; + } + +- /* get info of all paths from the dm device */ ++ /* get info of all paths from the dm device */ + if (get_mpvec(curmp, pathvec, alias)){ + condlog(0, "%s: failed to get device info.", alias); + ret = MPATH_PR_DMMP_ERROR; +@@ -882,7 +891,7 @@ out: + return (status); + } + +-void * mpath_alloc_prin_response(int prin_sa) ++void *mpath_alloc_prin_response(int prin_sa) + { + void * ptr = NULL; + int size=0; +@@ -905,6 +914,10 @@ void * mpath_alloc_prin_response(int prin_sa) + if (size > 0) + { + ptr = calloc(size, 1); ++ if (!ptr) { ++ condlog (0, "failed to allocate MPATH_PRIN_RFSTAT_SA buffer"); ++ return NULL; ++ } + } + return ptr; + } +diff --git a/libmpathpersist/mpath_pr_ioctl.c b/libmpathpersist/mpath_pr_ioctl.c +index 6dd7403..b317b4e 100644 +--- a/libmpathpersist/mpath_pr_ioctl.c ++++ b/libmpathpersist/mpath_pr_ioctl.c +@@ -25,8 +25,8 @@ + int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp *resp, int noisy); + void mpath_format_readkeys(struct prin_resp *pr_buff, int len , int noisy); + void mpath_format_readfullstatus(struct prin_resp *pr_buff, int len, int noisy); +-int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr, +- SenseData_t *Sensedata, int noisy); ++int mpath_translate_response (const char *dev, struct sg_io_hdr *io_hdr, ++ const SenseData_t *Sensedata, int noisy); + void dumpHex(const char* str, int len, int no_ascii); + int prout_do_scsi_ioctl( char * dev, int rq_servact, int rq_scope, + unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy); +@@ -115,7 +115,7 @@ retry : + + condlog(4, "%s: Duration=%u (ms)", dev, io_hdr.duration); + +- status = mpath_translate_response(dev, io_hdr, &Sensedata, noisy); ++ status = mpath_translate_response(dev, &io_hdr, &Sensedata, noisy); + condlog(3, "%s: status = %d", dev, status); + + if (status == MPATH_PR_SENSE_UNIT_ATTENTION && (retry > 0)) +@@ -354,7 +354,7 @@ retry : + condlog(3, "%s: duration = %u (ms)", dev, io_hdr.duration); + condlog(4, "%s: persistent reservation in: requested %d bytes but got %d bytes)", dev, mx_resp_len, got); + +- status = mpath_translate_response(dev, io_hdr, &Sensedata, noisy); ++ status = mpath_translate_response(dev, &io_hdr, &Sensedata, noisy); + + if (status == MPATH_PR_SENSE_UNIT_ATTENTION && (retry > 0)) + { +@@ -399,18 +399,18 @@ out: + return status; + } + +-int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr, +- SenseData_t *Sensedata, int noisy) ++int mpath_translate_response (const char *dev, struct sg_io_hdr *io_hdr, ++ const SenseData_t *Sensedata, int noisy) + { + condlog(3, "%s: status driver:%02x host:%02x scsi:%02x", dev, +- io_hdr.driver_status, io_hdr.host_status ,io_hdr.status); +- io_hdr.status &= 0x7e; +- if ((0 == io_hdr.status) && +- (0 == io_hdr.host_status) && +- (0 == io_hdr.driver_status)) ++ io_hdr->driver_status, io_hdr->host_status ,io_hdr->status); ++ io_hdr->status &= 0x7e; ++ if ((0 == io_hdr->status) && ++ (0 == io_hdr->host_status) && ++ (0 == io_hdr->driver_status)) + return MPATH_PR_SUCCESS; + +- switch(io_hdr.status) { ++ switch(io_hdr->status) { + case SAM_STAT_GOOD: + break; + case SAM_STAT_CHECK_CONDITION: +@@ -450,13 +450,13 @@ int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr, + return MPATH_PR_OTHER; + } + +- switch(io_hdr.host_status) { ++ switch(io_hdr->host_status) { + case DID_OK : + break; + default : + return MPATH_PR_OTHER; + } +- switch(io_hdr.driver_status) ++ switch(io_hdr->driver_status) + { + case DRIVER_OK: + break; +diff --git a/mpathpersist/main.c b/mpathpersist/main.c +index 0e4d3f2..4db07b2 100644 +--- a/mpathpersist/main.c ++++ b/mpathpersist/main.c +@@ -61,7 +61,7 @@ struct udev *udev; + + int main (int argc, char * argv[]) + { +- int fd, c, res; ++ int c, res, fd = -1; + const char *device_name = NULL; + int num_prin_sa = 0; + int num_prout_sa = 0; +@@ -488,6 +488,7 @@ int main (int argc, char * argv[]) + } + + res = close (fd); ++ fd = -1; + if (res < 0) + { + mpath_lib_exit(conf); +@@ -496,6 +497,8 @@ int main (int argc, char * argv[]) + } + + out : ++ if (fd >= 0) ++ close(fd); + mpath_lib_exit(conf); + udev_unref(udev); + return (ret >= 0) ? ret : MPATH_PR_OTHER; diff --git a/9011-bugfix-change-log-level-to-info-if-alua-is-not-support-by-s.patch b/9011-bugfix-change-log-level-to-info-if-alua-is-not-support-by-s.patch new file mode 100644 index 0000000..6a0944a --- /dev/null +++ b/9011-bugfix-change-log-level-to-info-if-alua-is-not-support-by-s.patch @@ -0,0 +1,26 @@ +From 0008a2343765ab689cfc66acd8fc84630611d796 Mon Sep 17 00:00:00 2001 +From: root +Date: Fri, 22 Mar 2019 19:37:43 +0800 +Subject: [PATCH 1/5] change log level to info if alua is not support by + storage server + +--- + libmultipath/prioritizers/alua.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/prioritizers/alua.c b/libmultipath/prioritizers/alua.c +index 1400b11..6b69982 100644 +--- a/libmultipath/prioritizers/alua.c ++++ b/libmultipath/prioritizers/alua.c +@@ -127,7 +127,7 @@ int getprio (struct path * pp, char * args, unsigned int timeout) + } else { + switch(-rc) { + case ALUA_PRIO_NOT_SUPPORTED: +- condlog(0, "%s: alua not supported", pp->dev); ++ condlog(3, "%s: alua not supported", pp->dev); + rc = 0; + break; + case ALUA_PRIO_RTPG_FAILED: +-- +2.19.1 + diff --git a/9012-bugfix-clear-mpp-path-reference-when-path-is-freed-otherwis.patch b/9012-bugfix-clear-mpp-path-reference-when-path-is-freed-otherwis.patch new file mode 100644 index 0000000..3de1359 --- /dev/null +++ b/9012-bugfix-clear-mpp-path-reference-when-path-is-freed-otherwis.patch @@ -0,0 +1,139 @@ +From 2c3047d7f6bd8cdd1d92cab32893cecdd5a1dfa9 Mon Sep 17 00:00:00 2001 +From: root +Date: Fri, 22 Mar 2019 19:48:35 +0800 +Subject: [PATCH] clear mpp path reference when path is freed, otherwise double + free may occur in verify_paths. + +call stack: + vecs=vecs@entry=0x557b01d62140, rpvec=rpvec@entry=0x0) at structs_vec.c:521 + at main.c:574 + uev=) at main.c:510 + uev_trigger=uev_trigger@entry=0x557affdfe3d0 , trigger_data=) + at uevent.c:178 +--- + libmultipath/discovery.c | 10 ++++++---- + libmultipath/discovery.h | 2 +- + multipathd/main.c | 23 ++++++++++++++++++++++- + 3 files changed, 29 insertions(+), 6 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 53fc67a..305d27c 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -112,7 +112,7 @@ transport (int h) + } + + int +-remove_local_path (vector pathvec, struct path *pp) ++remove_local_path (vector pathvec, struct path *pp, int isfree) + { + int i = -1; + +@@ -127,7 +127,9 @@ remove_local_path (vector pathvec, struct path *pp) + if ((i = find_slot(pathvec, (void *)pp)) != -1) { + vector_del_slot(pathvec, i); + } +- free_path(pp); ++ if(isfree){ ++ free_path(pp); ++ } + return 0; + } + +@@ -235,7 +237,7 @@ path_discover (vector pathvec, struct config * conf, + if (err == 1) + return 1; + if (err == 0) +- remove_local_path(pathvec, pp); ++ remove_local_path(pathvec, pp, 1); + return 0; + } + } +@@ -243,7 +245,7 @@ path_discover (vector pathvec, struct config * conf, + if (err) + return err; + +- remove_local_path(pathvec, pp); ++ remove_local_path(pathvec, pp, 1); + return err; + } + +diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h +index c4b1d25..0fb0d3a 100644 +--- a/libmultipath/discovery.h ++++ b/libmultipath/discovery.h +@@ -53,7 +53,7 @@ ssize_t sysfs_get_vpd (struct udev_device * udev, int pg, unsigned char * buff, + int sysfs_get_asymmetric_access_state(struct path *pp, + char *buff, int buflen); + int get_uid(struct path * pp, int path_state, struct udev_device *udev); +-int remove_local_path(vector pathvec, struct path *pp); ++int remove_local_path(vector pathvec, struct path *pp, int isfree); + + /* + * discovery bitmask +diff --git a/multipathd/main.c b/multipathd/main.c +index b180f2a..8de0871 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -815,6 +815,21 @@ ev_remove_map (char * devname, char * alias, int minor, struct vectors * vecs) + return flush_map(mpp, vecs, 0); + } + ++static ++void clear_ref_from_mpp(struct path * pp, struct vectors * vecs) ++{ ++ struct multipath * mpp = NULL; ++ int i = -1; ++ ++ mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); ++ if(!!mpp){ ++ condlog(2, "%s: clear path from mpp %s", pp->dev, mpp->alias); ++ if ((i = find_slot(mpp->paths, (void *)pp)) != -1){ ++ vector_del_slot(mpp->paths, i); ++ } ++ } ++} ++ + static int + uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map) + { +@@ -857,6 +872,7 @@ uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map) + i = find_slot(vecs->pathvec, (void *)pp); + if (i != -1) + vector_del_slot(vecs->pathvec, i); ++ clear_ref_from_mpp(pp, vecs); + free_path(pp); + } else { + condlog(0, "%s: failed to reinitialize path", +@@ -918,8 +934,11 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map) + int ret; + + /* if pp is local path,remove it and return 0. */ +- if (!remove_local_path(vecs->pathvec, pp)) ++ if (!remove_local_path(vecs->pathvec, pp, 0)){ ++ clear_ref_from_mpp(pp, vecs); ++ free_path(pp); + return 0; ++ } + + /* + * need path UID to go any further +@@ -950,6 +969,7 @@ rescan: + int i = find_slot(vecs->pathvec, (void *)pp); + if (i != -1) + vector_del_slot(vecs->pathvec, i); ++ clear_ref_from_mpp(pp, vecs); + free_path(pp); + return 1; + } +@@ -1182,6 +1202,7 @@ out: + if ((i = find_slot(vecs->pathvec, (void *)pp)) != -1) + vector_del_slot(vecs->pathvec, i); + ++ clear_ref_from_mpp(pp, vecs); + free_path(pp); + + return retval; +-- +2.19.1 + diff --git a/9013-bugfix-libmultipath-fix-memory-leaks-from-scandir-use.patch b/9013-bugfix-libmultipath-fix-memory-leaks-from-scandir-use.patch new file mode 100644 index 0000000..8cf6a2f --- /dev/null +++ b/9013-bugfix-libmultipath-fix-memory-leaks-from-scandir-use.patch @@ -0,0 +1,91 @@ +From a10343b550f56c6c39c6a9b8f9ad38ab825a3fa3 Mon Sep 17 00:00:00 2001 +From: root +Date: Fri, 22 Mar 2019 19:58:56 +0800 +Subject: [PATCH 3/5] libmultipath: fix memory leaks from scandir() use + +upstream commit b0e8a7456dd83cd0a5ecd1005e016656e785405f + +scandir() users must not only free the resulting dirent* array, +but also every member. Add a cleanup function, and fix the +existing users of scandir() in libmultipath. + +Add a small helper macro for casting function pointers to the +type pthread_cleanup_push() expects. +--- + libmultipath/config.c | 10 ++++------ + libmultipath/util.c | 9 +++++++++ + libmultipath/util.h | 8 ++++++++ + 3 files changed, 21 insertions(+), 6 deletions(-) + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index bfd07e3..654f330 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -640,17 +640,13 @@ free_config (struct config * conf) + FREE(conf); + } + +-static void free_namelist(void *nl) +-{ +- free(nl); +-} +- + /* if multipath fails to process the config directory, it should continue, + * with just a warning message */ + static void + process_config_dir(struct config *conf, vector keywords, char *dir) + { + struct dirent **namelist; ++ struct scandir_result sr; + int i, n; + char path[LINE_MAX]; + int old_hwtable_size; +@@ -670,7 +666,9 @@ process_config_dir(struct config *conf, vector keywords, char *dir) + return; + } else if (n == 0) + return; +- pthread_cleanup_push(free_namelist, namelist); ++ sr.di = namelist; ++ sr.n = n; ++ pthread_cleanup_push_cast(free_scandir_result, &sr); + for (i = 0; i < n; i++) { + if (!strstr(namelist[i]->d_name, ".conf")) + continue; +diff --git a/libmultipath/util.c b/libmultipath/util.c +index 3c284b7..2bb1102 100644 +--- a/libmultipath/util.c ++++ b/libmultipath/util.c +@@ -472,3 +472,12 @@ int safe_write(int fd, const void *buf, size_t count) + + return 0; + } ++ ++void free_scandir_result(struct scandir_result *res) ++{ ++ int i; ++ ++ for (i = 0; i < res->n; i++) ++ FREE(res->di[i]); ++ FREE(res->di); ++} +diff --git a/libmultipath/util.h b/libmultipath/util.h +index 56cec76..4374720 100644 +--- a/libmultipath/util.h ++++ b/libmultipath/util.h +@@ -28,5 +28,13 @@ int safe_write(int fd, const void *buf, size_t count); + snprintf(var, sizeof(var), format, ##args) >= sizeof(var) + #define safe_snprintf(var, size, format, args...) \ + snprintf(var, size, format, ##args) >= size ++#define pthread_cleanup_push_cast(f, arg) \ ++ pthread_cleanup_push(((void (*)(void *))&f), (arg)) ++ ++struct scandir_result { ++ struct dirent **di; ++ int n; ++}; ++void free_scandir_result(struct scandir_result *); + + #endif /* _UTIL_H */ +-- +2.19.1 + diff --git a/9014-bugfix-libmultipath-fix-memory-leak-in-disassemble_map.patch b/9014-bugfix-libmultipath-fix-memory-leak-in-disassemble_map.patch new file mode 100644 index 0000000..a4873a7 --- /dev/null +++ b/9014-bugfix-libmultipath-fix-memory-leak-in-disassemble_map.patch @@ -0,0 +1,87 @@ +From db72d840682d15abb2e6694704a91200e513dbac Mon Sep 17 00:00:00 2001 +From: root +Date: Fri, 22 Mar 2019 20:33:53 +0800 +Subject: [PATCH 5/5] libmultipath: fix memory leak in disassemble_map + +--- + libmultipath/dmparser.c | 12 ++++++++++-- + libmultipath/structs_vec.c | 10 ++++++++++ + 2 files changed, 20 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c +index 620f507..1558c4e 100644 +--- a/libmultipath/dmparser.c ++++ b/libmultipath/dmparser.c +@@ -142,6 +142,7 @@ int disassemble_map(vector pathvec, char *params, struct multipath *mpp, + int def_minio = 0; + struct path * pp; + struct pathgroup * pgp; ++ int pp_unfound; + + p = params; + +@@ -291,6 +292,7 @@ int disassemble_map(vector pathvec, char *params, struct multipath *mpp, + char devname[FILE_NAME_SIZE]; + + pp = NULL; ++ pp_unfound = 0; + p += get_word(p, &word); + + if (!word) +@@ -310,6 +312,7 @@ int disassemble_map(vector pathvec, char *params, struct multipath *mpp, + } + + if (!pp) { ++ pp_unfound = 1; + pp = alloc_path(); + + if (!pp) +@@ -322,8 +325,10 @@ int disassemble_map(vector pathvec, char *params, struct multipath *mpp, + WWID_SIZE - 1); + } + /* Only call this in multipath client mode */ +- if (!is_daemon && store_path(pathvec, pp)) ++ if (!is_daemon && store_path(pathvec, pp)) { ++ free_path(pp); + goto out1; ++ } + } else { + if (!strlen(pp->wwid) && + strlen(mpp->wwid)) +@@ -332,8 +337,11 @@ int disassemble_map(vector pathvec, char *params, struct multipath *mpp, + } + FREE(word); + +- if (store_path(pgp->paths, pp)) ++ if (store_path(pgp->paths, pp)) { ++ if (pp_unfound) ++ free_path(pp); + goto out; ++ } + + /* + * Update wwid for multipaths which are not setup +diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c +index 6c42824..828aef2 100644 +--- a/libmultipath/structs_vec.c ++++ b/libmultipath/structs_vec.c +@@ -252,6 +252,16 @@ void sync_paths(struct multipath *mpp, vector pathvec) + update_mpp_paths(mpp, pathvec); + vector_foreach_slot (mpp->paths, pp, i) + pp->mpp = mpp; ++ ++ vector_foreach_slot (mpp->pg, pgp, i) { ++ vector_foreach_slot (pgp->paths, pp, j) { ++ if ((find_slot(mpp->paths, pp) == -1) \ ++ && (find_slot(pathvec, pp) == -1)) { ++ vector_del_slot(pgp->paths, j--); ++ free_path(pp); ++ } ++ } ++ } + } + + int +-- +2.19.1 + diff --git a/9015-bugfix-check-close-return-value.patch b/9015-bugfix-check-close-return-value.patch new file mode 100644 index 0000000..8115f5c --- /dev/null +++ b/9015-bugfix-check-close-return-value.patch @@ -0,0 +1,29 @@ +Subject: [PATCH] check close return value + +--- + mpathpersist/main.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/mpathpersist/main.c b/mpathpersist/main.c +index 4db07b2..db8b6d7 100644 +--- a/mpathpersist/main.c ++++ b/mpathpersist/main.c +@@ -498,7 +498,14 @@ int main (int argc, char * argv[]) + + out : + if (fd >= 0) +- close(fd); ++ { ++ res = close(fd); ++ if (res < 0) ++ { ++ ret = MPATH_PR_FILE_ERROR; ++ } ++ ++ } + mpath_lib_exit(conf); + udev_unref(udev); + return (ret >= 0) ? ret : MPATH_PR_OTHER; +-- +2.19.1 + diff --git a/9016-fix-find-multipath-failure.patch b/9016-fix-find-multipath-failure.patch new file mode 100644 index 0000000..7d87131 --- /dev/null +++ b/9016-fix-find-multipath-failure.patch @@ -0,0 +1,28 @@ +From eba371974dc9343740ff3b3fd18caab8529291d1 Mon Sep 17 00:00:00 2001 +From: openEuler Buildteam +Date: Thu, 2 Jan 2020 15:34:13 +0800 +Subject: [PATCH] device-mapper-multipath: fix find multipath failure + +when DEFAULT_FIND_MULTIPATHS is FIND_MULTIPATHS_STRICT, it fail to +find multipath in find_multipaths function, use FIND_MULTIPATHS_OFF +instead of FIND_MULTIPATHS_STRICT. +--- + libmultipath/defaults.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h +index 7f3839f..c84d31d 100644 +--- a/libmultipath/defaults.h ++++ b/libmultipath/defaults.h +@@ -17,7 +17,7 @@ + #define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF + #define DEFAULT_VERBOSITY 2 + #define DEFAULT_REASSIGN_MAPS 0 +-#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_STRICT ++#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_OFF + #define DEFAULT_FAST_IO_FAIL 5 + #define DEFAULT_DEV_LOSS_TMO 600 + #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON +-- +1.8.3.1 + diff --git a/9017-change-kpartx-file-and-default-bindir.patch b/9017-change-kpartx-file-and-default-bindir.patch new file mode 100644 index 0000000..f3ef96b --- /dev/null +++ b/9017-change-kpartx-file-and-default-bindir.patch @@ -0,0 +1,42 @@ +From 768883da9969b76aade3e16d4a5b8cec47d6f30e Mon Sep 17 00:00:00 2001 +From: wangjufeng +Date: Fri, 10 Jan 2020 11:57:08 +0800 +Subject: [PATCH] kpartx: change kpartx file and default bindir + +Change default bindir of multipath to /usr/sbin. Don't +set device name-partition number delimiter in kpartx rules. + +Signed-off-by: wangjufeng +--- + Makefile.inc | 2 +- + kpartx/kpartx.rules | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index af2f5ba..e6466ee 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -49,7 +49,7 @@ ifndef SYSTEMDPATH + endif + + prefix = +-exec_prefix = $(prefix) ++exec_prefix = $(prefix)/usr + usr_prefix = $(prefix) + bindir = $(exec_prefix)/sbin + libudevdir = $(prefix)/$(SYSTEMDPATH)/udev +diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules +index 8f99049..8a3a171 100644 +--- a/kpartx/kpartx.rules ++++ b/kpartx/kpartx.rules +@@ -32,6 +32,6 @@ LABEL="mpath_kpartx_end" + GOTO="kpartx_end" + + LABEL="run_kpartx" +-RUN+="/sbin/kpartx -un -p -part /dev/$name" ++RUN+="/sbin/kpartx -un /dev/$name" + + LABEL="kpartx_end" +-- +1.8.3.1 + diff --git a/multipath-tools-ef6d98b.tgz b/multipath-tools-ef6d98b.tgz new file mode 100644 index 0000000..37d46df Binary files /dev/null and b/multipath-tools-ef6d98b.tgz differ diff --git a/multipath-tools.spec b/multipath-tools.spec new file mode 100644 index 0000000..28fef1c --- /dev/null +++ b/multipath-tools.spec @@ -0,0 +1,234 @@ +Name: multipath-tools +Version: 0.7.7 +Release: 14 +Summary: Tools to manage multipath devices with the device-mapper +License: GPLv2-or-later and LGPLv2+ +URL: http://christophe.varoqui.free.fr/ + +# curl "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=ef6d98b;sf=tgz" -o multipath-tools-ef6d98b.tgz +Source0: multipath-tools-ef6d98b.tgz +Source1: multipath.conf +Patch0000: 0000-libmultipath-remove-last-of-rbd-code.patch +Patch0001: 0001-libmultipath-fix-detect-alua-corner-case.patch +Patch0002: 0002-multipath-fix-setting-conf-version.patch +Patch0003: 0003-mpathpersist-add-param-alltgpt-option.patch +Patch0004: 0004-libmutipath-remove-unused-IDE-bus-type.patch +Patch0005: 0005-multipathd-add-new-protocol-path-wildcard.patch +Patch0006: 0006-libmultipath-add-protocol-blacklist-option.patch +Patch0007: 0007-libmultipath-remove-_filter_-blacklist-functions.patch +Patch0008: 0008-multipath-tests-change-to-work-with-old-make-version.patch +Patch0009: 0009-multipath-tests-add-blacklist-tests.patch +Patch0010: 0010-mpathpersist-add-missing-param-rk-usage-info.patch +Patch0011: 0011-change-order-of-multipath.rules.patch +Patch0012: 0012-RH-Remove-the-property-blacklist-exception-builtin.patch + +Patch9000: 9000-fix-segfault-when-mount-or-umount-VIMS-with-reservation-conflict.patch +Patch9001: 9001-fix-multipathd-resize-when-not-all-paths-size-are-equal.patch +Patch9002: 9002-multipathd-disable-queueing-for-recreated-map-in-uev.patch +Patch9003: 9003-avoid-handling-paths-repeatedly-in-coalesce-paths.patch +Patch9004: 9004-fix-bugs-backported-from-next-branch.patch +Patch9005: 9005-bugfix-fix-change-reservation-key-to-uint8-for-memcmp.patch +Patch9006: 9006-bugfix-ignore-for-clear-mismatch-key.patch +Patch9007: 9007-bugfix-flush-and-sync-before-reboot.patch +Patch9008: 9008-bugfix-RH-remove-local-disk-from-pathvec.patch +Patch9009: 9009-bugfix-lun-expansion-failure-when-there-is-offline-path.patch +Patch9010: 9010-bugfix-some-memory-leaks-issues-in-libmpathpersist.patch + +Patch6000: 6000-libmultipath-fix-set_int-error-path.patch +Patch6001: 6001-libmultipath-free-allocated-value-in-set_int.patch +Patch6002: 6002-libmultipath-fix-memory-issue-in-path_latency-prio.patch +Patch6003: 6003-libmultipath-fix-null-dereference-int-alloc_path_group.patch +Patch6004: 6004-multipath-fix-max-array-size-in-print_cmd_valid.patch +Patch6005: 6005-multipathd-minor-fixes.patch +Patch6006: 6006-multipathd-fix-memory-leak-on-error-in-configure.patch +Patch6007: 6007-multipathd-check-for-NULL-udevice-in-cli_add_path.patch +Patch6008: 6008-kpartx-fix-apparent-out-of-bounds-access.patch +Patch6009: 6009-libmultipath-fix-apparent-overflow.patch +Patch6010: 6010-libmultipath-fix-int-overflow-in-sysfs_set_scsi_tmo.patch +Patch6011: 6011-libmultipath-fix-enum-misuse-for-find_multipaths.patch +Patch6012: 6012-libmultipath-fix-possible-NULL-dereference.patch +Patch6014: 6014-fix-syntax-error.patch + +Patch9011: 9011-bugfix-change-log-level-to-info-if-alua-is-not-support-by-s.patch +Patch9012: 9012-bugfix-clear-mpp-path-reference-when-path-is-freed-otherwis.patch +Patch9013: 9013-bugfix-libmultipath-fix-memory-leaks-from-scandir-use.patch +Patch9014: 9014-bugfix-libmultipath-fix-memory-leak-in-disassemble_map.patch +Patch6013: 6013-multipathd-fix-mpp-hwe-handling-when-paths-are-freed.patch +Patch9015: 9015-bugfix-check-close-return-value.patch +Patch9016: 9016-fix-find-multipath-failure.patch +Patch9017: 9017-change-kpartx-file-and-default-bindir.patch + +Patch6020: 6020-multipathd-ignore-failed-wwid-recheck.patch +Patch6021: 6021-libmultipath-group_by_prio-fix-signedness-bug.patch +Patch6022: 6022-multipathd-handle-NULL-return-from-genhelp_handler.patch +Patch6023: 6023-libmultipath-fix-parsing-of-VPD-83-type-1-T10-vendor.patch +Patch6024: 6024-libmultipath-Fix-buffer-overflow-in-parse_vpd_pg80.patch +Patch6025: 6025-libmultipath-fix-another-WWID-overflow-in-parse_vpd_.patch +Patch6026: 6026-libmultipath-fix-possible-WWID-overflow-in-parse_vpd.patch +Patch6027: 6027-libmultipath-fix-parsing-of-SCSI-name-string-iqn-for.patch +Patch6028: 6028-libmultipath-fix-double-free-in-pgpolicyfn-error-pat.patch + + +BuildRequires: gcc, libaio-devel, userspace-rcu-devel, device-mapper-devel >= 1.02.89 +BuildRequires: libselinux-devel, libsepol-devel, readline-devel, ncurses-devel, git +BuildRequires: systemd-units, systemd-devel, json-c-devel, perl-interpreter, pkgconfig +Requires: userspace-rcu, json-c, device-mapper >= 1.02.96 +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units +Conflicts: mdadm < 4.1-rc2.0.2 +Conflicts: udisks2 < 2.8.0-2 +Provides: device-mapper-multipath +Obsoletes: device-mapper-multipath +Provides: device-mapper-multipath-libs +Obsoletes: device-mapper-multipath-libs +Provides: kpartx +Obsoletes: kpartx +Provides: libdmmp +Obsoletes: libdmmp + +%description +This package provides the multipath tool and the multipathd daemon +to manage dm-multipath devices. multipath can detect and set up +multipath maps. multipathd sets up multipath maps automatically, +monitors path devices for failure, removal, or addition, and applies +the necessary changes to the multipath maps to ensure continuous +availability of the map devices. + +%package devel +Summary: Development libraries for %{name} +Requires: %{name} = %{version}-%{release} +Obsoletes: %{name}-libs < %{version}-%{release} +Provides: libdmmp-devel +Obsoletes: libdmmp-devel +Provides: device-mapper-multipath-devel +Obsoletes: device-mapper-multipath-devel +Requires: pkgconfig +Obsoletes: libdmmp + +%description devel +This package contains the development libraries for %{name} +that are %{name}'s libbmpathpersist and libmpathcmd libraries. + +%package help +Summary: Including man files for multipath-tools. +Requires: man +Provides: device-mapper-multipath-help +Obsoletes: device-mapper-multipath-help +%description help +This contains man files for the using of multipath-tools. + +%prep +%autosetup -Sgit -n multipath-tools-ef6d98b +cp %{SOURCE1} . + +%build +%make_build LIB=%{_lib} + +%install +make install \ + DESTDIR=%{buildroot} \ + bindir=/usr/sbin \ + syslibdir=/usr/%{_lib} \ + usrlibdir=/usr/%{_lib} \ + libdir=/usr/%{_lib}/multipath \ + rcdir=%{_initrddir} \ + unitdir=%{_unitdir} \ + includedir=%{_includedir} \ + pkgconfdir=/usr/%{_lib}/pkgconfig + +install -d %{buildroot}/etc/multipath +rm -rf %{buildroot}/%{_initrddir} + +%post +/sbin/ldconfig +%systemd_post multipathd.service + +%preun +%systemd_preun multipathd.service + +%postun +/sbin/ldconfig +if [ $1 -ge 1 ] ; then + /sbin/multipathd forcequeueing daemon > /dev/null 2>&1 || : +fi +%systemd_postun_with_restart multipathd.service + +%triggerun -- %{name} < 0.4.9-37 +/bin/systemctl --quiet is-enabled multipathd.service >/dev/null 2>&1 && /bin/systemctl reenable multipathd.service ||: + + +%files +%doc README README.alua multipath.conf +%license LICENSES/GPL-2.0 LICENSES/LGPL-2.0 LICENSES/GPL-3.0 +%{_unitdir}/* + /usr/sbin/* + /usr/%{_lib}/libmultipath.so + /usr/%{_lib}/libmultipath.so.* + /usr/%{_lib}/libmpathpersist.so.* + /usr/%{_lib}/libmpathcmd.so.* + /usr/%{_lib}/libdmmp.so.* +%dir /etc/multipath +%dir /usr/%{_lib}/multipath + /usr/%{_lib}/multipath/* + /usr/lib/udev/kpartx_id +%config /usr/lib/udev/rules.d/* + +%files devel +%doc README + %{_includedir}/*.h +%dir %{_includedir}/libdmmp + %{_includedir}/libdmmp/* + /usr/%{_lib}/libmpathpersist.so + /usr/%{_lib}/libmpathcmd.so + /usr/%{_lib}/libdmmp.so + /usr/%{_lib}/pkgconfig/libdmmp.pc + +%files help +%{_mandir}/man3/* +%{_mandir}/man5/* +%{_mandir}/man8/* + + +%changelog +* Fri Jan 10 2020 wangjufeng - 0.7.7-14 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:rename the package + +* Fri Jan 10 2020 wangjufeng - 0.7.7-13 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:rewrap the package + +* Fri Jan 3 2020 openEuler Buildteam - 0.7.7-12 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix find multipath failure + +* Tue Dec 31 2019 openEuler Buildteam - 0.7.7-11 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:package rewrap + +* Thu Dec 25 2019 openEuler Buildteam - 0.7.7-10 +- reupload patches + +* Wed Dec 25 2019 openEuler Buildteam - 0.7.7-9 +- revert patches + +* Tue Dec 24 2019 openEuler Buildteam - 0.7.7-8 +- bugfix + +* Fri Nov 01 2019 wangjufeng - 0.7.7-7 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix syntax error + +* Tue Sep 17 2019 zoujing - 0.7.7-6 +- Package init diff --git a/multipath.conf b/multipath.conf new file mode 100644 index 0000000..c7684fe --- /dev/null +++ b/multipath.conf @@ -0,0 +1,93 @@ +# This is a basic configuration file with some examples, for device mapper +# multipath. +# +# For a complete list of the default configuration values, run either +# multipath -t +# or +# multipathd show config +# +# For a list of configuration options with descriptions, see the multipath.conf +# man page + +## By default, devices with vendor = "IBM" and product = "S/390.*" are +## blacklisted. To enable mulitpathing on these devies, uncomment the +## following lines. +#blacklist_exceptions { +# device { +# vendor "IBM" +# product "S/390.*" +# } +#} + +## Use user friendly names, instead of using WWIDs as names. +defaults { + user_friendly_names yes + find_multipaths yes +} +## +## Here is an example of how to configure some standard options. +## +# +#defaults { +# udev_dir /dev +# polling_interval 10 +# selector "round-robin 0" +# path_grouping_policy multibus +# prio alua +# path_checker readsector0 +# rr_min_io 100 +# max_fds 8192 +# rr_weight priorities +# failback immediate +# no_path_retry fail +# user_friendly_names yes +#} +## +## The wwid line in the following blacklist section is shown as an example +## of how to blacklist devices by wwid. The 2 devnode lines are the +## compiled in default blacklist. If you want to blacklist entire types +## of devices, such as all scsi devices, you should use a devnode line. +## However, if you want to blacklist specific devices, you should use +## a wwid line. Since there is no guarantee that a specific device will +## not change names on reboot (from /dev/sda to /dev/sdb for example) +## devnode lines are not recommended for blacklisting specific devices. +## +#blacklist { +# wwid 26353900f02796769 +# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" +# devnode "^hd[a-z]" +#} +#multipaths { +# multipath { +# wwid 3600508b4000156d700012000000b0000 +# alias yellow +# path_grouping_policy multibus +# path_checker readsector0 +# path_selector "round-robin 0" +# failback manual +# rr_weight priorities +# no_path_retry 5 +# } +# multipath { +# wwid 1DEC_____321816758474 +# alias red +# } +#} +#devices { +# device { +# vendor "COMPAQ " +# product "HSV110 (C)COMPAQ" +# path_grouping_policy multibus +# path_checker readsector0 +# path_selector "round-robin 0" +# hardware_handler "0" +# failback 15 +# rr_weight priorities +# no_path_retry queue +# } +# device { +# vendor "COMPAQ " +# product "MSA1000 " +# path_grouping_policy multibus +# } +#}