diff --git a/SOURCES/0050-RH-listing-speedup.patch b/SOURCES/0050-RH-listing-speedup.patch new file mode 100644 index 0000000..4742634 --- /dev/null +++ b/SOURCES/0050-RH-listing-speedup.patch @@ -0,0 +1,17 @@ +--- + multipath/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -311,7 +311,7 @@ configure (void) + /* + * get a path list + */ +- if (conf->dev) ++ if (conf->dev && !conf->list) + di_flag = DI_WWID; + + if (conf->list > 1) diff --git a/SOURCES/0081-RHBZ-1066264-check-prefix-on-rename.patch b/SOURCES/0081-RHBZ-1066264-check-prefix-on-rename.patch new file mode 100644 index 0000000..791f32e --- /dev/null +++ b/SOURCES/0081-RHBZ-1066264-check-prefix-on-rename.patch @@ -0,0 +1,41 @@ +--- + libmultipath/devmapper.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -1151,6 +1151,8 @@ dm_rename_partmaps (char * old, char * n + unsigned long long size; + char dev_t[32]; + int r = 1; ++ int offset; ++ char *delim; + + if (!(dmt = dm_task_create(DM_DEVICE_LIST))) + return 1; +@@ -1171,6 +1173,11 @@ dm_rename_partmaps (char * old, char * n + if (dm_dev_t(old, &dev_t[0], 32)) + goto out; + ++ if (isdigit(new[strlen(new)-1])) ++ delim = "p"; ++ else ++ delim = ""; ++ + do { + if ( + /* +@@ -1198,8 +1205,9 @@ dm_rename_partmaps (char * old, char * n + * then it's a kpartx generated partition. + * Rename it. + */ +- snprintf(buff, PARAMS_SIZE, "%s%s", +- new, names->name + strlen(old)); ++ for (offset = strlen(old); names->name[offset] && !(isdigit(names->name[offset])); offset++); /* do nothing */ ++ snprintf(buff, PARAMS_SIZE, "%s%s%s", ++ new, delim, names->name + offset); + dm_rename(names->name, buff); + condlog(4, "partition map %s renamed", + names->name); diff --git a/SOURCES/0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch b/SOURCES/0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch new file mode 100644 index 0000000..9a1bd34 --- /dev/null +++ b/SOURCES/0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch @@ -0,0 +1,32 @@ +--- + libmultipath/checkers/tur.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +Index: multipath-tools-130222/libmultipath/checkers/tur.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/tur.c ++++ multipath-tools-130222/libmultipath/checkers/tur.c +@@ -409,7 +409,6 @@ libcheck_check (struct checker * c) + ct->running = 0; + MSG(c, MSG_TUR_TIMEOUT); + tur_status = PATH_DOWN; +- ct->state = PATH_UNCHECKED; + } else { + condlog(3, "%d:%d: tur checker not finished", + TUR_DEVT(ct)); +@@ -426,12 +425,10 @@ libcheck_check (struct checker * c) + pthread_mutex_unlock(&ct->lock); + } else { + if (ct->thread) { +- /* pthread cancel failed. continue in sync mode */ + pthread_mutex_unlock(&ct->lock); +- condlog(3, "%d:%d: tur thread not responding, " +- "using sync mode", TUR_DEVT(ct)); +- return tur_check(c->fd, c->timeout, c->message, +- ct->wwid); ++ condlog(3, "%d:%d: tur thread not responding, ", ++ TUR_DEVT(ct)); ++ return PATH_DOWN; + } + /* Start new TUR checker */ + ct->state = PATH_UNCHECKED; diff --git a/SOURCES/0083-RHBZ-1080055-orphan-paths-on-reload.patch b/SOURCES/0083-RHBZ-1080055-orphan-paths-on-reload.patch new file mode 100644 index 0000000..8eaee74 --- /dev/null +++ b/SOURCES/0083-RHBZ-1080055-orphan-paths-on-reload.patch @@ -0,0 +1,85 @@ +--- + libmultipath/structs_vec.c | 31 +++++++++++++++++++++++++++---- + multipathd/main.c | 4 ++++ + 2 files changed, 31 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -280,12 +280,38 @@ update_multipath_status (struct multipat + return 0; + } + ++void sync_paths(struct multipath *mpp, vector pathvec) ++{ ++ struct path *pp; ++ struct pathgroup *pgp; ++ int found, i, j; ++ ++ vector_foreach_slot (mpp->paths, pp, i) { ++ found = 0; ++ vector_foreach_slot(mpp->pg, pgp, j) { ++ if (find_slot(pgp->paths, (void *)pp) != -1) { ++ found = 1; ++ break; ++ } ++ } ++ if (!found) { ++ condlog(3, "%s dropped path %s", mpp->alias, pp->dev); ++ vector_del_slot(mpp->paths, i--); ++ orphan_path(pp); ++ } ++ } ++ update_mpp_paths(mpp, pathvec); ++ vector_foreach_slot (mpp->paths, pp, i) ++ pp->mpp = mpp; ++} ++ + extern int + update_multipath_strings (struct multipath *mpp, vector pathvec) + { + if (!mpp) + return 1; + ++ update_mpp_paths(mpp, pathvec); + condlog(4, "%s: %s", mpp->alias, __FUNCTION__); + + free_multipath_attributes(mpp); +@@ -294,6 +320,7 @@ update_multipath_strings (struct multipa + + if (update_multipath_table(mpp, pathvec)) + return 1; ++ sync_paths(mpp, pathvec); + + if (update_multipath_status(mpp)) + return 1; +@@ -494,13 +521,9 @@ int update_multipath (struct vectors *ve + return 2; + } + +- free_pgvec(mpp->pg, KEEP_PATHS); +- mpp->pg = NULL; +- + if (__setup_multipath(vecs, mpp, reset)) + return 1; /* mpp freed in setup_multipath */ + +- adopt_paths(vecs->pathvec, mpp, 0); + /* + * compare checkers states with DM states + */ +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1152,6 +1152,10 @@ check_path (struct vectors * vecs, struc + pp->dev); + pp->dmstate = PSTATE_UNDEF; + } ++ /* if update_multipath_strings orphaned the path, quit early */ ++ if (!pp->mpp) ++ return; ++ + pp->chkrstate = newstate; + if (newstate != pp->state) { + int oldstate = pp->state; diff --git a/SOURCES/0084-RHBZ-1110000-multipath-man.patch b/SOURCES/0084-RHBZ-1110000-multipath-man.patch new file mode 100644 index 0000000..4ea422a --- /dev/null +++ b/SOURCES/0084-RHBZ-1110000-multipath-man.patch @@ -0,0 +1,101 @@ +--- + libmultipath/prioritizers/alua.c | 4 ++-- + multipathd/multipathd.8 | 37 +++++++++++++++++++++++++++++++++---- + 2 files changed, 35 insertions(+), 6 deletions(-) + +Index: multipath-tools-130222/multipathd/multipathd.8 +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.8 ++++ multipath-tools-130222/multipathd/multipathd.8 +@@ -42,6 +42,9 @@ format wildcards. + .B list|show maps|multipaths + Show the multipath devices that the multipathd is monitoring. + .TP ++.B list|show daemon ++Show the current state of the multipathd daemon ++.TP + .B list|show maps|multipaths format $format + Show the status of all multipath devices that the multipathd is monitoring, + using a format string with multipath format wildcards. +@@ -83,16 +86,16 @@ Add a path to the list of monitored path + .B remove|del path $path + Stop monitoring a path. $path is as listed in /sys/block (e.g. sda). + .TP +-.B add map $map ++.B add map|multipath $map + Add a multipath device to the list of monitored devices. $map can either be a device-mapper device as listed in /sys/block (e.g. dm-0) or it can be the alias for the multipath device (e.g. mpath1) or the uid of the multipath device (e.g. 36005076303ffc56200000000000010aa). + .TP +-.B remove|del map $map ++.B remove|del map|multipath $map + Stop monitoring a multipath device. + .TP + .B resize map|multipath $map + Resizes map $map to the given size + .TP +-.B switch|switchgroup map $map group $group ++.B switch|switchgroup map|multipath $map group $group + Force a multipath device to switch to a specific path group. $group is the path group index, starting with 1. + .TP + .B reconfigure +@@ -104,6 +107,13 @@ Sets map $map into suspend state. + .B resume map|multipath $map + Resumes map $map from suspend state. + .TP ++.B reset map|multipath $map ++Reassign existing device-mapper table(s) use use the multipath device, instead ++of its path devices. ++.TP ++.B reload map|multipath $map ++Reload a multipath device. ++.TP + .B fail path $path + Sets path $path into failed state. + .TP +@@ -120,10 +130,29 @@ Restore queueing on all multipath device + Disable queuing on multipathed map $map + .TP + .B restorequeueing map|multipath $map +-Restore queuing on multipahted map $map ++Restore queuing on multipathed map $map ++.TP ++.B forcequeueing daemon ++Forces multipathd into queue_without_daemon mode, so that no_path_retry queueing ++will not be disabled when the daemon stops ++.TP ++.B restorequeueing daemon ++Restores configured queue_without_daemon mode ++.TP ++.B map|multipath $map setprstatus ++Enable persistent reservation management on $map ++.TP ++.B map|multipath $map unsetprstatus ++Disable persistent reservation management on $map ++.TP ++.B map|multipath $map getprstatus ++Get the current persistent reservation management status of $map + .TP + .B quit|exit + End interactive session. ++.TP ++.B shutdown ++Stop multipathd. + + .SH "SEE ALSO" + .BR multipath (8) +Index: multipath-tools-130222/libmultipath/prioritizers/alua.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua.c ++++ multipath-tools-130222/libmultipath/prioritizers/alua.c +@@ -119,10 +119,10 @@ int getprio (struct path * pp, char * ar + condlog(0, "%s: couldn't get target port group", pp->dev); + break; + case ALUA_PRIO_GETAAS_FAILED: +- condlog(0, "%s: couln't get asymmetric access state", pp->dev); ++ condlog(0, "%s: couldn't get asymmetric access state", pp->dev); + break; + case ALUA_PRIO_TPGS_FAILED: +- condlog(3, "%s: couln't get supported alua states", pp->dev); ++ condlog(3, "%s: couldn't get supported alua states", pp->dev); + break; + } + } diff --git a/SOURCES/0085-UPBZ-1110006-datacore-config.patch b/SOURCES/0085-UPBZ-1110006-datacore-config.patch new file mode 100644 index 0000000..cedb5e3 --- /dev/null +++ b/SOURCES/0085-UPBZ-1110006-datacore-config.patch @@ -0,0 +1,28 @@ +--- + libmultipath/hwtable.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1108,6 +1108,19 @@ static struct hwentry default_hw[] = { + .prio_name = PRIO_ALUA, + .prio_args = NULL, + }, ++ { ++ .vendor = "DataCore", ++ .product = "Virtual Disk", ++ .features = DEFAULT_FEATURES, ++ .hwhandler = DEFAULT_HWHANDLER, ++ .pgpolicy = GROUP_BY_PRIO, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .rr_weight = RR_WEIGHT_NONE, ++ .no_path_retry = NO_PATH_RETRY_QUEUE, ++ .checker_name = TUR, ++ .prio_name = PRIO_ALUA, ++ .prio_args = NULL, ++ }, + /* + * EOL + */ diff --git a/SOURCES/0086-RHBZ-1110007-orphan-path-on-failed-add.patch b/SOURCES/0086-RHBZ-1110007-orphan-path-on-failed-add.patch new file mode 100644 index 0000000..0d6aa58 --- /dev/null +++ b/SOURCES/0086-RHBZ-1110007-orphan-path-on-failed-add.patch @@ -0,0 +1,17 @@ +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -562,7 +562,7 @@ rescan: + return 0; + } + else +- return 1; ++ goto fail; + + fail_map: + remove_map(mpp, vecs, 1); diff --git a/SOURCES/0087-RHBZ-1110013-config-error-checking.patch b/SOURCES/0087-RHBZ-1110013-config-error-checking.patch new file mode 100644 index 0000000..c774bc5 --- /dev/null +++ b/SOURCES/0087-RHBZ-1110013-config-error-checking.patch @@ -0,0 +1,190 @@ +--- + libmultipath/parser.c | 154 ++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 126 insertions(+), 28 deletions(-) + +Index: multipath-tools-130222/libmultipath/parser.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/parser.c ++++ multipath-tools-130222/libmultipath/parser.c +@@ -395,36 +395,57 @@ set_value(vector strvec) + char *alloc = NULL; + char *tmp; + +- if (!str) ++ if (!str) { ++ condlog(0, "option '%s' missing value", ++ (char *)VECTOR_SLOT(strvec, 0)); + return NULL; +- ++ } + size = strlen(str); +- if (size == 0) ++ if (size == 0) { ++ condlog(0, "option '%s' has empty value", ++ (char *)VECTOR_SLOT(strvec, 0)); + return NULL; +- +- if (*str == '"') { +- for (i = 2; i < VECTOR_SIZE(strvec); i++) { +- str = VECTOR_SLOT(strvec, i); +- len += strlen(str); +- if (!alloc) +- alloc = +- (char *) MALLOC(sizeof (char *) * +- (len + 1)); +- else { +- alloc = +- REALLOC(alloc, sizeof (char *) * (len + 1)); +- tmp = VECTOR_SLOT(strvec, i-1); +- if (alloc && *str != '"' && *tmp != '"') +- strncat(alloc, " ", 1); +- } +- +- if (alloc && i != VECTOR_SIZE(strvec)-1) +- strncat(alloc, str, strlen(str)); +- } +- } else { +- alloc = MALLOC(sizeof (char *) * (size + 1)); ++ } ++ if (*str != '"') { ++ alloc = MALLOC(sizeof (char) * (size + 1)); + if (alloc) + memcpy(alloc, str, size); ++ else ++ condlog(0, "can't allocate memeory for option '%s'", ++ (char *)VECTOR_SLOT(strvec, 0)); ++ return alloc; ++ } ++ /* Even empty quotes counts as a value (An empty string) */ ++ alloc = (char *) MALLOC(sizeof (char)); ++ if (!alloc) { ++ condlog(0, "can't allocate memeory for option '%s'", ++ (char *)VECTOR_SLOT(strvec, 0)); ++ return NULL; ++ } ++ for (i = 2; i < VECTOR_SIZE(strvec); i++) { ++ str = VECTOR_SLOT(strvec, i); ++ if (!str) { ++ free(alloc); ++ condlog(0, "parse error for option '%s'", ++ (char *)VECTOR_SLOT(strvec, 0)); ++ return NULL; ++ } ++ if (*str == '"') ++ break; ++ tmp = alloc; ++ /* The first +1 is for the NULL byte. The rest are for the ++ * spaces between words */ ++ len += strlen(str) + 1; ++ alloc = REALLOC(alloc, sizeof (char) * len); ++ if (!alloc) { ++ FREE(tmp); ++ condlog(0, "can't allocate memeory for option '%s'", ++ (char *)VECTOR_SLOT(strvec, 0)); ++ return NULL; ++ } ++ if (*alloc != '\0') ++ strncat(alloc, " ", 1); ++ strncat(alloc, str, strlen(str)); + } + return alloc; + } +@@ -465,6 +486,74 @@ void free_uniques(vector uniques) + } + + int ++is_sublevel_keyword(char *str) ++{ ++ return (strcmp(str, "defaults") == 0 || strcmp(str, "blacklist") == 0 || ++ strcmp(str, "blacklist_exceptions") == 0 || ++ strcmp(str, "devices") == 0 || strcmp(str, "devices") == 0 || ++ strcmp(str, "device") == 0 || strcmp(str, "multipaths") == 0 || ++ strcmp(str, "multipath") == 0); ++} ++ ++int ++validate_config_strvec(vector strvec) ++{ ++ char *str; ++ int i; ++ ++ str = VECTOR_SLOT(strvec, 0); ++ if (str == NULL) { ++ condlog(0, "can't parse option on line %d of config file", ++ line_nr); ++ return -1; ++ } ++ if (*str == '}') { ++ if (VECTOR_SIZE(strvec) > 1) ++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 1), line_nr); ++ return 0; ++ } ++ if (*str == '{') { ++ condlog(0, "invalid keyword '%s' on line %d of config file", str, line_nr); ++ return -1; ++ } ++ if (is_sublevel_keyword(str)) { ++ str = VECTOR_SLOT(strvec, 1); ++ if (str == NULL) ++ condlog(0, "missing '{' on line %d of config file", line_nr); ++ else if (*str != '{') ++ condlog(0, "expecting '{' on line %d of config file. found '%s'", line_nr, str); ++ else if (VECTOR_SIZE(strvec) > 2) ++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr); ++ return 0; ++ } ++ str = VECTOR_SLOT(strvec, 1); ++ if (str == NULL) { ++ condlog(0, "missing value for option '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 0), line_nr); ++ return -1; ++ } ++ if (*str != '"') { ++ if (VECTOR_SIZE(strvec) > 2) ++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr); ++ return 0; ++ } ++ for (i = 2; i < VECTOR_SIZE(strvec); i++) { ++ str = VECTOR_SLOT(strvec, i); ++ if (str == NULL) { ++ condlog(0, "can't parse value on line %d of config file", line_nr); ++ return -1; ++ } ++ if (*str == '"') { ++ if (VECTOR_SIZE(strvec) > i + 1) ++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr); ++ return 0; ++ } ++ } ++ condlog(0, "missing closing quotes on line %d of config file", ++ line_nr); ++ return 0; ++} ++ ++int + process_stream(vector keywords) + { + int i; +@@ -494,11 +583,20 @@ process_stream(vector keywords) + if (!strvec) + continue; + ++ if (validate_config_strvec(strvec) != 0) { ++ free_strvec(strvec); ++ continue; ++ } ++ + str = VECTOR_SLOT(strvec, 0); + +- if (!strcmp(str, EOB) && kw_level > 0) { +- free_strvec(strvec); +- break; ++ if (!strcmp(str, EOB)) { ++ if (kw_level > 0) { ++ free_strvec(strvec); ++ break; ++ } ++ condlog(0, "unmatched '%s' at line %d of config file", ++ EOB, line_nr); + } + + for (i = 0; i < VECTOR_SIZE(keywords); i++) { diff --git a/SOURCES/0088-RHBZ-1069811-configurable-prio-timeout.patch b/SOURCES/0088-RHBZ-1069811-configurable-prio-timeout.patch new file mode 100644 index 0000000..60f374b --- /dev/null +++ b/SOURCES/0088-RHBZ-1069811-configurable-prio-timeout.patch @@ -0,0 +1,178 @@ +--- + libmultipath/prio.c | 7 +++++++ + libmultipath/prio.h | 1 + + libmultipath/prioritizers/alua_rtpg.c | 5 +++-- + libmultipath/prioritizers/emc.c | 2 +- + libmultipath/prioritizers/hds.c | 2 +- + libmultipath/prioritizers/hp_sw.c | 2 +- + libmultipath/prioritizers/ontap.c | 4 ++-- + libmultipath/prioritizers/rdac.c | 2 +- + multipath.conf.annotated | 5 +++-- + multipath/multipath.conf.5 | 4 ++-- + 10 files changed, 22 insertions(+), 12 deletions(-) + +Index: multipath-tools-130222/libmultipath/prio.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prio.c ++++ multipath-tools-130222/libmultipath/prio.c +@@ -10,6 +10,13 @@ + + static LIST_HEAD(prioritizers); + ++unsigned int get_prio_timeout(unsigned int default_timeout) ++{ ++ if (conf->checker_timeout) ++ return conf->checker_timeout * 1000; ++ return default_timeout; ++} ++ + int init_prio (void) + { + if (!add_prio(DEFAULT_PRIO)) +Index: multipath-tools-130222/libmultipath/prio.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prio.h ++++ multipath-tools-130222/libmultipath/prio.h +@@ -51,6 +51,7 @@ struct prio { + int (*getprio)(struct path *, char *); + }; + ++unsigned int get_prio_timeout(unsigned int default_timeout); + int init_prio (void); + void cleanup_prio (void); + struct prio * add_prio (char *); +Index: multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua_rtpg.c ++++ multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c +@@ -21,6 +21,7 @@ + #define __user + #include + ++#include "../prio.h" + #include "alua_rtpg.h" + + #define SENSE_BUFF_LEN 32 +@@ -134,7 +135,7 @@ do_inquiry(int fd, int evpd, unsigned in + hdr.dxfer_len = resplen; + hdr.sbp = sense; + hdr.mx_sb_len = sizeof(sense); +- hdr.timeout = DEF_TIMEOUT; ++ hdr.timeout = get_prio_timeout(DEF_TIMEOUT); + + if (ioctl(fd, SG_IO, &hdr) < 0) { + PRINT_DEBUG("do_inquiry: IOCTL failed!\n"); +@@ -253,7 +254,7 @@ do_rtpg(int fd, void* resp, long resplen + hdr.dxfer_len = resplen; + hdr.mx_sb_len = sizeof(sense); + hdr.sbp = sense; +- hdr.timeout = DEF_TIMEOUT; ++ hdr.timeout = get_prio_timeout(DEF_TIMEOUT); + + if (ioctl(fd, SG_IO, &hdr) < 0) + return -RTPG_RTPG_FAILED; +Index: multipath-tools-130222/libmultipath/prioritizers/emc.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/emc.c ++++ multipath-tools-130222/libmultipath/prioritizers/emc.c +@@ -31,7 +31,7 @@ int emc_clariion_prio(const char *dev, i + io_hdr.dxferp = sense_buffer; + io_hdr.cmdp = inqCmdBlk; + io_hdr.sbp = sb; +- io_hdr.timeout = 60000; ++ io_hdr.timeout = get_prio_timeout(60000); + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_emc_log(0, "sending query command failed"); +Index: multipath-tools-130222/libmultipath/prioritizers/hds.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/hds.c ++++ multipath-tools-130222/libmultipath/prioritizers/hds.c +@@ -114,7 +114,7 @@ int hds_modular_prio (const char *dev, i + io_hdr.dxferp = inqBuff; + io_hdr.cmdp = inqCmdBlk; + io_hdr.sbp = sense_buffer; +- io_hdr.timeout = 2000; /* TimeOut = 2 seconds */ ++ io_hdr.timeout = get_prio_timeout(2000); /* TimeOut = 2 seconds */ + + if (ioctl (fd, SG_IO, &io_hdr) < 0) { + pp_hds_log(0, "SG_IO error"); +Index: multipath-tools-130222/libmultipath/prioritizers/hp_sw.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/hp_sw.c ++++ multipath-tools-130222/libmultipath/prioritizers/hp_sw.c +@@ -46,7 +46,7 @@ int hp_sw_prio(const char *dev, int fd) + io_hdr.dxfer_direction = SG_DXFER_NONE; + io_hdr.cmdp = turCmdBlk; + io_hdr.sbp = sb; +- io_hdr.timeout = 60000; ++ io_hdr.timeout = get_prio_timeout(60000); + io_hdr.pack_id = 0; + retry: + if (ioctl(fd, SG_IO, &io_hdr) < 0) { +Index: multipath-tools-130222/libmultipath/prioritizers/ontap.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/ontap.c ++++ multipath-tools-130222/libmultipath/prioritizers/ontap.c +@@ -89,7 +89,7 @@ static int send_gva(const char *dev, int + io_hdr.dxferp = results; + io_hdr.cmdp = cdb; + io_hdr.sbp = sb; +- io_hdr.timeout = SG_TIMEOUT; ++ io_hdr.timeout = get_prio_timeout(SG_TIMEOUT); + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_ontap_log(0, "SG_IO ioctl failed, errno=%d", errno); +@@ -141,7 +141,7 @@ static int get_proxy(const char *dev, in + io_hdr.dxferp = results; + io_hdr.cmdp = cdb; + io_hdr.sbp = sb; +- io_hdr.timeout = SG_TIMEOUT; ++ io_hdr.timeout = get_prio_timeout(SG_TIMEOUT); + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_ontap_log(0, "ioctl sending inquiry command failed, " +Index: multipath-tools-130222/libmultipath/prioritizers/rdac.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/rdac.c ++++ multipath-tools-130222/libmultipath/prioritizers/rdac.c +@@ -31,7 +31,7 @@ int rdac_prio(const char *dev, int fd) + io_hdr.dxferp = sense_buffer; + io_hdr.cmdp = inqCmdBlk; + io_hdr.sbp = sb; +- io_hdr.timeout = 60000; ++ io_hdr.timeout = get_prio_timeout(60000); + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_rdac_log(0, "sending inquiry command failed"); +Index: multipath-tools-130222/multipath.conf.annotated +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.annotated ++++ multipath-tools-130222/multipath.conf.annotated +@@ -188,8 +188,9 @@ + # # + # # name : checker_timeout + # # scope : multipath & multipathd +-# # desc : The timeout to use for path checkers that issue scsi +-# # commands with an explicit timeout, in seconds. ++# # desc : The timeout to use for path checkers and prioritizers ++# # that issue scsi commands with an explicit timeout, in ++# # seconds. + # # values : n > 0 + # # default : taken from /sys/block/sd/device/timeout + # checker_timeout 60 +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -321,8 +321,8 @@ maximum number of open fds is taken from + if that number is greated than 1024. + .TP + .B checker_timeout +-Specify the timeout to user for path checkers that issue scsi commands with an +-explicit timeout, in seconds; default taken from ++Specify the timeout to use for path checkers and prioritizers that issue scsi ++commands with an explicit timeout, in seconds; default taken from + .I /sys/block/sd/device/timeout + .TP + .B fast_io_fail_tmo diff --git a/SOURCES/0089-RHBZ-1110016-add-noasync-option.patch b/SOURCES/0089-RHBZ-1110016-add-noasync-option.patch new file mode 100644 index 0000000..2651c0e --- /dev/null +++ b/SOURCES/0089-RHBZ-1110016-add-noasync-option.patch @@ -0,0 +1,158 @@ +--- + libmultipath/config.c | 1 + + libmultipath/config.h | 1 + + libmultipath/dict.c | 33 +++++++++++++++++++++++++++++++++ + libmultipath/discovery.c | 8 ++++++-- + multipath.conf.annotated | 10 ++++++++++ + multipath/multipath.conf.5 | 9 +++++++++ + 6 files changed, 60 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -556,6 +556,7 @@ load_config (char * file, struct udev *u + conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER; + conf->detect_prio = DEFAULT_DETECT_PRIO; + conf->hw_strmatch = 0; ++ conf->force_sync = 0; + + /* + * preload default hwtable +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -115,6 +115,7 @@ struct config { + int reassign_maps; + int retain_hwhandler; + int detect_prio; ++ int force_sync; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -712,6 +712,29 @@ def_hw_strmatch_handler(vector strvec) + return 0; + } + ++static int ++def_force_sync_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->force_sync = 0; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ conf->force_sync = 1; ++ else ++ conf->force_sync = 0; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -2822,6 +2845,15 @@ snprint_def_hw_strmatch(char * buff, int + } + + static int ++snprint_def_force_sync(char * buff, int len, void * data) ++{ ++ if (conf->force_sync) ++ return snprintf(buff, len, "yes"); ++ else ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -2889,6 +2921,7 @@ init_keywords(void) + install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler_handler); + install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio); + install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch); ++ install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -952,8 +952,12 @@ get_state (struct path * pp, int daemon) + } + } + checker_clear_message(c); +- if (daemon) +- checker_set_async(c); ++ if (daemon) { ++ if (conf->force_sync == 0) ++ checker_set_async(c); ++ else ++ checker_set_sync(c); ++ } + if (!conf->checker_timeout && + (pp->bus != SYSFS_BUS_SCSI || + sysfs_get_timeout(pp, &(c->timeout)))) +Index: multipath-tools-130222/multipath.conf.annotated +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.annotated ++++ multipath-tools-130222/multipath.conf.annotated +@@ -214,6 +214,8 @@ + # # values : n > 0 + # # default : determined by the OS + # dev_loss_tmo 600 ++# ++# # + # # name : bindings_file + # # scope : multipath + # # desc : The location of the bindings file that is used with +@@ -222,6 +224,14 @@ + # # default : "/var/lib/multipath/bindings" + # bindings_file "/etc/multipath_bindings" + # ++# # ++# # name : force_sync ++# # scope : multipathd ++# # desc : If set to yes, multipath will run all of the checkers in ++# # sync mode, even if the checker has an async mode. ++# # values : yes|no ++# # default : no ++# force_sync yes + #} + # + ## +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -411,6 +411,15 @@ modify an existing config, or create a n + , the user device configs will be regular expression matched against the + built-in configs instead. Default is + .I no ++.TP ++.B force_sync ++If set to ++.I yes ++, multipathd will call the path checkers in sync mode only. This means that ++only one checker will run at a time. This is useful in the case where many ++multipathd checkers running in parallel causes significant CPU pressure. The ++Default is ++.I no + . + .SH "blacklist section" + The diff --git a/SOURCES/0090-UPBZ-1080038-reorder-paths-for-round-robin.patch b/SOURCES/0090-UPBZ-1080038-reorder-paths-for-round-robin.patch new file mode 100644 index 0000000..44f8407 --- /dev/null +++ b/SOURCES/0090-UPBZ-1080038-reorder-paths-for-round-robin.patch @@ -0,0 +1,529 @@ +--- + libmultipath/configure.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++ + libmultipath/configure.h | 2 + libmultipath/discovery.c | 87 +++++++++++++++++ + libmultipath/discovery.h | 2 + libmultipath/structs.c | 84 +++++++++++++++++ + libmultipath/structs.h | 25 ++++- + 6 files changed, 427 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -39,6 +39,219 @@ + #include "uxsock.h" + #include "wwids.h" + ++/* group paths in pg by host adapter ++ */ ++int group_by_host_adapter(struct pathgroup *pgp, vector adapters) ++{ ++ struct adapter_group *agp; ++ struct host_group *hgp; ++ struct path *pp, *pp1; ++ char adapter_name1[SLOT_NAME_SIZE]; ++ char adapter_name2[SLOT_NAME_SIZE]; ++ int i, j; ++ int found_hostgroup = 0; ++ ++ while (VECTOR_SIZE(pgp->paths) > 0) { ++ ++ pp = VECTOR_SLOT(pgp->paths, 0); ++ ++ if (sysfs_get_host_adapter_name(pp, adapter_name1)) ++ goto out; ++ /* create a new host adapter group ++ */ ++ agp = alloc_adaptergroup(); ++ if (!agp) ++ goto out; ++ agp->pgp = pgp; ++ ++ strncpy(agp->adapter_name, adapter_name1, SLOT_NAME_SIZE); ++ store_adaptergroup(adapters, agp); ++ ++ /* create a new host port group ++ */ ++ hgp = alloc_hostgroup(); ++ if (!hgp) ++ goto out; ++ if (store_hostgroup(agp->host_groups, hgp)) ++ goto out; ++ ++ hgp->host_no = pp->sg_id.host_no; ++ agp->num_hosts++; ++ if (store_path(hgp->paths, pp)) ++ goto out; ++ ++ hgp->num_paths++; ++ /* delete path from path group ++ */ ++ vector_del_slot(pgp->paths, 0); ++ ++ /* add all paths belonging to same host adapter ++ */ ++ vector_foreach_slot(pgp->paths, pp1, i) { ++ if (sysfs_get_host_adapter_name(pp1, adapter_name2)) ++ goto out; ++ if (strcmp(adapter_name1, adapter_name2) == 0) { ++ found_hostgroup = 0; ++ vector_foreach_slot(agp->host_groups, hgp, j) { ++ if (hgp->host_no == pp1->sg_id.host_no) { ++ if (store_path(hgp->paths, pp1)) ++ goto out; ++ hgp->num_paths++; ++ found_hostgroup = 1; ++ break; ++ } ++ } ++ if (!found_hostgroup) { ++ /* this path belongs to new host port ++ * within this adapter ++ */ ++ hgp = alloc_hostgroup(); ++ if (!hgp) ++ goto out; ++ ++ if (store_hostgroup(agp->host_groups, hgp)) ++ goto out; ++ ++ agp->num_hosts++; ++ if (store_path(hgp->paths, pp1)) ++ goto out; ++ ++ hgp->host_no = pp1->sg_id.host_no; ++ hgp->num_paths++; ++ } ++ /* delete paths from original path_group ++ * as they are added into adapter group now ++ */ ++ vector_del_slot(pgp->paths, i); ++ i--; ++ } ++ } ++ } ++ return 0; ++ ++out: /* add back paths into pg as re-ordering failed ++ */ ++ vector_foreach_slot(adapters, agp, i) { ++ vector_foreach_slot(agp->host_groups, hgp, j) { ++ while (VECTOR_SIZE(hgp->paths) > 0) { ++ pp = VECTOR_SLOT(hgp->paths, 0); ++ if (store_path(pgp->paths, pp)) ++ condlog(3, "failed to restore " ++ "path %s into path group", ++ pp->dev); ++ vector_del_slot(hgp->paths, 0); ++ } ++ } ++ } ++ free_adaptergroup(adapters); ++ return 1; ++} ++ ++/* re-order paths in pg by alternating adapters and host ports ++ * for optimized selection ++ */ ++int order_paths_in_pg_by_alt_adapters(struct pathgroup *pgp, vector adapters, ++ int total_paths) ++{ ++ int next_adapter_index = 0; ++ struct adapter_group *agp; ++ struct host_group *hgp; ++ struct path *pp; ++ ++ while (total_paths > 0) { ++ agp = VECTOR_SLOT(adapters, next_adapter_index); ++ if (!agp) { ++ condlog(0, "can't get adapter group %d", next_adapter_index); ++ return 1; ++ } ++ ++ hgp = VECTOR_SLOT(agp->host_groups, agp->next_host_index); ++ if (!hgp) { ++ condlog(0, "can't get host group %d of adapter group %d", next_adapter_index, agp->next_host_index); ++ return 1; ++ } ++ ++ if (!hgp->num_paths) { ++ agp->next_host_index++; ++ agp->next_host_index %= agp->num_hosts; ++ next_adapter_index++; ++ next_adapter_index %= VECTOR_SIZE(adapters); ++ continue; ++ } ++ ++ pp = VECTOR_SLOT(hgp->paths, 0); ++ ++ if (store_path(pgp->paths, pp)) ++ return 1; ++ ++ total_paths--; ++ ++ vector_del_slot(hgp->paths, 0); ++ ++ hgp->num_paths--; ++ ++ agp->next_host_index++; ++ agp->next_host_index %= agp->num_hosts; ++ next_adapter_index++; ++ next_adapter_index %= VECTOR_SIZE(adapters); ++ } ++ ++ /* all paths are added into path_group ++ * in crafted child order ++ */ ++ return 0; ++} ++ ++/* round-robin: order paths in path group to alternate ++ * between all host adapters ++ */ ++int rr_optimize_path_order(struct pathgroup *pgp) ++{ ++ vector adapters; ++ struct path *pp; ++ int total_paths; ++ int i; ++ ++ total_paths = VECTOR_SIZE(pgp->paths); ++ vector_foreach_slot(pgp->paths, pp, i) { ++ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP && ++ pp->sg_id.proto_id != SCSI_PROTOCOL_SAS && ++ pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI && ++ pp->sg_id.proto_id != SCSI_PROTOCOL_SRP) { ++ /* return success as default path order ++ * is maintained in path group ++ */ ++ return 0; ++ } ++ } ++ adapters = vector_alloc(); ++ if (!adapters) ++ return 0; ++ ++ /* group paths in path group by host adapters ++ */ ++ if (group_by_host_adapter(pgp, adapters)) { ++ /* already freed adapters */ ++ condlog(3, "Failed to group paths by adapters"); ++ return 0; ++ } ++ ++ /* re-order paths in pg to alternate between adapters and host ports ++ */ ++ if (order_paths_in_pg_by_alt_adapters(pgp, adapters, total_paths)) { ++ condlog(3, "Failed to re-order paths in pg by adapters " ++ "and host ports"); ++ free_adaptergroup(adapters); ++ /* return failure as original paths are ++ * removed form pgp ++ */ ++ return 1; ++ } ++ ++ free_adaptergroup(adapters); ++ return 0; ++} ++ + extern int + setup_map (struct multipath * mpp, char * params, int params_size) + { +@@ -101,6 +314,22 @@ setup_map (struct multipath * mpp, char + */ + mpp->bestpg = select_path_group(mpp); + ++ /* re-order paths in all path groups in an optimized way ++ * for round-robin path selectors to get maximum throughput. ++ */ ++ if (!strncmp(mpp->selector, "round-robin", 11)) { ++ vector_foreach_slot(mpp->pg, pgp, i) { ++ if (VECTOR_SIZE(pgp->paths) <= 2) ++ continue; ++ if (rr_optimize_path_order(pgp)) { ++ condlog(2, "cannot re-order paths for " ++ "optimization: %s", ++ mpp->alias); ++ return 1; ++ } ++ } ++ } ++ + /* + * transform the mp->pg vector of vectors of paths + * into a mp->params strings to feed the device-mapper +Index: multipath-tools-130222/libmultipath/configure.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.h ++++ multipath-tools-130222/libmultipath/configure.h +@@ -29,4 +29,4 @@ int reinstate_paths (struct multipath *m + int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload); + int get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid); + int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh); +- ++int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name); +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -310,6 +310,93 @@ sysfs_get_tgt_nodename (struct path *pp, + return 1; + } + ++int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name) ++{ ++ int proto_id; ++ ++ if (!pp || !adapter_name) ++ return 1; ++ ++ proto_id = pp->sg_id.proto_id; ++ ++ if (proto_id != SCSI_PROTOCOL_FCP && ++ proto_id != SCSI_PROTOCOL_SAS && ++ proto_id != SCSI_PROTOCOL_ISCSI && ++ proto_id != SCSI_PROTOCOL_SRP) { ++ return 1; ++ } ++ /* iscsi doesn't have adapter info in sysfs ++ * get ip_address for grouping paths ++ */ ++ if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI) ++ return sysfs_get_iscsi_ip_address(pp, adapter_name); ++ ++ /* fetch adapter pci name for other protocols ++ */ ++ return sysfs_get_host_pci_name(pp, adapter_name); ++} ++ ++int sysfs_get_host_pci_name(struct path *pp, char *pci_name) ++{ ++ struct udev_device *hostdev, *parent; ++ char host_name[HOST_NAME_LEN]; ++ const char *driver_name, *value; ++ ++ if (!pp || !pci_name) ++ return 1; ++ ++ sprintf(host_name, "host%d", pp->sg_id.host_no); ++ hostdev = udev_device_new_from_subsystem_sysname(conf->udev, ++ "scsi_host", host_name); ++ if (!hostdev) ++ return 1; ++ ++ parent = udev_device_get_parent(hostdev); ++ while (parent) { ++ driver_name = udev_device_get_driver(parent); ++ if (!driver_name) { ++ parent = udev_device_get_parent(parent); ++ continue; ++ } ++ if (!strcmp(driver_name, "pcieport")) ++ break; ++ parent = udev_device_get_parent(parent); ++ } ++ if (parent) { ++ /* pci_device found ++ */ ++ value = udev_device_get_sysname(parent); ++ ++ strncpy(pci_name, value, SLOT_NAME_SIZE); ++ udev_device_unref(hostdev); ++ return 0; ++ } ++ udev_device_unref(hostdev); ++ return 1; ++} ++ ++int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address) ++{ ++ struct udev_device *hostdev; ++ char host_name[HOST_NAME_LEN]; ++ const char *value; ++ ++ sprintf(host_name, "host%d", pp->sg_id.host_no); ++ hostdev = udev_device_new_from_subsystem_sysname(conf->udev, ++ "iscsi_host", host_name); ++ if (hostdev) { ++ value = udev_device_get_sysattr_value(hostdev, ++ "ipaddress"); ++ if (value) { ++ strncpy(ip_address, value, SLOT_NAME_SIZE); ++ udev_device_unref(hostdev); ++ return 0; ++ } else ++ udev_device_unref(hostdev); ++ } ++ return 1; ++} ++ + static void + sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp) + { +Index: multipath-tools-130222/libmultipath/discovery.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.h ++++ multipath-tools-130222/libmultipath/discovery.h +@@ -38,6 +38,8 @@ int store_pathinfo (vector pathvec, vect + struct path **pp_ptr); + int sysfs_set_scsi_tmo (struct multipath *mpp); + int sysfs_get_timeout(struct path *pp, unsigned int *timeout); ++int sysfs_get_host_pci_name(struct path *pp, char *pci_name); ++int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address); + + /* + * discovery bitmask +Index: multipath-tools-130222/libmultipath/structs.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.c ++++ multipath-tools-130222/libmultipath/structs.c +@@ -18,6 +18,70 @@ + #include "blacklist.h" + #include "prio.h" + ++struct adapter_group * ++alloc_adaptergroup(void) ++{ ++ struct adapter_group *agp; ++ ++ agp = (struct adapter_group *)MALLOC(sizeof(struct adapter_group)); ++ ++ if (!agp) ++ return NULL; ++ ++ agp->host_groups = vector_alloc(); ++ if (!agp->host_groups) { ++ FREE(agp); ++ agp = NULL; ++ } ++ return agp; ++} ++ ++void free_adaptergroup(vector adapters) ++{ ++ int i; ++ struct adapter_group *agp; ++ ++ vector_foreach_slot(adapters, agp, i) { ++ free_hostgroup(agp->host_groups); ++ FREE(agp); ++ } ++ vector_free(adapters); ++} ++ ++void free_hostgroup(vector hostgroups) ++{ ++ int i; ++ struct host_group *hgp; ++ ++ if (!hostgroups) ++ return; ++ ++ vector_foreach_slot(hostgroups, hgp, i) { ++ vector_free(hgp->paths); ++ FREE(hgp); ++ } ++ vector_free(hostgroups); ++} ++ ++struct host_group * ++alloc_hostgroup(void) ++{ ++ struct host_group *hgp; ++ ++ hgp = (struct host_group *)MALLOC(sizeof(struct host_group)); ++ ++ if (!hgp) ++ return NULL; ++ ++ hgp->paths = vector_alloc(); ++ ++ if (!hgp->paths) { ++ FREE(hgp); ++ hgp = NULL; ++ } ++ return hgp; ++} ++ + struct path * + alloc_path (void) + { +@@ -242,6 +306,26 @@ store_pathgroup (vector pgvec, struct pa + return 0; + } + ++int ++store_hostgroup(vector hostgroupvec, struct host_group * hgp) ++{ ++ if (!vector_alloc_slot(hostgroupvec)) ++ return 1; ++ ++ vector_set_slot(hostgroupvec, hgp); ++ return 0; ++} ++ ++int ++store_adaptergroup(vector adapters, struct adapter_group * agp) ++{ ++ if (!vector_alloc_slot(adapters)) ++ return 1; ++ ++ vector_set_slot(adapters, agp); ++ return 0; ++} ++ + struct multipath * + find_mp_by_minor (vector mpvec, int minor) + { +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -15,7 +15,8 @@ + #define BLK_DEV_SIZE 33 + #define PATH_SIZE 512 + #define NAME_SIZE 512 +- ++#define HOST_NAME_LEN 8 ++#define SLOT_NAME_SIZE 40 + + #define SCSI_VENDOR_SIZE 9 + #define SCSI_PRODUCT_SIZE 17 +@@ -251,6 +252,20 @@ struct pathgroup { + char * selector; + }; + ++struct adapter_group { ++ char adapter_name[SLOT_NAME_SIZE]; ++ struct pathgroup *pgp; ++ int num_hosts; ++ vector host_groups; ++ int next_host_index; ++}; ++ ++struct host_group { ++ int host_no; ++ int num_paths; ++ vector paths; ++}; ++ + struct path * alloc_path (void); + struct pathgroup * alloc_pathgroup (void); + struct multipath * alloc_multipath (void); +@@ -263,6 +278,14 @@ void free_multipath_attributes (struct m + void drop_multipath (vector mpvec, char * wwid, enum free_path_mode free_paths); + void free_multipathvec (vector mpvec, enum free_path_mode free_paths); + ++struct adapter_group * alloc_adaptergroup(void); ++struct host_group * alloc_hostgroup(void); ++void free_adaptergroup(vector adapters); ++void free_hostgroup(vector hostgroups); ++ ++int store_adaptergroup(vector adapters, struct adapter_group *agp); ++int store_hostgroup(vector hostgroupvec, struct host_group *hgp); ++ + int store_path (vector pathvec, struct path * pp); + int store_pathgroup (vector pgvec, struct pathgroup * pgp); + diff --git a/SOURCES/0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch b/SOURCES/0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch new file mode 100644 index 0000000..d164de1 --- /dev/null +++ b/SOURCES/0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch @@ -0,0 +1,38 @@ +--- + libmultipath/dict.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -43,6 +43,9 @@ def_fast_io_fail_handler(vector strvec) + char * buff; + + buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ + if (strlen(buff) == 3 && !strcmp(buff, "off")) + conf->fast_io_fail = MP_FAST_IO_FAIL_OFF; + else if (sscanf(buff, "%d", &conf->fast_io_fail) != 1 || +@@ -1002,6 +1005,9 @@ hw_dev_loss_handler(vector strvec) + char * buff; + struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); + ++ if (!hwe) ++ return 1; ++ + buff = set_value(strvec); + if (!buff) + return 1; +@@ -1021,6 +1027,9 @@ hw_pgpolicy_handler(vector strvec) + char * buff; + struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); + ++ if (!hwe) ++ return 1; ++ + buff = set_value(strvec); + + if (!buff) diff --git a/SOURCES/0092-UPBZ-1104605-reload-on-rename.patch b/SOURCES/0092-UPBZ-1104605-reload-on-rename.patch new file mode 100644 index 0000000..465257c --- /dev/null +++ b/SOURCES/0092-UPBZ-1104605-reload-on-rename.patch @@ -0,0 +1,63 @@ +--- + libmultipath/configure.c | 11 +++++++++++ + libmultipath/configure.h | 1 + + libmultipath/devmapper.c | 3 +-- + 3 files changed, 13 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -394,6 +394,8 @@ select_action (struct multipath * mpp, v + cmpp->alias, mpp->alias); + strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE); + mpp->action = ACT_RENAME; ++ if (force_reload) ++ mpp->action = ACT_RENAME2; + return; + } + mpp->action = ACT_CREATE; +@@ -632,6 +634,15 @@ domap (struct multipath * mpp, char * pa + r = dm_rename(mpp->alias_old, mpp->alias); + break; + ++ case ACT_RENAME2: ++ r = dm_rename(mpp->alias_old, mpp->alias); ++ if (r) { ++ r = dm_addmap_reload(mpp, params); ++ if (r) ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, MPATH_UDEV_RELOAD_FLAG); ++ } ++ break; ++ + default: + break; + } +Index: multipath-tools-130222/libmultipath/configure.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.h ++++ multipath-tools-130222/libmultipath/configure.h +@@ -18,6 +18,7 @@ enum actions { + ACT_RENAME, + ACT_CREATE, + ACT_RESIZE, ++ ACT_RENAME2, + }; + + #define FLUSH_ONE 1 +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -565,10 +565,9 @@ dm_dev_t (const char * mapname, char * d + if (!dm_task_run(dmt)) + goto out; + +- if (!dm_task_get_info(dmt, &info)) ++ if (!dm_task_get_info(dmt, &info) || !info.exists) + goto out; + +- r = info.open_count; + if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len) + goto out; + diff --git a/SOURCES/0093-UPBZ-1086825-user-friendly-name-remap.patch b/SOURCES/0093-UPBZ-1086825-user-friendly-name-remap.patch new file mode 100644 index 0000000..ab5abbd --- /dev/null +++ b/SOURCES/0093-UPBZ-1086825-user-friendly-name-remap.patch @@ -0,0 +1,199 @@ +--- + libmultipath/alias.c | 64 ++++++++++++++++++++++++++++++++++++++++++--- + libmultipath/alias.h | 2 + + libmultipath/propsel.c | 32 +++++++++++++++------- + libmultipath/structs_vec.c | 15 ++++++++++ + 4 files changed, 100 insertions(+), 13 deletions(-) + +Index: multipath-tools-130222/libmultipath/alias.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.c ++++ multipath-tools-130222/libmultipath/alias.c +@@ -145,7 +145,7 @@ lookup_binding(FILE *f, char *map_wwid, + } + + static int +-rlookup_binding(FILE *f, char *buff, char *map_alias) ++rlookup_binding(FILE *f, char *buff, char *map_alias, char *prefix) + { + char line[LINE_MAX]; + unsigned int line_nr = 0; +@@ -164,7 +164,7 @@ rlookup_binding(FILE *f, char *buff, cha + alias = strtok(line, " \t"); + if (!alias) /* blank line */ + continue; +- curr_id = scan_devname(alias, NULL); /* TBD: Why this call? */ ++ curr_id = scan_devname(alias, prefix); + if (curr_id >= id) + id = curr_id + 1; + wwid = strtok(NULL, " \t"); +@@ -188,6 +188,11 @@ rlookup_binding(FILE *f, char *buff, cha + } + } + condlog(3, "No matching alias [%s] in bindings file.", map_alias); ++ ++ /* Get the theoretical id for this map alias. ++ * Used by use_existing_alias ++ */ ++ id = scan_devname(map_alias, prefix); + return id; + } + +@@ -237,6 +242,59 @@ allocate_binding(int fd, char *wwid, int + } + + char * ++use_existing_alias (char *wwid, char *file, char *alias_old, ++ char *prefix, int bindings_read_only) ++{ ++ char *alias = NULL; ++ int id = 0; ++ int fd, can_write; ++ char buff[WWID_SIZE]; ++ FILE *f; ++ ++ fd = open_file(file, &can_write, BINDINGS_FILE_HEADER); ++ if (fd < 0) ++ return NULL; ++ ++ f = fdopen(fd, "r"); ++ if (!f) { ++ condlog(0, "cannot fdopen on bindings file descriptor"); ++ close(fd); ++ return NULL; ++ } ++ /* lookup the binding. if it exsists, the wwid will be in buff ++ * either way, id contains the id for the alias ++ */ ++ id = rlookup_binding(f , buff, alias_old, prefix); ++ if (id < 0) ++ goto out; ++ ++ if (strlen(buff) > 0) { ++ /* if buff is our wwid, it's already ++ * allocated correctly ++ */ ++ if (strcmp(buff, wwid) == 0) ++ alias = STRDUP(alias_old); ++ else { ++ alias = NULL; ++ condlog(0, "alias %s already bound to wwid %s, cannot reuse", ++ alias_old, buff); ++ } ++ goto out; ++ } ++ ++ /* allocate the existing alias in the bindings file */ ++ if (can_write && id && !bindings_read_only) { ++ alias = allocate_binding(fd, wwid, id, prefix); ++ condlog(0, "Allocated existing binding [%s] for WWID [%s]", ++ alias, wwid); ++ } ++ ++out: ++ fclose(f); ++ return alias; ++} ++ ++char * + get_user_friendly_alias(char *wwid, char *file, char *prefix, + int bindings_read_only) + { +@@ -305,7 +363,7 @@ get_user_friendly_wwid(char *alias, char + return -1; + } + +- rlookup_binding(f, buff, alias); ++ rlookup_binding(f, buff, alias, NULL); + if (!strlen(buff)) { + fclose(f); + return -1; +Index: multipath-tools-130222/libmultipath/alias.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.h ++++ multipath-tools-130222/libmultipath/alias.h +@@ -10,3 +10,5 @@ + char *get_user_friendly_alias(char *wwid, char *file, char *prefix, + int bindings_readonly); + int get_user_friendly_wwid(char *alias, char *buff, char *file); ++char *use_existing_alias (char *wwid, char *file, char *alias_old, ++ char *prefix, int bindings_read_only); +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -253,19 +253,31 @@ want_user_friendly_names(struct multipat + extern int + select_alias (struct multipath * mp) + { +- if (mp->mpe && mp->mpe->alias) ++ if (mp->mpe && mp->mpe->alias) { + mp->alias = STRDUP(mp->mpe->alias); +- else { +- mp->alias = NULL; +- if (want_user_friendly_names(mp)) { +- select_alias_prefix(mp); +- mp->alias = get_user_friendly_alias(mp->wwid, +- conf->bindings_file, mp->alias_prefix, conf->bindings_read_only); +- } +- if (mp->alias == NULL) +- mp->alias = STRDUP(mp->wwid); ++ goto out; + } + ++ mp->alias = NULL; ++ if (!want_user_friendly_names(mp)) ++ goto out; ++ ++ select_alias_prefix(mp); ++ ++ if (strlen(mp->alias_old) > 0) { ++ mp->alias = use_existing_alias(mp->wwid, conf->bindings_file, ++ mp->alias_old, mp->alias_prefix, ++ conf->bindings_read_only); ++ memset (mp->alias_old, 0, WWID_SIZE); ++ } ++ ++ if (mp->alias == NULL) ++ mp->alias = get_user_friendly_alias(mp->wwid, ++ conf->bindings_file, mp->alias_prefix, conf->bindings_read_only); ++out: ++ if (mp->alias == NULL) ++ mp->alias = STRDUP(mp->wwid); ++ + return mp->alias ? 0 : 1; + } + +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -430,6 +430,20 @@ out: + return NULL; + } + ++static void ++find_existing_alias (struct multipath * mpp, ++ struct vectors *vecs) ++{ ++ struct multipath * mp; ++ int i; ++ ++ vector_foreach_slot (vecs->mpvec, mp, i) ++ if (strcmp(mp->wwid, mpp->wwid) == 0) { ++ strncpy(mpp->alias_old, mp->alias, WWID_SIZE); ++ return; ++ } ++} ++ + extern struct multipath * + add_map_with_path (struct vectors * vecs, + struct path * pp, int add_vec) +@@ -443,6 +457,7 @@ add_map_with_path (struct vectors * vecs + mpp->hwe = pp->hwe; + + strcpy(mpp->wwid, pp->wwid); ++ find_existing_alias(mpp, vecs); + if (select_alias(mpp)) + goto out; + mpp->size = pp->size; diff --git a/SOURCES/0094-RHBZ-1086825-cleanup-remap.patch b/SOURCES/0094-RHBZ-1086825-cleanup-remap.patch new file mode 100644 index 0000000..7d85c2d --- /dev/null +++ b/SOURCES/0094-RHBZ-1086825-cleanup-remap.patch @@ -0,0 +1,107 @@ +--- + libmultipath/alias.c | 31 +++++++++++++++---------------- + libmultipath/propsel.c | 4 ++-- + 2 files changed, 17 insertions(+), 18 deletions(-) + +Index: multipath-tools-130222/libmultipath/alias.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.c ++++ multipath-tools-130222/libmultipath/alias.c +@@ -149,13 +149,11 @@ rlookup_binding(FILE *f, char *buff, cha + { + char line[LINE_MAX]; + unsigned int line_nr = 0; +- int id = 0; + + buff[0] = '\0'; + + while (fgets(line, LINE_MAX, f)) { + char *c, *alias, *wwid; +- int curr_id; + + line_nr++; + c = strpbrk(line, "#\n\r"); +@@ -164,9 +162,6 @@ rlookup_binding(FILE *f, char *buff, cha + alias = strtok(line, " \t"); + if (!alias) /* blank line */ + continue; +- curr_id = scan_devname(alias, prefix); +- if (curr_id >= id) +- id = curr_id + 1; + wwid = strtok(NULL, " \t"); + if (!wwid){ + condlog(3, +@@ -184,16 +179,12 @@ rlookup_binding(FILE *f, char *buff, cha + "\nSetting wwid to %s", alias, wwid); + strncpy(buff, wwid, WWID_SIZE); + buff[WWID_SIZE - 1] = '\0'; +- return id; ++ return 0; + } + } + condlog(3, "No matching alias [%s] in bindings file.", map_alias); + +- /* Get the theoretical id for this map alias. +- * Used by use_existing_alias +- */ +- id = scan_devname(map_alias, prefix); +- return id; ++ return -1; + } + + static char * +@@ -264,9 +255,7 @@ use_existing_alias (char *wwid, char *fi + /* lookup the binding. if it exsists, the wwid will be in buff + * either way, id contains the id for the alias + */ +- id = rlookup_binding(f , buff, alias_old, prefix); +- if (id < 0) +- goto out; ++ rlookup_binding(f, buff, alias_old, prefix); + + if (strlen(buff) > 0) { + /* if buff is our wwid, it's already +@@ -279,11 +268,21 @@ use_existing_alias (char *wwid, char *fi + condlog(0, "alias %s already bound to wwid %s, cannot reuse", + alias_old, buff); + } +- goto out; ++ goto out; + } + + /* allocate the existing alias in the bindings file */ +- if (can_write && id && !bindings_read_only) { ++ id = scan_devname(alias_old, prefix); ++ if (id <= 0) ++ goto out; ++ ++ if (fflush(f) != 0) { ++ condlog(0, "cannot fflush bindings file stream : %s", ++ strerror(errno)); ++ goto out; ++ } ++ ++ if (can_write && !bindings_read_only) { + alias = allocate_binding(fd, wwid, id, prefix); + condlog(0, "Allocated existing binding [%s] for WWID [%s]", + alias, wwid); +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -263,13 +263,13 @@ select_alias (struct multipath * mp) + goto out; + + select_alias_prefix(mp); +- ++ + if (strlen(mp->alias_old) > 0) { + mp->alias = use_existing_alias(mp->wwid, conf->bindings_file, + mp->alias_old, mp->alias_prefix, + conf->bindings_read_only); + memset (mp->alias_old, 0, WWID_SIZE); +- } ++ } + + if (mp->alias == NULL) + mp->alias = get_user_friendly_alias(mp->wwid, diff --git a/SOURCES/0095-RHBZ-1127944-xtremIO-config.patch b/SOURCES/0095-RHBZ-1127944-xtremIO-config.patch new file mode 100644 index 0000000..6807cbc --- /dev/null +++ b/SOURCES/0095-RHBZ-1127944-xtremIO-config.patch @@ -0,0 +1,28 @@ +--- + libmultipath/hwtable.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1121,6 +1121,19 @@ static struct hwentry default_hw[] = { + .prio_name = PRIO_ALUA, + .prio_args = NULL, + }, ++ { ++ .vendor = "XtremIO", ++ .product = "XtremApp", ++ .features = DEFAULT_FEATURES, ++ .hwhandler = DEFAULT_HWHANDLER, ++ .selector = "queue-length 0", ++ .pgpolicy = MULTIBUS, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .checker_name = DIRECTIO, ++ .fast_io_fail = 15, ++ .prio_name = DEFAULT_PRIO, ++ .prio_args = NULL, ++ }, + /* + * EOL + */ diff --git a/SOURCES/0096-RHBZ-979474-new-wildcards.patch b/SOURCES/0096-RHBZ-979474-new-wildcards.patch new file mode 100644 index 0000000..9025efe --- /dev/null +++ b/SOURCES/0096-RHBZ-979474-new-wildcards.patch @@ -0,0 +1,120 @@ +--- + libmultipath/print.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 83 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "checkers.h" + #include "vector.h" +@@ -44,7 +45,7 @@ + * information printing helpers + */ + static int +-snprint_str (char * buff, size_t len, char * str) ++snprint_str (char * buff, size_t len, const char * str) + { + return snprintf(buff, len, "%s", str); + } +@@ -432,6 +433,83 @@ snprint_path_mpp (char * buff, size_t le + } + + static int ++snprint_host_attr (char * buff, size_t len, struct path * pp, char *attr) ++{ ++ struct udev_device *host_dev = NULL; ++ char host_id[32]; ++ const char *value = NULL; ++ int ret; ++ ++ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) ++ return snprintf(buff, len, "[undef]"); ++ sprintf(host_id, "host%d", pp->sg_id.host_no); ++ host_dev = udev_device_new_from_subsystem_sysname(conf->udev, "fc_host", ++ host_id); ++ if (!host_dev) { ++ condlog(1, "%s: No fc_host device for '%s'", pp->dev, host_id); ++ goto out; ++ } ++ value = udev_device_get_sysattr_value(host_dev, attr); ++ if (value) ++ ret = snprint_str(buff, len, value); ++ udev_device_unref(host_dev); ++out: ++ if (!value) ++ ret = snprintf(buff, len, "[unknown]"); ++ return ret; ++} ++ ++static int ++snprint_host_wwnn (char * buff, size_t len, struct path * pp) ++{ ++ return snprint_host_attr(buff, len, pp, "node_name"); ++} ++ ++static int ++snprint_host_wwpn (char * buff, size_t len, struct path * pp) ++{ ++ return snprint_host_attr(buff, len, pp, "port_name"); ++} ++ ++static int ++snprint_tgt_wwpn (char * buff, size_t len, struct path * pp) ++{ ++ struct udev_device *rport_dev = NULL; ++ char rport_id[32]; ++ const char *value = NULL; ++ int ret; ++ ++ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) ++ return snprintf(buff, len, "[undef]"); ++ sprintf(rport_id, "rport-%d:%d-%d", ++ pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); ++ rport_dev = udev_device_new_from_subsystem_sysname(conf->udev, ++ "fc_remote_ports", rport_id); ++ if (!rport_dev) { ++ condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev, ++ rport_id); ++ goto out; ++ } ++ value = udev_device_get_sysattr_value(rport_dev, "port_name"); ++ if (value) ++ ret = snprint_str(buff, len, value); ++ udev_device_unref(rport_dev); ++out: ++ if (!value) ++ ret = snprintf(buff, len, "[unknown]"); ++ return ret; ++} ++ ++ ++static int ++snprint_tgt_wwnn (char * buff, size_t len, struct path * pp) ++{ ++ if (pp->tgt_node_name[0] == '\0') ++ return snprintf(buff, len, "[undef]"); ++ return snprint_str(buff, len, pp->tgt_node_name); ++} ++ ++static int + snprint_path_checker (char * buff, size_t len, struct path * pp) + { + struct checker * c = &pp->checker; +@@ -475,6 +553,10 @@ struct path_data pd[] = { + {'S', "size", 0, snprint_path_size}, + {'z', "serial", 0, snprint_path_serial}, + {'m', "multipath", 0, snprint_path_mpp}, ++ {'N', "host WWNN", 0, snprint_host_wwnn}, ++ {'n', "target WWNN", 0, snprint_tgt_wwnn}, ++ {'R', "host WWPN", 0, snprint_host_wwpn}, ++ {'r', "target WWPN", 0, snprint_tgt_wwpn}, + {0, NULL, 0 , NULL} + }; + diff --git a/SOURCES/0097-RH-fix-coverity-errors.patch b/SOURCES/0097-RH-fix-coverity-errors.patch new file mode 100644 index 0000000..8ce0e87 --- /dev/null +++ b/SOURCES/0097-RH-fix-coverity-errors.patch @@ -0,0 +1,158 @@ +--- + kpartx/devmapper.c | 3 ++- + libmultipath/alias.c | 1 + + libmultipath/blacklist.c | 7 +++++++ + libmultipath/prioritizers/iet.c | 2 ++ + libmultipath/prioritizers/weightedpath.c | 5 ++++- + libmultipath/regex.c | 5 ++++- + libmultipath/sysfs.c | 3 ++- + libmultipath/util.c | 2 +- + 8 files changed, 23 insertions(+), 5 deletions(-) + +Index: multipath-tools-130222/kpartx/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.c ++++ multipath-tools-130222/kpartx/devmapper.c +@@ -132,8 +132,9 @@ dm_addmap (int task, const char *name, c + goto addout; + r = dm_task_run (dmt); + +- addout: ++addout: + dm_task_destroy (dmt); ++ free(prefixed_uuid); + + return r; + } +Index: multipath-tools-130222/libmultipath/alias.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.c ++++ multipath-tools-130222/libmultipath/alias.c +@@ -328,6 +328,7 @@ get_user_friendly_alias(char *wwid, char + if (fflush(f) != 0) { + condlog(0, "cannot fflush bindings file stream : %s", + strerror(errno)); ++ free(alias); + fclose(f); + return NULL; + } +Index: multipath-tools-130222/libmultipath/blacklist.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/blacklist.c ++++ multipath-tools-130222/libmultipath/blacklist.c +@@ -79,6 +79,8 @@ set_ble_device (vector blist, char * ven + if (regcomp(&ble->vendor_reg, vendor, + REG_EXTENDED|REG_NOSUB)) { + FREE(vendor); ++ if (product) ++ FREE(product); + return 1; + } + ble->vendor = vendor; +@@ -87,6 +89,10 @@ set_ble_device (vector blist, char * ven + if (regcomp(&ble->product_reg, product, + REG_EXTENDED|REG_NOSUB)) { + FREE(product); ++ if (vendor) { ++ ble->vendor = NULL; ++ FREE(vendor); ++ } + return 1; + } + ble->product = product; +@@ -189,6 +195,7 @@ setup_default_blist (struct config * con + STRDUP(hwe->bl_product), + ORIGIN_DEFAULT)) { + FREE(ble); ++ vector_del_slot(conf->blist_device, VECTOR_SIZE(conf->blist_device) - 1); + return 1; + } + } +Index: multipath-tools-130222/libmultipath/prioritizers/iet.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/iet.c ++++ multipath-tools-130222/libmultipath/prioritizers/iet.c +@@ -109,6 +109,7 @@ int iet_prio(const char *dev, char * arg + ssize_t nchars = readlink(path, buffer, sizeof(buffer)-1); + if (nchars != -1) { + char *device; ++ buffer[nchars] = '\0'; + device = find_regex(buffer,"(sd[a-z]+)"); + // if device parsed is the right one + if (device!=NULL && strncmp(device, dev, strlen(device)) == 0) { +@@ -118,6 +119,7 @@ int iet_prio(const char *dev, char * arg + if (ip!=NULL && strncmp(ip, preferredip, strlen(ip)) == 0) { + // high prio + free(ip); ++ free(device); + closedir(dir_p); + return 20; + } +Index: multipath-tools-130222/libmultipath/prioritizers/weightedpath.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/weightedpath.c ++++ multipath-tools-130222/libmultipath/prioritizers/weightedpath.c +@@ -61,8 +61,10 @@ int prio_path_weight(struct path *pp, ch + regex = get_next_string(&temp, split_char); + + /* Return default priority if the argument is not parseable */ +- if (!regex) ++ if (!regex) { ++ FREE(arg); + return priority; ++ } + + if (!strcmp(regex, HBTL)) { + sprintf(path, "%d:%d:%d:%d", pp->sg_id.host_no, +@@ -72,6 +74,7 @@ int prio_path_weight(struct path *pp, ch + } else { + condlog(0, "%s: %s - Invalid arguments", pp->dev, + pp->prio.name); ++ FREE(arg); + return priority; + } + +Index: multipath-tools-130222/libmultipath/regex.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/regex.c ++++ multipath-tools-130222/libmultipath/regex.c +@@ -3936,8 +3936,11 @@ int eflags; + regs.num_regs = nmatch; + regs.start = TALLOC(nmatch, regoff_t); + regs.end = TALLOC(nmatch, regoff_t); +- if (regs.start == NULL || regs.end == NULL) ++ if (regs.start == NULL || regs.end == NULL) { ++ free(regs.start); ++ free(regs.end); + return (int) REG_NOMATCH; ++ } + } + + /* Perform the searching operation. */ +Index: multipath-tools-130222/libmultipath/sysfs.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/sysfs.c ++++ multipath-tools-130222/libmultipath/sysfs.c +@@ -88,7 +88,8 @@ ssize_t sysfs_attr_get_value(struct udev + } else if (size == value_len) { + condlog(4, "overflow while reading from %s", devpath); + size = 0; +- } ++ } else ++ value[size] = '\0'; + + close(fd); + return size; +Index: multipath-tools-130222/libmultipath/util.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/util.c ++++ multipath-tools-130222/libmultipath/util.c +@@ -175,7 +175,7 @@ devt2devname (char *devname, int devname + sprintf(block_path,"/sys/dev/block/%u:%u", major, minor); + if (lstat(block_path, &statbuf) == 0) { + if (S_ISLNK(statbuf.st_mode) && +- readlink(block_path, dev, FILE_NAME_SIZE) > 0) { ++ readlink(block_path, dev, FILE_NAME_SIZE-1) > 0) { + char *p = strrchr(dev, '/'); + + if (!p) { diff --git a/SOURCES/0098-UPBZ-1067171-mutipath-i.patch b/SOURCES/0098-UPBZ-1067171-mutipath-i.patch new file mode 100644 index 0000000..cf41863 --- /dev/null +++ b/SOURCES/0098-UPBZ-1067171-mutipath-i.patch @@ -0,0 +1,332 @@ +--- + libmultipath/config.h | 15 ++++++++- + libmultipath/configure.c | 2 - + libmultipath/discovery.c | 5 +-- + multipath/main.c | 75 +++++++++++++++++++++++++---------------------- + multipath/multipath.8 | 5 ++- + 5 files changed, 61 insertions(+), 41 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -23,6 +23,17 @@ enum devtypes { + DEV_DEVMAP + }; + ++enum mpath_cmds { ++ CMD_CREATE, ++ CMD_DRY_RUN, ++ CMD_LIST_SHORT, ++ CMD_LIST_LONG, ++ CMD_VALID_PATH, ++ CMD_REMOVE_WWID, ++ CMD_RESET_WWIDS, ++ CMD_ADD_WWID, ++}; ++ + struct hwentry { + char * vendor; + char * product; +@@ -79,8 +90,7 @@ struct mpentry { + + struct config { + int verbosity; +- int dry_run; +- int list; ++ enum mpath_cmds cmd; + int pgpolicy_flag; + int pgpolicy; + enum devtypes dev_type; +@@ -98,6 +108,7 @@ struct config { + int max_fds; + int force_reload; + int queue_without_daemon; ++ int ignore_wwids; + int checker_timeout; + int daemon; + int flush_on_last_del; +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -85,7 +85,7 @@ usage (char * progname) + { + fprintf (stderr, VERSION_STRING); + fprintf (stderr, "Usage:\n"); +- fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-T tm:val] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); ++ fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-T tm:val] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); + fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); + fprintf (stderr, " %s -F [-v lvl]\n", progname); + fprintf (stderr, " %s -t\n", progname); +@@ -109,6 +109,7 @@ usage (char * progname) + " -d dry run, do not create or update devmaps\n" \ + " -t dump internal hardware table\n" \ + " -r force devmap reload\n" \ ++ " -i ignore wwids file\n" \ + " -B treat the bindings file as read only\n" \ + " -p policy failover|multibus|group_by_serial|group_by_prio\n" \ + " -b fil bindings file location\n" \ +@@ -209,18 +210,19 @@ get_dm_mpvec (vector curmp, vector pathv + * If not in "fast list mode", we need to fetch information + * about them + */ +- if (conf->list != 1) ++ if (conf->cmd != CMD_LIST_SHORT) + update_paths(mpp); + +- if (conf->list > 1) ++ if (conf->cmd == CMD_LIST_LONG) + mpp->bestpg = select_path_group(mpp); + + disassemble_status(status, mpp); + +- if (conf->list) ++ if (conf->cmd == CMD_LIST_SHORT || ++ conf->cmd == CMD_LIST_LONG) + print_multipath_topology(mpp, conf->verbosity); + +- if (!conf->dry_run) ++ if (conf->cmd == CMD_CREATE) + reinstate_paths(mpp); + } + return 0; +@@ -262,10 +264,11 @@ configure (void) + /* + * if we have a blacklisted device parameter, exit early + */ +- if (dev && conf->dev_type == DEV_DEVNODE && conf->dry_run != 3 && ++ if (dev && conf->dev_type == DEV_DEVNODE && ++ conf->cmd != CMD_REMOVE_WWID && + (filter_devnode(conf->blist_devnode, + conf->elist_devnode, dev) > 0)) { +- if (conf->dry_run == 2) ++ if (conf->cmd == CMD_VALID_PATH) + printf("%s is not a valid multipath device path\n", + conf->dev); + goto out; +@@ -278,13 +281,13 @@ configure (void) + int failed = get_refwwid(conf->dev, conf->dev_type, pathvec, + &refwwid); + if (!refwwid) { +- if (failed == 2 && conf->dry_run == 2) ++ if (failed == 2 && conf->cmd == CMD_VALID_PATH) + printf("%s is not a valid multipath device path\n", conf->dev); + else + condlog(3, "scope is nul"); + goto out; + } +- if (conf->dry_run == 3) { ++ if (conf->cmd == CMD_REMOVE_WWID) { + r = remove_wwid(refwwid); + if (r == 0) + printf("wwid '%s' removed\n", refwwid); +@@ -295,7 +298,7 @@ configure (void) + } + goto out; + } +- if (conf->dry_run == 5) { ++ if (conf->cmd == CMD_ADD_WWID) { + r = remember_wwid(refwwid); + if (r == 0) + printf("wwid '%s' added\n", refwwid); +@@ -305,13 +308,13 @@ configure (void) + goto out; + } + condlog(3, "scope limited to %s", refwwid); +- if (conf->dry_run == 2) { +- if (check_wwids_file(refwwid, 0) == 0){ +- printf("%s is a valid multipath device path\n", conf->dev); ++ if (conf->cmd == CMD_VALID_PATH) { ++ if (conf->ignore_wwids || ++ check_wwids_file(refwwid, 0) == 0) + r = 0; +- } +- else +- printf("%s is not a valid multipath device path\n", conf->dev); ++ ++ printf("%s %s a valid multipath device path\n", ++ conf->dev, r == 0 ? "is" : "is not"); + goto out; + } + } +@@ -319,13 +322,13 @@ configure (void) + /* + * get a path list + */ +- if (conf->dev && !conf->list) ++ if (conf->dev) + di_flag = DI_WWID; + +- if (conf->list > 1) ++ if (conf->cmd == CMD_LIST_LONG) + /* extended path info '-ll' */ + di_flag |= DI_SYSFS | DI_CHECKER; +- else if (conf->list) ++ else if (conf->cmd == CMD_LIST_SHORT) + /* minimum path info '-l' */ + di_flag |= DI_SYSFS; + else +@@ -345,7 +348,7 @@ configure (void) + + filter_pathvec(pathvec, refwwid); + +- if (conf->list) { ++ if (conf->cmd != CMD_CREATE && conf->cmd != CMD_DRY_RUN) { + r = 0; + goto out; + } +@@ -440,7 +443,7 @@ main (int argc, char *argv[]) + int r = 1; + long int timestamp = -1; + int valid = -1; +- while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BritT:qwW")) != EOF ) { + switch(arg) { + case 'T': + if (optarg[0] == ':') +@@ -476,7 +479,7 @@ main (int argc, char *argv[]) + if (dm_prereq()) + exit(1); + +- while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BritT:qwW")) != EOF ) { + switch(arg) { + case 1: printf("optarg : %s\n",optarg); + break; +@@ -499,11 +502,11 @@ main (int argc, char *argv[]) + conf->allow_queueing = 1; + break; + case 'c': +- conf->dry_run = 2; ++ conf->cmd = CMD_VALID_PATH; + break; + case 'd': +- if (!conf->dry_run) +- conf->dry_run = 1; ++ if (conf->cmd == CMD_CREATE) ++ conf->cmd = CMD_DRY_RUN; + break; + case 'f': + conf->remove = FLUSH_ONE; +@@ -512,11 +515,10 @@ main (int argc, char *argv[]) + conf->remove = FLUSH_ALL; + break; + case 'l': +- conf->list = 1; +- conf->dry_run = 1; +- + if (optarg && !strncmp(optarg, "l", 1)) +- conf->list++; ++ conf->cmd = CMD_LIST_LONG; ++ else ++ conf->cmd = CMD_LIST_SHORT; + + break; + case 'M': +@@ -535,6 +537,9 @@ main (int argc, char *argv[]) + case 'r': + conf->force_reload = 1; + break; ++ case 'i': ++ conf->ignore_wwids = 1; ++ break; + case 't': + r = dump_config(); + goto out; +@@ -548,13 +553,13 @@ main (int argc, char *argv[]) + usage(argv[0]); + exit(0); + case 'w': +- conf->dry_run = 3; ++ conf->cmd = CMD_REMOVE_WWID; + break; + case 'W': +- conf->dry_run = 4; ++ conf->cmd = CMD_RESET_WWIDS; + break; + case 'a': +- conf->dry_run = 5; ++ conf->cmd = CMD_ADD_WWID; + break; + case ':': + fprintf(stderr, "Missing option argument\n"); +@@ -600,16 +605,16 @@ main (int argc, char *argv[]) + } + dm_init(); + +- if (conf->dry_run == 2 && ++ if (conf->cmd == CMD_VALID_PATH && + (!conf->dev || conf->dev_type == DEV_DEVMAP)) { + condlog(0, "the -c option requires a path to check"); + goto out; + } +- if (conf->dry_run == 3 && !conf->dev) { ++ if (conf->cmd == CMD_REMOVE_WWID && !conf->dev) { + condlog(0, "the -w option requires a device"); + goto out; + } +- if (conf->dry_run == 4) { ++ if (conf->cmd == CMD_RESET_WWIDS) { + struct multipath * mpp; + int i; + vector curmp; +Index: multipath-tools-130222/multipath/multipath.8 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.8 ++++ multipath-tools-130222/multipath/multipath.8 +@@ -8,7 +8,7 @@ multipath \- Device mapper target autoco + .RB [\| \-b\ \c + .IR bindings_file \|] + .RB [\| \-d \|] +-.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-a | \-A | \-w | \-W \|] ++.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-r | \-a | \-A | \-w | \-W \|] + .RB [\| \-p\ \c + .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|] + .RB [\| device \|] +@@ -55,6 +55,9 @@ print internal hardware table to stdout + .B \-r + force devmap reload + .TP ++.B \-i ++ignore wwids file when processing devices ++.TP + .B \-B + treat the bindings file as read only + .TP +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -580,7 +580,7 @@ domap (struct multipath * mpp, char * pa + /* + * last chance to quit before touching the devmaps + */ +- if (conf->dry_run && mpp->action != ACT_NOTHING) { ++ if (conf->cmd == CMD_DRY_RUN && mpp->action != ACT_NOTHING) { + print_multipath_topology(mpp, conf->verbosity); + return DOMAP_DRY; + } +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -54,7 +54,8 @@ store_pathinfo (vector pathvec, vector h + } + pp->udev = udev_device_ref(udevice); + err = pathinfo(pp, hwtable, +- (conf->dry_run == 3)? flag : (flag | DI_BLACKLIST)); ++ (conf->cmd == CMD_REMOVE_WWID)? flag : ++ (flag | DI_BLACKLIST)); + if (err) + goto out; + +@@ -1101,7 +1102,7 @@ get_uid (struct path * pp) + + memset(pp->wwid, 0, WWID_SIZE); + value = udev_device_get_property_value(pp->udev, pp->uid_attribute); +- if ((!value || strlen(value) == 0) && conf->dry_run == 2) ++ if ((!value || strlen(value) == 0) && conf->cmd == CMD_VALID_PATH) + value = getenv(pp->uid_attribute); + if (value && strlen(value)) { + size_t len = WWID_SIZE; diff --git a/SOURCES/0099-RH-add-all-devs.patch b/SOURCES/0099-RH-add-all-devs.patch new file mode 100644 index 0000000..aca6d4c --- /dev/null +++ b/SOURCES/0099-RH-add-all-devs.patch @@ -0,0 +1,170 @@ +--- + libmultipath/config.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++- + libmultipath/config.h | 1 + libmultipath/dict.c | 38 +++++++++++++++++++++++++++++ + 3 files changed, 102 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -113,6 +113,8 @@ find_hwe (vector hwtable, char * vendor, + * continuing to the generic entries + */ + vector_foreach_slot_backwards (hwtable, tmp, i) { ++ if (tmp->all_devs == 1) ++ continue; + if (hwe_regmatch(tmp, &hwe)) + continue; + ret = tmp; +@@ -348,6 +350,62 @@ merge_hwe (struct hwentry * dst, struct + return 0; + } + ++#define overwrite_str(s) \ ++do { \ ++ if (src->s) { \ ++ if (dst->s) \ ++ FREE(dst->s); \ ++ if (!(dst->s = set_param_str(src->s))) \ ++ return 1; \ ++ } \ ++} while(0) ++ ++#define overwrite_num(s) \ ++do { \ ++ if (src->s) \ ++ dst->s = src->s; \ ++} while(0) ++ ++static int ++overwrite_hwe (struct hwentry * dst, struct hwentry * src) ++{ ++ overwrite_str(vendor); ++ overwrite_str(product); ++ overwrite_str(revision); ++ overwrite_str(uid_attribute); ++ overwrite_str(features); ++ overwrite_str(hwhandler); ++ overwrite_str(selector); ++ overwrite_str(checker_name); ++ overwrite_str(prio_name); ++ overwrite_str(prio_args); ++ overwrite_str(alias_prefix); ++ overwrite_str(bl_product); ++ overwrite_num(pgpolicy); ++ overwrite_num(pgfailback); ++ overwrite_num(rr_weight); ++ overwrite_num(no_path_retry); ++ overwrite_num(minio); ++ overwrite_num(minio_rq); ++ overwrite_num(pg_timeout); ++ overwrite_num(flush_on_last_del); ++ overwrite_num(fast_io_fail); ++ overwrite_num(dev_loss); ++ overwrite_num(user_friendly_names); ++ overwrite_num(retain_hwhandler); ++ overwrite_num(detect_prio); ++ ++ /* ++ * Make sure features is consistent with ++ * no_path_retry ++ */ ++ if (dst->no_path_retry == NO_PATH_RETRY_FAIL) ++ remove_feature(&dst->features, "queue_if_no_path"); ++ else if (dst->no_path_retry != NO_PATH_RETRY_UNDEF) ++ add_feature(&dst->features, "queue_if_no_path"); ++ return 0; ++} ++ + int + store_hwe (vector hwtable, struct hwentry * dhwe) + { +@@ -431,7 +489,11 @@ restart: + break; + j = n; + vector_foreach_slot_after(hw, hwe2, j) { +- if (conf->hw_strmatch) { ++ if (hwe2->all_devs == 1) { ++ overwrite_hwe(hwe1, hwe2); ++ continue; ++ } ++ else if (conf->hw_strmatch) { + if (hwe_strmatch(hwe2, hwe1)) + continue; + } +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -47,6 +47,7 @@ struct hwentry { + char * prio_args; + char * alias_prefix; + ++ int all_devs; + int pgpolicy; + int pgfailback; + int rr_weight; +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -918,6 +918,32 @@ device_handler(vector strvec) + } + + static int ++all_devs_handler(vector strvec) ++{ ++ char * buff; ++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); ++ ++ if (!hwe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ hwe->all_devs = 0; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ hwe->all_devs = 1; ++ else ++ hwe->all_devs = 0; ++ ++ FREE(buff); ++ return 0; ++} ++ ++static int + vendor_handler(vector strvec) + { + struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); +@@ -2182,6 +2208,17 @@ snprint_hw_dev_loss(char * buff, int len + } + + static int ++snprint_hw_all_devs (char *buff, int len, void *data) ++{ ++ struct hwentry * hwe = (struct hwentry *)data; ++ ++ if (!hwe->all_devs) ++ return 0; ++ ++ return snprintf(buff, len, "yes"); ++} ++ ++static int + snprint_hw_vendor (char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -2968,6 +3005,7 @@ init_keywords(void) + install_keyword_root("devices", &devices_handler); + install_keyword_multi("device", &device_handler, NULL); + install_sublevel(); ++ install_keyword("all_devs", &all_devs_handler, &snprint_hw_all_devs); + install_keyword("vendor", &vendor_handler, &snprint_hw_vendor); + install_keyword("product", &product_handler, &snprint_hw_product); + install_keyword("revision", &revision_handler, &snprint_hw_revision); diff --git a/SOURCES/0100-RHBZ-1067171-multipath-i-update.patch b/SOURCES/0100-RHBZ-1067171-multipath-i-update.patch new file mode 100644 index 0000000..9a67e7a --- /dev/null +++ b/SOURCES/0100-RHBZ-1067171-multipath-i-update.patch @@ -0,0 +1,54 @@ +--- + multipath/main.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -198,6 +198,9 @@ get_dm_mpvec (vector curmp, vector pathv + continue; + } + ++ if (conf->cmd == CMD_VALID_PATH) ++ continue; ++ + dm_get_map(mpp->alias, &mpp->size, params); + condlog(3, "params = %s", params); + dm_get_status(mpp->alias, status); +@@ -308,7 +311,13 @@ configure (void) + goto out; + } + condlog(3, "scope limited to %s", refwwid); +- if (conf->cmd == CMD_VALID_PATH) { ++ /* If you are ignoring the wwids file and find_multipaths is ++ * set, you need to actually check if there are two available ++ * paths to determine if this path should be multipathed. To ++ * do this, we put off the check until after discovering all ++ * the paths */ ++ if (conf->cmd == CMD_VALID_PATH && ++ (!conf->find_multipaths || !conf->ignore_wwids)) { + if (conf->ignore_wwids || + check_wwids_file(refwwid, 0) == 0) + r = 0; +@@ -348,6 +357,20 @@ configure (void) + + filter_pathvec(pathvec, refwwid); + ++ ++ if (conf->cmd == CMD_VALID_PATH) { ++ /* This only happens if find_multipaths is and ++ * ignore_wwids is set. ++ * If there is currently a multipath device matching ++ * the refwwid, or there is more than one path matching ++ * the refwwid, then the path is valid */ ++ if (VECTOR_SIZE(curmp) != 0 || VECTOR_SIZE(pathvec) > 1) ++ r = 0; ++ printf("%s %s a valid multipath device path\n", ++ conf->dev, r == 0 ? "is" : "is not"); ++ goto out; ++ } ++ + if (conf->cmd != CMD_CREATE && conf->cmd != CMD_DRY_RUN) { + r = 0; + goto out; diff --git a/SOURCES/0101-RH-cleanup-partmaps-code.patch b/SOURCES/0101-RH-cleanup-partmaps-code.patch new file mode 100644 index 0000000..57fb402 --- /dev/null +++ b/SOURCES/0101-RH-cleanup-partmaps-code.patch @@ -0,0 +1,199 @@ +--- + libmultipath/devmapper.c | 155 ++++++++++++++++++----------------------------- + 1 file changed, 61 insertions(+), 94 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -1006,8 +1006,9 @@ bad: + return NULL; + } + +-int +-dm_remove_partmaps (const char * mapname, int need_sync) ++static int ++do_foreach_partmaps (const char * mapname, int (*partmap_func)(char *, void *), ++ void *data) + { + struct dm_task *dmt; + struct dm_names *names; +@@ -1059,26 +1060,8 @@ dm_remove_partmaps (const char * mapname + */ + strstr(params, dev_t) + ) { +- /* +- * then it's a kpartx generated partition. +- * remove it. +- */ +- /* +- * if the opencount is 0 maybe some other +- * partitions depend on it. +- */ +- if (dm_get_opencount(names->name)) { +- dm_remove_partmaps(names->name, need_sync); +- if (dm_get_opencount(names->name)) { +- condlog(2, "%s: map in use", +- names->name); +- goto out; +- } +- } +- condlog(4, "partition map %s removed", +- names->name); +- dm_simplecmd_flush(DM_DEVICE_REMOVE, names->name, +- need_sync, 0); ++ if (partmap_func(names->name, data) != 0) ++ goto out; + } + + next = names->next; +@@ -1091,6 +1074,35 @@ out: + return r; + } + ++struct remove_data { ++ int need_sync; ++}; ++ ++static int ++remove_partmap(char *name, void *data) ++{ ++ struct remove_data *rd = (struct remove_data *)data; ++ ++ if (dm_get_opencount(name)) { ++ dm_remove_partmaps(name, rd->need_sync); ++ if (dm_get_opencount(name)) { ++ condlog(2, "%s: map in use", name); ++ return 1; ++ } ++ } ++ condlog(4, "partition map %s removed", name); ++ dm_simplecmd_flush(DM_DEVICE_REMOVE, name, ++ rd->need_sync, 0); ++ return 0; ++} ++ ++int ++dm_remove_partmaps (const char * mapname, int need_sync) ++{ ++ struct remove_data rd = { need_sync }; ++ return do_foreach_partmaps(mapname, remove_partmap, &rd); ++} ++ + static struct dm_info * + alloc_dminfo (void) + { +@@ -1140,86 +1152,41 @@ out: + return r; + } + +-int +-dm_rename_partmaps (char * old, char * new) ++struct rename_data { ++ char *old; ++ char *new; ++ char *delim; ++}; ++ ++static int ++rename_partmap (char *name, void *data) + { +- struct dm_task *dmt; +- struct dm_names *names; +- unsigned next = 0; + char buff[PARAMS_SIZE]; +- unsigned long long size; +- char dev_t[32]; +- int r = 1; + int offset; +- char *delim; +- +- if (!(dmt = dm_task_create(DM_DEVICE_LIST))) +- return 1; ++ struct rename_data *rd = (struct rename_data *)data; + +- dm_task_no_open_count(dmt); +- +- if (!dm_task_run(dmt)) +- goto out; +- +- if (!(names = dm_task_get_names(dmt))) +- goto out; +- +- if (!names->dev) { +- r = 0; /* this is perfectly valid */ +- goto out; +- } ++ if (strncmp(name, rd->old, strlen(rd->old)) != 0) ++ return 0; ++ for (offset = strlen(rd->old); name[offset] && !(isdigit(name[offset])); offset++); /* do nothing */ ++ snprintf(buff, PARAMS_SIZE, "%s%s%s", rd->new, rd->delim, ++ name + offset); ++ dm_rename(name, buff); ++ condlog(4, "partition map %s renamed", name); ++ return 0; ++} + +- if (dm_dev_t(old, &dev_t[0], 32)) +- goto out; ++int ++dm_rename_partmaps (char * old, char * new) ++{ ++ struct rename_data rd; + ++ rd.old = old; ++ rd.new = new; + if (isdigit(new[strlen(new)-1])) +- delim = "p"; ++ rd.delim = "p"; + else +- delim = ""; +- +- do { +- if ( +- /* +- * if devmap target is "linear" +- */ +- (dm_type(names->name, TGT_PART) > 0) && +- +- /* +- * and the multipath mapname and the part mapname start +- * the same +- */ +- !strncmp(names->name, old, strlen(old)) && +- +- /* +- * and we can fetch the map table from the kernel +- */ +- !dm_get_map(names->name, &size, &buff[0]) && +- +- /* +- * and the table maps over the multipath map +- */ +- strstr(buff, dev_t) +- ) { +- /* +- * then it's a kpartx generated partition. +- * Rename it. +- */ +- for (offset = strlen(old); names->name[offset] && !(isdigit(names->name[offset])); offset++); /* do nothing */ +- snprintf(buff, PARAMS_SIZE, "%s%s%s", +- new, delim, names->name + offset); +- dm_rename(names->name, buff); +- condlog(4, "partition map %s renamed", +- names->name); +- } +- +- next = names->next; +- names = (void *) names + next; +- } while (next); +- +- r = 0; +-out: +- dm_task_destroy (dmt); +- return r; ++ rd.delim = ""; ++ return do_foreach_partmaps(old, rename_partmap, &rd); + } + + int diff --git a/SOURCES/0102-RHBZ-631009-deferred-remove.patch b/SOURCES/0102-RHBZ-631009-deferred-remove.patch new file mode 100644 index 0000000..1e1367a --- /dev/null +++ b/SOURCES/0102-RHBZ-631009-deferred-remove.patch @@ -0,0 +1,751 @@ +--- + libmultipath/Makefile | 6 ++ + libmultipath/config.c | 3 + + libmultipath/config.h | 3 + + libmultipath/configure.c | 1 + libmultipath/defaults.h | 1 + libmultipath/devmapper.c | 130 +++++++++++++++++++++++++++++++++++++++------ + libmultipath/devmapper.h | 12 ++-- + libmultipath/dict.c | 116 +++++++++++++++++++++++++++++++++++++++- + libmultipath/propsel.c | 28 +++++++++ + libmultipath/propsel.h | 1 + libmultipath/structs.h | 8 ++ + libmultipath/structs_vec.c | 3 - + multipath/multipath.conf.5 | 14 ++++ + multipathd/main.c | 23 +++++-- + 14 files changed, 322 insertions(+), 27 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -337,6 +337,7 @@ merge_hwe (struct hwentry * dst, struct + merge_num(user_friendly_names); + merge_num(retain_hwhandler); + merge_num(detect_prio); ++ merge_num(deferred_remove); + + /* + * Make sure features is consistent with +@@ -394,6 +395,7 @@ overwrite_hwe (struct hwentry * dst, str + overwrite_num(user_friendly_names); + overwrite_num(retain_hwhandler); + overwrite_num(detect_prio); ++ overwrite_num(deferred_remove); + + /* + * Make sure features is consistent with +@@ -617,6 +619,7 @@ load_config (char * file, struct udev *u + conf->fast_io_fail = DEFAULT_FAST_IO_FAIL; + conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER; + conf->detect_prio = DEFAULT_DETECT_PRIO; ++ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE; + conf->hw_strmatch = 0; + conf->force_sync = 0; + +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -61,6 +61,7 @@ struct hwentry { + int user_friendly_names; + int retain_hwhandler; + int detect_prio; ++ int deferred_remove; + char * bl_product; + }; + +@@ -84,6 +85,7 @@ struct mpentry { + int flush_on_last_del; + int attribute_flags; + int user_friendly_names; ++ int deferred_remove; + uid_t uid; + gid_t gid; + mode_t mode; +@@ -128,6 +130,7 @@ struct config { + int retain_hwhandler; + int detect_prio; + int force_sync; ++ int deferred_remove; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -290,6 +290,7 @@ setup_map (struct multipath * mpp, char + select_dev_loss(mpp); + select_reservation_key(mpp); + select_retain_hwhandler(mpp); ++ select_deferred_remove(mpp); + + sysfs_set_scsi_tmo(mpp); + /* +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -19,6 +19,7 @@ + #define DEFAULT_FAST_IO_FAIL 5 + #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF + #define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF ++#define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF + + #define DEFAULT_CHECKINT 5 + #define MAX_CHECKINT(a) (a << 2) +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -103,7 +103,9 @@ dm_lib_prereq (void) + { + char version[64]; + int v[3]; +-#if defined(DM_SUBSYSTEM_UDEV_FLAG0) ++#if defined(LIBDM_API_DEFERRED) ++ int minv[3] = {1, 2, 89}; ++#elif defined(DM_SUBSYSTEM_UDEV_FLAG0) + int minv[3] = {1, 2, 82}; + #elif defined(LIBDM_API_COOKIE) + int minv[3] = {1, 2, 38}; +@@ -202,7 +204,7 @@ dm_prereq (void) + } + + static int +-dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags) { ++dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags, int deferred_remove) { + int r = 0; + int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE)); +@@ -220,7 +222,10 @@ dm_simplecmd (int task, const char *name + if (no_flush) + dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ + #endif +- ++#ifdef LIBDM_API_DEFERRED ++ if (deferred_remove) ++ dm_task_deferred_remove(dmt); ++#endif + if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags)) + goto out; + r = dm_task_run (dmt); +@@ -232,12 +237,18 @@ dm_simplecmd (int task, const char *name + + extern int + dm_simplecmd_flush (int task, const char *name, int needsync, uint16_t udev_flags) { +- return dm_simplecmd(task, name, 0, needsync, udev_flags); ++ return dm_simplecmd(task, name, 0, needsync, udev_flags, 0); + } + + extern int + dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) { +- return dm_simplecmd(task, name, 1, 1, udev_flags); ++ return dm_simplecmd(task, name, 1, 1, udev_flags, 0); ++} ++ ++extern int ++dm_device_remove (const char *name, int needsync, int deferred_remove) { ++ return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, needsync, 0, ++ deferred_remove); + } + + extern int +@@ -653,7 +664,7 @@ out: + } + + extern int +-_dm_flush_map (const char * mapname, int need_sync) ++_dm_flush_map (const char * mapname, int need_sync, int deferred_remove) + { + int r; + +@@ -663,23 +674,46 @@ _dm_flush_map (const char * mapname, int + if (dm_type(mapname, TGT_MPATH) <= 0) + return 0; /* nothing to do */ + +- if (dm_remove_partmaps(mapname, need_sync)) ++ if (dm_remove_partmaps(mapname, need_sync, deferred_remove)) + return 1; + +- if (dm_get_opencount(mapname)) { ++ if (!deferred_remove && dm_get_opencount(mapname)) { + condlog(2, "%s: map in use", mapname); + return 1; + } + +- r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync, 0); ++ r = dm_device_remove(mapname, need_sync, deferred_remove); + + if (r) { ++ if (deferred_remove && dm_map_present(mapname)) { ++ condlog(4, "multipath map %s remove deferred", ++ mapname); ++ return 2; ++ } + condlog(4, "multipath map %s removed", mapname); + return 0; + } + return 1; + } + ++#ifdef LIBDM_API_DEFERRED ++ ++int ++dm_flush_map_nopaths(const char * mapname, int deferred_remove) ++{ ++ return _dm_flush_map(mapname, 1, deferred_remove); ++} ++ ++#else ++ ++int ++dm_flush_map_nopaths(const char * mapname, int deferred_remove) ++{ ++ return _dm_flush_map(mapname, 1, 0); ++} ++ ++#endif ++ + extern int + dm_suspend_and_flush_map (const char * mapname) + { +@@ -1076,6 +1110,7 @@ out: + + struct remove_data { + int need_sync; ++ int deferred_remove; + }; + + static int +@@ -1084,25 +1119,90 @@ remove_partmap(char *name, void *data) + struct remove_data *rd = (struct remove_data *)data; + + if (dm_get_opencount(name)) { +- dm_remove_partmaps(name, rd->need_sync); +- if (dm_get_opencount(name)) { ++ dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove); ++ if (!rd->deferred_remove && dm_get_opencount(name)) { + condlog(2, "%s: map in use", name); + return 1; + } + } + condlog(4, "partition map %s removed", name); +- dm_simplecmd_flush(DM_DEVICE_REMOVE, name, +- rd->need_sync, 0); ++ dm_device_remove(name, rd->need_sync, rd->deferred_remove); + return 0; + } + + int +-dm_remove_partmaps (const char * mapname, int need_sync) ++dm_remove_partmaps (const char * mapname, int need_sync, int deferred_remove) + { +- struct remove_data rd = { need_sync }; ++ struct remove_data rd = { need_sync, deferred_remove }; + return do_foreach_partmaps(mapname, remove_partmap, &rd); + } + ++#ifdef LIBDM_API_DEFERRED ++ ++static int ++cancel_remove_partmap (char *name, void *unused) ++{ ++ if (dm_message(name, "@cancel_deferred_remove") != 0) ++ condlog(0, "%s: can't cancel deferred remove: %s", name, ++ strerror(errno)); ++ return 0; ++} ++ ++static int ++dm_get_deferred_remove (char * mapname) ++{ ++ int r = -1; ++ struct dm_task *dmt; ++ struct dm_info info; ++ ++ if (!(dmt = dm_task_create(DM_DEVICE_INFO))) ++ return -1; ++ ++ if (!dm_task_set_name(dmt, mapname)) ++ goto out; ++ ++ if (!dm_task_run(dmt)) ++ goto out; ++ ++ if (!dm_task_get_info(dmt, &info)) ++ goto out; ++ ++ r = info.deferred_remove; ++out: ++ dm_task_destroy(dmt); ++ return r; ++} ++ ++int ++dm_cancel_deferred_remove (struct multipath *mpp) ++{ ++ int r = 0; ++ ++ if (!dm_get_deferred_remove(mpp->alias)) ++ return 0; ++ if (mpp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) ++ mpp->deferred_remove = DEFERRED_REMOVE_ON; ++ ++ do_foreach_partmaps(mpp->alias, cancel_remove_partmap, NULL); ++ r = dm_message(mpp->alias, "@cancel_deferred_remove"); ++ if (r) ++ condlog(0, "%s: can't cancel deferred remove: %s", mpp->alias, ++ strerror(errno)); ++ else ++ condlog(2, "%s: canceled deferred remove", mpp->alias); ++ return r; ++} ++ ++#else ++ ++int ++dm_cancel_deferred_remove (struct multipath *mpp) ++{ ++ return 0; ++} ++ ++#endif ++ + static struct dm_info * + alloc_dminfo (void) + { +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -17,15 +17,18 @@ int dm_prereq (void); + int dm_drv_version (unsigned int * version, char * str); + int dm_simplecmd_flush (int, const char *, int, uint16_t); + int dm_simplecmd_noflush (int, const char *, uint16_t); ++int dm_device_remove (const char *, int, int); + int dm_addmap_create (struct multipath *mpp, char *params); + int dm_addmap_reload (struct multipath *mpp, char *params); + int dm_map_present (const char *); + int dm_get_map(const char *, unsigned long long *, char *); + int dm_get_status(char *, char *); + int dm_type(const char *, char *); +-int _dm_flush_map (const char *, int); +-#define dm_flush_map(mapname) _dm_flush_map(mapname, 1) +-#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0) ++int _dm_flush_map (const char *, int, int); ++int dm_flush_map_nopaths(const char * mapname, int deferred_remove); ++#define dm_flush_map(mapname) _dm_flush_map(mapname, 1, 0) ++#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0, 0) ++int dm_cancel_deferred_remove(struct multipath *mpp); + int dm_suspend_and_flush_map(const char * mapname); + int dm_flush_maps (void); + int dm_fail_path(char * mapname, char * path); +@@ -40,7 +43,8 @@ int dm_geteventnr (char *name); + int dm_get_major (char *name); + int dm_get_minor (char *name); + char * dm_mapname(int major, int minor); +-int dm_remove_partmaps (const char * mapname, int need_sync); ++int dm_remove_partmaps (const char * mapname, int need_sync, ++ int deferred_remove); + int dm_get_uuid(char *name, char *uuid); + int dm_get_info (char * mapname, struct dm_info ** dmi); + int dm_rename (char * old, char * new); +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -738,6 +738,29 @@ def_force_sync_handler(vector strvec) + return 0; + } + ++static int ++def_deferred_remove_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->deferred_remove = DEFERRED_REMOVE_OFF; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ conf->deferred_remove = DEFERRED_REMOVE_ON; ++ else ++ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -1445,6 +1468,33 @@ hw_detect_prio_handler(vector strvec) + return 0; + } + ++static int ++hw_deferred_remove_handler(vector strvec) ++{ ++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); ++ char * buff; ++ ++ if (!hwe) ++ return 1; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ hwe->deferred_remove = DEFERRED_REMOVE_OFF; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ hwe->deferred_remove = DEFERRED_REMOVE_ON; ++ else ++ hwe->deferred_remove = DEFERRED_REMOVE_UNDEF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * multipaths block handlers + */ +@@ -1920,6 +1970,32 @@ mp_names_handler(vector strvec) + return 0; + } + ++static int ++mp_deferred_remove_handler(vector strvec) ++{ ++ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); ++ char * buff; ++ ++ if (!mpe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && strcmp(buff, "no") == 0) || ++ (strlen(buff) == 1 && strcmp(buff, "0") == 0)) ++ mpe->deferred_remove = DEFERRED_REMOVE_OFF; ++ else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) || ++ (strlen(buff) == 1 && strcmp(buff, "1") == 0)) ++ mpe->deferred_remove = DEFERRED_REMOVE_ON; ++ else ++ mpe->deferred_remove = DEFERRED_REMOVE_UNDEF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * config file keywords printing + */ +@@ -2165,7 +2241,7 @@ snprint_mp_reservation_key (char * buff, + return snprintf(buff, len, "0x%" PRIx64, prkey); + } + +- static int ++static int + snprint_mp_user_friendly_names (char * buff, int len, void * data) + { + struct mpentry * mpe = (struct mpentry *)data; +@@ -2179,6 +2255,19 @@ snprint_mp_user_friendly_names (char * b + } + + static int ++snprint_mp_deferred_remove (char * buff, int len, void * data) ++{ ++ struct mpentry * mpe = (struct mpentry *)data; ++ ++ if (mpe->deferred_remove == DEFERRED_REMOVE_UNDEF) ++ return 0; ++ else if (mpe->deferred_remove == DEFERRED_REMOVE_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return snprintf(buff, len, "yes"); ++} ++ ++static int + snprint_hw_fast_io_fail(char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -2507,6 +2596,19 @@ snprint_hw_retain_hwhandler_handler(char + } + + static int ++snprint_hw_deferred_remove(char * buff, int len, void * data) ++{ ++ struct hwentry * hwe = (struct hwentry *)data; ++ ++ if (hwe->deferred_remove == DEFERRED_REMOVE_ON) ++ return snprintf(buff, len, "yes"); ++ else if (hwe->deferred_remove == DEFERRED_REMOVE_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return 0; ++} ++ ++static int + snprint_detect_prio(char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -2900,6 +3002,15 @@ snprint_def_force_sync(char * buff, int + } + + static int ++snprint_def_deferred_remove(char * buff, int len, void * data) ++{ ++ if (conf->deferred_remove == DEFERRED_REMOVE_ON) ++ return snprintf(buff, len, "yes"); ++ else ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -2968,6 +3079,7 @@ init_keywords(void) + install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio); + install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch); + install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync); ++ install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +@@ -3032,6 +3144,7 @@ init_keywords(void) + install_keyword("user_friendly_names", &hw_names_handler, &snprint_hw_user_friendly_names); + install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler_handler); + install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_detect_prio); ++ install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove); + install_sublevel_end(); + + install_keyword_root("multipaths", &multipaths_handler); +@@ -3056,5 +3169,6 @@ init_keywords(void) + install_keyword("gid", &mp_gid_handler, &snprint_mp_gid); + install_keyword("reservation_key", &mp_reservation_key_handler, &snprint_mp_reservation_key); + install_keyword("user_friendly_names", &mp_names_handler, &snprint_mp_user_friendly_names); ++ install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove); + install_sublevel_end(); + } +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -744,6 +744,34 @@ select_retain_hwhandler (struct multipat + } + + extern int ++select_deferred_remove (struct multipath *mp) ++{ ++ if (mp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) { ++ condlog(3, "%s: deferred_remove in progress", mp->alias); ++ return 0; ++ } ++ if (mp->mpe && mp->mpe->deferred_remove) { ++ mp->deferred_remove = mp->mpe->deferred_remove; ++ condlog(3, "%s: deferred_remove = %i (multipath setting)", ++ mp->alias, mp->deferred_remove); ++ return 0; ++ } ++ if (mp->hwe && mp->hwe->deferred_remove) { ++ mp->deferred_remove = mp->hwe->deferred_remove; ++ condlog(3, "%s: deferred_remove = %d (controller default)", mp->alias, mp->deferred_remove); ++ return 0; ++ } ++ if (conf->deferred_remove) { ++ mp->deferred_remove = conf->deferred_remove; ++ condlog(3, "%s: deferred_remove = %d (config file default)", mp->alias, mp->deferred_remove); ++ return 0; ++ } ++ mp->deferred_remove = DEFAULT_DEFERRED_REMOVE; ++ condlog(3, "%s: deferred_remove = %d (compiled in default)", mp->alias, mp->deferred_remove); ++ return 0; ++} ++ ++extern int + select_detect_prio (struct path * pp) + { + if (pp->hwe && pp->hwe->detect_prio) { +Index: multipath-tools-130222/libmultipath/propsel.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.h ++++ multipath-tools-130222/libmultipath/propsel.h +@@ -20,3 +20,4 @@ int select_dev_loss(struct multipath *mp + int select_reservation_key(struct multipath *mp); + int select_retain_hwhandler (struct multipath * mp); + int select_detect_prio(struct path * pp); ++int select_deferred_remove(struct multipath *mp); +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -114,6 +114,13 @@ enum detect_prio_states { + DETECT_PRIO_ON, + }; + ++enum deferred_remove_states { ++ DEFERRED_REMOVE_UNDEF, ++ DEFERRED_REMOVE_OFF, ++ DEFERRED_REMOVE_ON, ++ DEFERRED_REMOVE_IN_PROGRESS, ++}; ++ + enum scsi_protocol { + SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */ + SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */ +@@ -207,6 +214,7 @@ struct multipath { + int attribute_flags; + int fast_io_fail; + int retain_hwhandler; ++ int deferred_remove; + unsigned int dev_loss; + uid_t uid; + gid_t gid; +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -214,19 +214,30 @@ sync_maps_state(vector mpvec) + } + + static int +-flush_map(struct multipath * mpp, struct vectors * vecs) ++flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths) + { ++ int r; ++ ++ if (nopaths) ++ r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove); ++ else ++ r = dm_flush_map(mpp->alias); + /* + * clear references to this map before flushing so we can ignore + * the spurious uevent we may generate with the dm_flush_map call below + */ +- if (dm_flush_map(mpp->alias)) { ++ if (r) { + /* + * May not really be an error -- if the map was already flushed + * from the device mapper by dmsetup(8) for instance. + */ +- condlog(0, "%s: can't flush", mpp->alias); +- return 1; ++ if (r == 1) ++ condlog(0, "%s: can't flush", mpp->alias); ++ else { ++ condlog(2, "%s: devmap deferred remove", mpp->alias); ++ mpp->deferred_remove = DEFERRED_REMOVE_IN_PROGRESS; ++ } ++ return r; + } + else { + dm_lib_release(); +@@ -372,7 +383,7 @@ ev_remove_map (char * devname, char * al + mpp->alias, mpp->dmi->minor, minor); + return 0; + } +- return flush_map(mpp, vecs); ++ return flush_map(mpp, vecs, 0); + } + + static int +@@ -628,7 +639,7 @@ ev_remove_path (struct path *pp, struct + mpp->flush_on_last_del = FLUSH_IN_PROGRESS; + dm_queue_if_no_path(mpp->alias, 0); + } +- if (!flush_map(mpp, vecs)) { ++ if (!flush_map(mpp, vecs, 1)) { + condlog(2, "%s: removed map after" + " removing all paths", + alias); +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -392,6 +392,8 @@ __setup_multipath (struct vectors * vecs + set_no_path_retry(mpp); + select_pg_timeout(mpp); + select_flush_on_last_del(mpp); ++ if (VECTOR_SIZE(mpp->paths) != 0) ++ dm_cancel_deferred_remove(mpp); + } + + return 0; +@@ -565,7 +567,6 @@ int update_multipath (struct vectors *ve + } + } + } +- + return 0; + } + +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -420,6 +420,16 @@ only one checker will run at a time. Th + multipathd checkers running in parallel causes significant CPU pressure. The + Default is + .I no ++.TP ++.B deferred_remove ++If set to ++.I yes ++, multipathd will do a deferred remove instead of a regular remove when the ++last path device has been deleted. This means that if the multipath device is ++still in use, it will be freed when the last user closes it. If path is added ++to the multipath device before the last user closes it, the deferred remove ++will be canceled. Default is ++.I no + . + .SH "blacklist section" + The +@@ -521,6 +531,8 @@ section: + .B features + .TP + .B reservation_key ++.TP ++.B deferred_remove + .RE + .PD + .LP +@@ -611,6 +623,8 @@ section: + .B retain_attached_hw_handler + .TP + .B detect_prio ++.TP ++.B deferred_remove + .RE + .PD + .LP +Index: multipath-tools-130222/libmultipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmultipath/Makefile ++++ multipath-tools-130222/libmultipath/Makefile +@@ -36,6 +36,12 @@ ifneq ($(strip $(LIBUDEV_API_RECVBUF)),0 + CFLAGS += -DLIBUDEV_API_RECVBUF + endif + ++LIBDM_API_DEFERRED = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_deferred_remove' /usr/include/libdevmapper.h) ++ ++ifneq ($(strip $(LIBDM_API_DEFERRED)),0) ++ CFLAGS += -DLIBDM_API_DEFERRED ++endif ++ + + all: $(LIBS) + diff --git a/SOURCES/0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch b/SOURCES/0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch new file mode 100644 index 0000000..8c793bb --- /dev/null +++ b/SOURCES/0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch @@ -0,0 +1,10 @@ +diff -purN multipath-tools-130222.orig/multipath/multipath.rules multipath-tools-130222/multipath/multipath.rules +--- multipath-tools-130222.orig/multipath/multipath.rules 2014-11-03 14:37:41.269413134 +0100 ++++ multipath-tools-130222/multipath/multipath.rules 2014-11-03 14:38:43.694281901 +0100 +@@ -45,5 +45,5 @@ ACTION!="change", GOTO="end_mpath" + ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath" + ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" + ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" +-RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode" ++ENV{DM_ACTIVATION}=="1", RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode" + LABEL="end_mpath" diff --git a/SOURCES/0104-RHBZ-1159337-fix-double-free.patch b/SOURCES/0104-RHBZ-1159337-fix-double-free.patch new file mode 100644 index 0000000..cbe4d1e --- /dev/null +++ b/SOURCES/0104-RHBZ-1159337-fix-double-free.patch @@ -0,0 +1,20 @@ +--- + multipathd/main.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -669,9 +669,8 @@ ev_remove_path (struct path *pp, struct + /* + * update our state from kernel + */ +- if (setup_multipath(vecs, mpp)) { +- goto fail; +- } ++ if (setup_multipath(vecs, mpp)) ++ return 1; + sync_map_state(mpp); + + condlog(2, "%s [%s]: path removed from map %s", diff --git a/SOURCES/0105-RHBZ-1180032-find-multipaths-man.patch b/SOURCES/0105-RHBZ-1180032-find-multipaths-man.patch new file mode 100644 index 0000000..c5e6bcf --- /dev/null +++ b/SOURCES/0105-RHBZ-1180032-find-multipaths-man.patch @@ -0,0 +1,37 @@ +--- + multipath/multipath.conf.5 | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -84,6 +84,28 @@ directory where the dynamic shared objec + dependent, commonly + .I /lib/multipath + .TP ++.B find_multipaths ++If set to ++.I yes ++, instead of trying to create a multipath device for every non-blacklisted ++path, multipath will only create a device if one of three condidions are ++met. ++.I 1 ++There are at least two non-blacklisted paths with the same wwid, ++.I 2 ++the user manually forces the creation, by specifying a device with the multipath ++command, or ++.I 3 ++a path has the same WWID as a multipath device that was previously created ++while find_multipaths was set (even if that multipath device doesn't currently ++exist). ++Whenever a multipath device is created with find_multipaths set, multipath will ++remeber the WWID of the device, so that it will automatically create the ++device again, as soon as it sees a path with that WWID. This should allow most ++users to have multipath automatically choose the correct paths to make into ++multipath devices, without having to edit the blacklist; Default is ++.I no ++.TP + .B verbosity + default verbosity. Higher values increase the verbosity level. Valid + levels are between 0 and 6; default is diff --git a/SOURCES/multipath.conf b/SOURCES/multipath.conf index 401992b..22872ae 100644 --- a/SOURCES/multipath.conf +++ b/SOURCES/multipath.conf @@ -33,7 +33,7 @@ defaults { # polling_interval 10 # selector "round-robin 0" # path_grouping_policy multibus -# getuid_callout "/lib/udev/scsi_id --whitelisted --device=/dev/%n" +# uid_attribute ID_SERIAL # prio alua # path_checker readsector0 # rr_min_io 100 @@ -79,7 +79,6 @@ defaults { # vendor "COMPAQ " # product "HSV110 (C)COMPAQ" # path_grouping_policy multibus -# getuid_callout "/lib/udev/scsi_id --whitelisted --device=/dev/%n" # path_checker readsector0 # path_selector "round-robin 0" # hardware_handler "0" diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index 891931e..790e686 100644 --- a/SPECS/device-mapper-multipath.spec +++ b/SPECS/device-mapper-multipath.spec @@ -1,7 +1,7 @@ Summary: Tools to manage multipath devices using device-mapper Name: device-mapper-multipath Version: 0.4.9 -Release: 66%{?dist} +Release: 77%{?dist} License: GPL+ Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -57,7 +57,7 @@ Patch0046: 0046-RHBZ-883981-move-udev-rules.patch Patch0047: 0047-RHBZ-kpartx-read-only-loop-devs.patch Patch0048: 0048-RH-print-defaults.patch Patch0049: 0049-RH-remove-ID_FS_TYPE.patch -#Patch0050: 0050-RH-listing-speedup.patch +Patch0050: 0050-RH-listing-speedup.patch Patch0051: 0051-UP-fix-cli-resize.patch Patch0052: 0052-RH-fix-bad-derefs.patch Patch0053: 0053-UP-fix-failback.patch @@ -88,18 +88,43 @@ Patch0077: 0077-RHBZ-1054806-mpathconf-always-reload.patch Patch0078: 0078-RHBZ-1054044-fix-mpathconf-manpage.patch Patch0079: 0079-RHBZ-1070581-add-wwid-option.patch Patch0080: 0080-RHBZ-1075796-cmdline-wwid.patch +Patch0081: 0081-RHBZ-1066264-check-prefix-on-rename.patch +Patch0082: 0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch +Patch0083: 0083-RHBZ-1080055-orphan-paths-on-reload.patch +Patch0084: 0084-RHBZ-1110000-multipath-man.patch +Patch0085: 0085-UPBZ-1110006-datacore-config.patch +Patch0086: 0086-RHBZ-1110007-orphan-path-on-failed-add.patch +Patch0087: 0087-RHBZ-1110013-config-error-checking.patch +Patch0088: 0088-RHBZ-1069811-configurable-prio-timeout.patch +Patch0089: 0089-RHBZ-1110016-add-noasync-option.patch +Patch0090: 0090-UPBZ-1080038-reorder-paths-for-round-robin.patch +Patch0091: 0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch +Patch0092: 0092-UPBZ-1104605-reload-on-rename.patch +Patch0093: 0093-UPBZ-1086825-user-friendly-name-remap.patch +Patch0094: 0094-RHBZ-1086825-cleanup-remap.patch +Patch0095: 0095-RHBZ-1127944-xtremIO-config.patch +Patch0096: 0096-RHBZ-979474-new-wildcards.patch +Patch0097: 0097-RH-fix-coverity-errors.patch +Patch0098: 0098-UPBZ-1067171-mutipath-i.patch +Patch0099: 0099-RH-add-all-devs.patch +Patch0100: 0100-RHBZ-1067171-multipath-i-update.patch +Patch0101: 0101-RH-cleanup-partmaps-code.patch +Patch0102: 0102-RHBZ-631009-deferred-remove.patch +Patch0103: 0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch +Patch0104: 0104-RHBZ-1159337-fix-double-free.patch +Patch0105: 0105-RHBZ-1180032-find-multipaths-man.patch # runtime Requires: %{name}-libs = %{version}-%{release} Requires: kpartx = %{version}-%{release} -Requires: device-mapper >= 1.02.82-2 +Requires: device-mapper >= 1.02.89 Requires: initscripts Requires(post): systemd-units systemd-sysv chkconfig Requires(preun): systemd-units Requires(postun): systemd-units # build/setup -BuildRequires: libaio-devel, device-mapper-devel >= 1.02.82-2 +BuildRequires: libaio-devel, device-mapper-devel >= 1.02.89 BuildRequires: libselinux-devel, libsepol-devel BuildRequires: readline-devel, ncurses-devel BuildRequires: systemd-units, systemd-devel @@ -189,7 +214,7 @@ kpartx manages partition creation and removal for device-mapper devices. %patch0047 -p1 %patch0048 -p1 %patch0049 -p1 -# %patch0050 -p1 +%patch0050 -p1 %patch0051 -p1 %patch0052 -p1 %patch0053 -p1 @@ -220,6 +245,31 @@ kpartx manages partition creation and removal for device-mapper devices. %patch0078 -p1 %patch0079 -p1 %patch0080 -p1 +%patch0081 -p1 +%patch0082 -p1 +%patch0083 -p1 +%patch0084 -p1 +%patch0085 -p1 +%patch0086 -p1 +%patch0087 -p1 +%patch0088 -p1 +%patch0089 -p1 +%patch0090 -p1 +%patch0091 -p1 +%patch0092 -p1 +%patch0093 -p1 +%patch0094 -p1 +%patch0095 -p1 +%patch0096 -p1 +%patch0097 -p1 +%patch0098 -p1 +%patch0099 -p1 +%patch0100 -p1 +%patch0101 -p1 +%patch0102 -p1 +%patch0103 -p1 +%patch0104 -p1 +%patch0105 -p1 cp %{SOURCE1} . %build @@ -314,6 +364,112 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: %{_mandir}/man8/kpartx.8.gz %changelog +* Fri Jan 9 2015 Benjamin Marzinski 0.4.9-77 +- Add 0105-RHBZ-1180032-find-multipaths-man.patch + * add find_multipaths to man page +- Modify multipath.conf (bz #1069360) + * add uid_attribute example +- Resolves: bz #1180032 + +* Fri Nov 14 2014 Benjamin Marzinski 0.4.9-76 +- Modify 0102-RHBZ-631009-deferred-remove.patch + * Fixed compiler warning message for builds with old device-mapper versions +- Add 0104-RHBZ-1159337-fix-double-free.patch + * made ev_remove_path exit immediately after failing setup_multipath, since + it handles cleaning up the device +- Resolves: bz #1159337 +- Related: bz #631009 + +* Thu Nov 6 2014 Benjamin Marzinski 0.4.9-75 +- Add 0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch + * Only run kpartx on device activation +- Resolves: bz #1148979 + +* Tue Oct 28 2014 Benjamin Marzinski 0.4.9-74 +- Respin again to let buildroot catch up. +- Related: bz #631009 + +* Tue Oct 28 2014 Benjamin Marzinski 0.4.9-73 +- Respin to pick up latest lvm2 code +- Related: bz #631009 + +* Tue Oct 28 2014 Benjamin Marzinski 0.4.9-72 +- Add 0101-RH-cleanup-partmaps-code.patch + * code refactoring to prepare for next patch +- Add 0102-RHBZ-631009-deferred-remove.patch + * add deferred_remove option to /etc/multipath.conf +- Resolves: bz #631009 + +* Fri Sep 5 2014 Benjamin Marzinski 0.4.9-71 +- Re-add 0050-RH-listing-speedup.patch +- Modify 0098-UPBZ-1067171-mutipath-i.patch + * add dry_run cleanup code from upstream +- Refresh 0099-RH-add-all-devs.patch +- Add 0100-RHBZ-1067171-multipath-i-update.patch + * make -i work correctly with find_multipaths +- Resolves: bz #1067171 + +* Wed Sep 3 2014 Benjamin Marzinski 0.4.9-70 +- Modify 0096-RHBZ-979474-new-wildcards.patch + * Fix a faulty check +- Add 0098-UPBZ-1067171-mutipath-i.patch + * Add -i option to ignore wwids file when checking for valid paths +- Add 0099-RH-add-all-devs.patch + * Add new devices config option all_devs. This makes the configuration + overwrite the specified values in all builtin configs +- Related: bz #979474 +- Resolves: bz #1067171 + +* Thu Aug 28 2014 Benjamin Marzinski 0.4.9-69 +- Add 0096-RHBZ-979474-new-wildcards.patch + * Add N, n, R, and r path wildcards to print World Wide ids +- Add 0097-RH-fix-coverity-errors.patch + * Fix a number of unterminated strings and memory leaks on failure + paths. +- Resolves: bz #979474 + +* Tue Aug 12 2014 Benjamin Marzinski 0.4.9-68 +- Add 0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch + * check for null pointers in configuration reading code. +- Add 0092-UPBZ-1104605-reload-on-rename.patch + * Reload table on rename if necessary +- Add 0093-UPBZ-1086825-user-friendly-name-remap.patch + * Keep existing user_friend_name if possible +- Add 0094-RHBZ-1086825-cleanup-remap.patch + * Cleanup issues with upstream patch +- Add 0095-RHBZ-1127944-xtremIO-config.patch + * Add support for EMC ExtremIO devices +- Resolves: bz #1069584, #1104605, #1086825, #1086825, #1127944 + +* Tue Aug 12 2014 Benjamin Marzinski 0.4.9-67 +- Modify multipath.conf (bz #1069360) + * remove getuid_callout example +- Add 0081-RHBZ-1066264-check-prefix-on-rename.patch + * make multipath check the prefix on kpartx partitions during rename, and + copy the existing behaviour +- Add 0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch + * If async tur checker fails on threads, don't retry with the sync version +- Add 0083-RHBZ-1080055-orphan-paths-on-reload.patch + * Fix case where pathlist wasn't getting updated properly +- Add 0084-RHBZ-1110000-multipath-man.patch + * fix errors in multipath man page +- Add 0085-UPBZ-1110006-datacore-config.patch + * Add support for DataCore Virtual Disk +- Add 0086-RHBZ-1110007-orphan-path-on-failed-add.patch + * If multipathd fails to add path correctly, it now fully orphans the path +- Add 0087-RHBZ-1110013-config-error-checking.patch + * Improve multipath.conf error checking. +- Add 0088-RHBZ-1069811-configurable-prio-timeout.patch + * checker_timeout now adjusts the timeouts of the prioritizers as well. +- Add 0089-RHBZ-1110016-add-noasync-option.patch + * Add a new defaults option, "force_sync", that disables the async mode + of the path checkers. This is for cases where to many parallel checkers + hog the CPU +- Add 0090-UPBZ-1080038-reorder-paths-for-round-robin.patch + * make multipathd order paths for better throughput in round-robin mode +- Resolves: bz #1069360, #1066264, #1109995, #1080055, #1110000, #1110006 +- Resolves: bz #1110007, #1110013, #1069811, #1110016, #1080038 + * Wed Mar 12 2014 Benjamin Marzinski 0.4.9-66 - Add 0080-RHBZ-1075796-cmdline-wwid.patch * add multipath option "-A" to add wwids specified by the kernel