From c896fb97e81fc836395a3dfd6496ed9610ac4fec Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 03 2016 06:19:36 +0000 Subject: import device-mapper-multipath-0.4.9-99.el7 --- diff --git a/SOURCES/0133-RHBZ-1241774-sun-partition-numbering.patch b/SOURCES/0133-RHBZ-1241774-sun-partition-numbering.patch new file mode 100644 index 0000000..1cf555f --- /dev/null +++ b/SOURCES/0133-RHBZ-1241774-sun-partition-numbering.patch @@ -0,0 +1,17 @@ +--- + kpartx/sun.c | 2 -- + 1 file changed, 2 deletions(-) + +Index: multipath-tools-130222/kpartx/sun.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/sun.c ++++ multipath-tools-130222/kpartx/sun.c +@@ -82,8 +82,6 @@ read_sun_pt(int fd, struct slice all, st + for(i=0, n=0; ipartitions[i]; + +- if (s->num_sectors == 0) +- continue; + if (n < ns) { + sp[n].start = offset + + be32_to_cpu(s->start_cylinder) * be16_to_cpu(l->nsect) * be16_to_cpu(l->ntrks); diff --git a/SOURCES/0133-RHBZ-1321019-wait-for-map-add.patch b/SOURCES/0133-RHBZ-1321019-wait-for-map-add.patch deleted file mode 100644 index 3ac3f77..0000000 --- a/SOURCES/0133-RHBZ-1321019-wait-for-map-add.patch +++ /dev/null @@ -1,495 +0,0 @@ ---- - libmultipath/config.c | 1 - libmultipath/config.h | 2 - libmultipath/configure.c | 4 + - libmultipath/defaults.h | 1 - libmultipath/dict.c | 25 +++++++++ - libmultipath/structs.h | 2 - multipath.conf.defaults | 1 - multipath/multipath.conf.5 | 8 +++ - multipathd/cli_handlers.c | 65 ++++++++++++++++++++---- - multipathd/main.c | 119 +++++++++++++++++++++++++++++++++++++++++++-- - multipathd/main.h | 1 - 11 files changed, 216 insertions(+), 13 deletions(-) - -Index: multipath-tools-130222/libmultipath/configure.c -=================================================================== ---- multipath-tools-130222.orig/libmultipath/configure.c -+++ multipath-tools-130222/libmultipath/configure.c -@@ -675,6 +675,10 @@ domap (struct multipath * mpp, char * pa - */ - if (mpp->action != ACT_CREATE) - mpp->action = ACT_NOTHING; -+ else { -+ mpp->wait_for_udev = 1; -+ mpp->uev_msg_tick = conf->uev_msg_delay; -+ } - } - dm_setgeometry(mpp); - return DOMAP_OK; -Index: multipath-tools-130222/libmultipath/structs.h -=================================================================== ---- multipath-tools-130222.orig/libmultipath/structs.h -+++ multipath-tools-130222/libmultipath/structs.h -@@ -217,6 +217,8 @@ struct multipath { - int bestpg; - int queuedio; - int action; -+ int wait_for_udev; -+ int uev_msg_tick; - int pgfailback; - int failback_tick; - int rr_weight; -Index: multipath-tools-130222/multipathd/cli_handlers.c -=================================================================== ---- multipath-tools-130222.orig/multipathd/cli_handlers.c -+++ multipath-tools-130222/multipathd/cli_handlers.c -@@ -548,6 +548,11 @@ cli_reload(void *v, char **reply, int *l - condlog(0, "%s: invalid map name. cannot reload", mapname); - return 1; - } -+ if (mpp->wait_for_udev) { -+ condlog(2, "%s: device not fully created, failing reload", -+ mpp->alias); -+ return 1; -+ } - - return reload_map(vecs, mpp, 0); - } -@@ -592,6 +597,12 @@ cli_resize(void *v, char **reply, int *l - return 1; - } - -+ if (mpp->wait_for_udev) { -+ condlog(2, "%s: device not fully created, failing resize", -+ mpp->alias); -+ return 1; -+ } -+ - pgp = VECTOR_SLOT(mpp->pg, 0); - - if (!pgp){ -@@ -756,6 +767,12 @@ cli_reconfigure(void * v, char ** reply, - { - struct vectors * vecs = (struct vectors *)data; - -+ if (need_to_delay_reconfig(vecs)) { -+ conf->delayed_reconfig = 1; -+ condlog(2, "delaying reconfigure (operator)"); -+ return 0; -+ } -+ - condlog(2, "reconfigure (operator)"); - - return reconfigure(vecs); -@@ -766,17 +783,25 @@ cli_suspend(void * v, char ** reply, int - { - struct vectors * vecs = (struct vectors *)data; - char * param = get_keyparam(v, MAP); -- int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0); -+ int r; -+ struct multipath * mpp; - - param = convert_dev(param, 0); -- condlog(2, "%s: suspend (operator)", param); -+ mpp = find_mp_by_alias(vecs->mpvec, param); -+ if (!mpp) -+ return 1; - -- if (!r) /* error */ -+ if (mpp->wait_for_udev) { -+ condlog(2, "%s: device not fully created, failing suspend", -+ mpp->alias); - return 1; -+ } - -- struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); -+ r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0); - -- if (!mpp) -+ condlog(2, "%s: suspend (operator)", param); -+ -+ if (!r) /* error */ - return 1; - - dm_get_info(param, &mpp->dmi); -@@ -788,17 +813,25 @@ cli_resume(void * v, char ** reply, int - { - struct vectors * vecs = (struct vectors *)data; - char * param = get_keyparam(v, MAP); -- int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); -+ int r; -+ struct multipath * mpp; - - param = convert_dev(param, 0); -- condlog(2, "%s: resume (operator)", param); -+ mpp = find_mp_by_alias(vecs->mpvec, param); -+ if (!mpp) -+ return 1; - -- if (!r) /* error */ -+ if (mpp->wait_for_udev) { -+ condlog(2, "%s: device not fully created, failing resume", -+ mpp->alias); - return 1; -+ } - -- struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); -+ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); - -- if (!mpp) -+ condlog(2, "%s: resume (operator)", param); -+ -+ if (!r) /* error */ - return 1; - - dm_get_info(param, &mpp->dmi); -@@ -831,9 +864,21 @@ cli_reinstate(void * v, char ** reply, i - int - cli_reassign (void * v, char ** reply, int * len, void * data) - { -+ struct vectors * vecs = (struct vectors *)data; - char * param = get_keyparam(v, MAP); -+ struct multipath *mpp; - - param = convert_dev(param, 0); -+ mpp = find_mp_by_alias(vecs->mpvec, param); -+ if (!mpp) -+ return 1; -+ -+ if (mpp->wait_for_udev) { -+ condlog(2, "%s: device not fully created, failing reassign", -+ mpp->alias); -+ return 1; -+ } -+ - condlog(3, "%s: reset devices (operator)", param); - - dm_reassign(param); -Index: multipath-tools-130222/libmultipath/config.h -=================================================================== ---- multipath-tools-130222.orig/libmultipath/config.h -+++ multipath-tools-130222/libmultipath/config.h -@@ -142,6 +142,8 @@ struct config { - int retrigger_tries; - int retrigger_delay; - int new_bindings_in_boot; -+ int delayed_reconfig; -+ int uev_msg_delay; - unsigned int version[3]; - - char * dev; -Index: multipath-tools-130222/multipathd/main.c -=================================================================== ---- multipath-tools-130222.orig/multipathd/main.c -+++ multipath-tools-130222/multipathd/main.c -@@ -251,6 +251,47 @@ flush_map(struct multipath * mpp, struct - return 0; - } - -+int -+update_map (struct multipath *mpp, struct vectors *vecs) -+{ -+ int retries = 3; -+ char params[PARAMS_SIZE] = {0}; -+ -+retry: -+ condlog(4, "%s: updating new map", mpp->alias); -+ if (adopt_paths(vecs->pathvec, mpp, 1)) { -+ condlog(0, "%s: failed to adopt paths for new map update", -+ mpp->alias); -+ retries = -1; -+ goto fail; -+ } -+ verify_paths(mpp, vecs, NULL); -+ mpp->flush_on_last_del = FLUSH_UNDEF; -+ mpp->action = ACT_RELOAD; -+ -+ if (setup_map(mpp, params, PARAMS_SIZE)) { -+ condlog(0, "%s: failed to setup new map in update", mpp->alias); -+ retries = -1; -+ goto fail; -+ } -+ if (domap(mpp, params) <= 0 && retries-- > 0) { -+ condlog(0, "%s: map_udate sleep", mpp->alias); -+ sleep(1); -+ goto retry; -+ } -+ dm_lib_release(); -+ -+fail: -+ if (setup_multipath(vecs, mpp)) -+ return 1; -+ -+ sync_map_state(mpp); -+ -+ if (retries < 0) -+ condlog(0, "%s: failed reload in new map update", mpp->alias); -+ return 0; -+} -+ - static int - uev_add_map (struct uevent * uev, struct vectors * vecs) - { -@@ -293,6 +334,20 @@ ev_add_map (char * dev, char * alias, st - mpp = find_mp_by_alias(vecs->mpvec, alias); - - if (mpp) { -+ if (mpp->wait_for_udev > 1) { -+ if (update_map(mpp, vecs)) -+ /* setup multipathd removed the map */ -+ return 1; -+ } -+ if (mpp->wait_for_udev) { -+ mpp->wait_for_udev = 0; -+ if (conf->delayed_reconfig && -+ !need_to_delay_reconfig(vecs)) { -+ condlog(2, "reconfigure (delayed)"); -+ reconfigure(vecs); -+ return 0; -+ } -+ } - /* - * Not really an error -- we generate our own uevent - * if we create a multipath mapped device as a result -@@ -471,7 +526,14 @@ ev_add_path (struct path * pp, struct ve - condlog(0, "%s: failed to get path uid", pp->dev); - goto fail; /* leave path added to pathvec */ - } -- mpp = pp->mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); -+ mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); -+ if (mpp && mpp->wait_for_udev) { -+ mpp->wait_for_udev = 2; -+ orphan_path(pp); -+ return 0; -+ } -+ -+ pp->mpp = mpp; - rescan: - if (mpp) { - if ((!pp->size) || (mpp->size != pp->size)) { -@@ -670,6 +732,12 @@ ev_remove_path (struct path *pp, struct - " removal of path %s", mpp->alias, pp->dev); - goto fail; - } -+ -+ if (mpp->wait_for_udev) { -+ mpp->wait_for_udev = 2; -+ goto out; -+ } -+ - /* - * reload the map - */ -@@ -731,6 +799,11 @@ uev_update_path (struct uevent *uev, str - condlog(2, "%s: update path write_protect to '%d' (uevent)", - uev->kernel, ro); - if (pp->mpp) { -+ if (pp->mpp->wait_for_udev) { -+ pp->mpp->wait_for_udev = 2; -+ return 0; -+ } -+ - retval = reload_map(vecs, pp->mpp, 0); - - condlog(2, "%s: map %s reloaded (retval %d)", -@@ -1063,6 +1136,20 @@ followover_should_failback(struct path * - } - - static void -+missing_uev_message_tick(vector mpvec) -+{ -+ struct multipath * mpp; -+ unsigned int i; -+ -+ vector_foreach_slot (mpvec, mpp, i) { -+ if (mpp->wait_for_udev && --mpp->uev_msg_tick <= 0) { -+ condlog(0, "%s: startup incomplete. Still waiting on udev", mpp->alias); -+ mpp->uev_msg_tick = conf->uev_msg_delay; -+ } -+ } -+} -+ -+static void - defered_failback_tick (vector mpvec) - { - struct multipath * mpp; -@@ -1316,6 +1403,9 @@ check_path (struct vectors * vecs, struc - - pp->state = newstate; - -+ -+ if (pp->mpp->wait_for_udev) -+ return; - /* - * path prio refreshing - */ -@@ -1369,6 +1459,7 @@ checkerloop (void *ap) - if (vecs->mpvec) { - defered_failback_tick(vecs->mpvec); - retry_count_tick(vecs->mpvec); -+ missing_uev_message_tick(vecs->mpvec); - } - if (count) - count--; -@@ -1464,6 +1555,22 @@ configure (struct vectors * vecs, int st - } - - int -+need_to_delay_reconfig(struct vectors * vecs) -+{ -+ struct multipath *mpp; -+ int i; -+ -+ if (!VECTOR_SIZE(vecs->mpvec)) -+ return 0; -+ -+ vector_foreach_slot(vecs->mpvec, mpp, i) { -+ if (mpp->wait_for_udev) -+ return 1; -+ } -+ return 0; -+} -+ -+int - reconfigure (struct vectors * vecs) - { - struct config * old = conf; -@@ -1543,12 +1650,18 @@ void - handle_signals(void) - { - if (reconfig_sig && running_state == DAEMON_RUNNING) { -- condlog(2, "reconfigure (signal)"); - pthread_cleanup_push(cleanup_lock, - &gvecs->lock); - lock(gvecs->lock); - pthread_testcancel(); -- reconfigure(gvecs); -+ if (need_to_delay_reconfig(gvecs)) { -+ conf->delayed_reconfig = 1; -+ condlog(2, "delaying reconfigure (signal)"); -+ } -+ else { -+ condlog(2, "reconfigure (signal)"); -+ reconfigure(gvecs); -+ } - lock_cleanup_pop(gvecs->lock); - } - if (log_reset_sig) { -Index: multipath-tools-130222/multipathd/main.h -=================================================================== ---- multipath-tools-130222.orig/multipathd/main.h -+++ multipath-tools-130222/multipathd/main.h -@@ -18,6 +18,7 @@ extern pid_t daemon_pid; - - void exit_daemon(void); - const char * daemon_status(void); -+int need_to_delay_reconfig (struct vectors *); - int reconfigure (struct vectors *); - int ev_add_path (struct path *, struct vectors *); - int ev_remove_path (struct path *, struct vectors *); -Index: multipath-tools-130222/libmultipath/config.c -=================================================================== ---- multipath-tools-130222.orig/libmultipath/config.c -+++ multipath-tools-130222/libmultipath/config.c -@@ -676,6 +676,7 @@ load_config (char * file, struct udev *u - conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; - conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; - conf->new_bindings_in_boot = 0; -+ conf->uev_msg_delay = DEFAULT_UEV_MSG_DELAY; - - /* - * preload default hwtable -Index: multipath-tools-130222/libmultipath/defaults.h -=================================================================== ---- multipath-tools-130222.orig/libmultipath/defaults.h -+++ multipath-tools-130222/libmultipath/defaults.h -@@ -23,6 +23,7 @@ - #define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF - #define DEFAULT_RETRIGGER_DELAY 10 - #define DEFAULT_RETRIGGER_TRIES 3 -+#define DEFAULT_UEV_MSG_DELAY 30 - - #define DEFAULT_CHECKINT 5 - #define MAX_CHECKINT(a) (a << 2) -Index: multipath-tools-130222/libmultipath/dict.c -=================================================================== ---- multipath-tools-130222.orig/libmultipath/dict.c -+++ multipath-tools-130222/libmultipath/dict.c -@@ -872,6 +872,24 @@ def_retrigger_delay_handler(vector strve - } - - static int -+def_uev_msg_delay_handler(vector strvec) -+{ -+ char *buff; -+ -+ buff = set_value(strvec); -+ -+ if (!buff) -+ return 1; -+ -+ conf->uev_msg_delay = atoi(buff); -+ if (conf->uev_msg_delay <= 0) -+ conf->uev_msg_delay = DEFAULT_UEV_MSG_DELAY; -+ FREE(buff); -+ -+ return 0; -+} -+ -+static int - def_new_bindings_in_boot_handler(vector strvec) - { - char * buff; -@@ -3261,6 +3279,12 @@ snprint_def_retrigger_delay (char * buff - } - - static int -+snprint_def_uev_msg_delay (char * buff, int len, void * data) -+{ -+ return snprintf(buff, len, "%i", conf->uev_msg_delay); -+} -+ -+static int - snprint_def_new_bindings_in_boot(char * buff, int len, void * data) - { - if (conf->new_bindings_in_boot == 1) -@@ -3345,6 +3369,7 @@ init_keywords(void) - install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks); - install_keyword("retrigger_tries", &def_retrigger_tries_handler, &snprint_def_retrigger_tries); - install_keyword("retrigger_delay", &def_retrigger_delay_handler, &snprint_def_retrigger_delay); -+ install_keyword("missing_uev_msg_delay", &def_uev_msg_delay_handler, &snprint_def_uev_msg_delay); - install_keyword("new_bindings_in_boot", &def_new_bindings_in_boot_handler, &snprint_def_new_bindings_in_boot); - __deprecated install_keyword("default_selector", &def_selector_handler, NULL); - __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); -Index: multipath-tools-130222/multipath.conf.defaults -=================================================================== ---- multipath-tools-130222.orig/multipath.conf.defaults -+++ multipath-tools-130222/multipath.conf.defaults -@@ -29,6 +29,7 @@ - # config_dir "/etc/multipath/conf.d" - # delay_watch_checks no - # delay_wait_checks no -+# missing_uev_msg_delay 30 - #} - #blacklist { - # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" -Index: multipath-tools-130222/multipath/multipath.conf.5 -=================================================================== ---- multipath-tools-130222.orig/multipath/multipath.conf.5 -+++ multipath-tools-130222/multipath/multipath.conf.5 -@@ -478,6 +478,14 @@ used until it has passed - .I delay_wait_checks - checks. Default is - .I no -+.TP -+.B missing_uev_msg_delay -+Controls how long multipathd will wait, after a new multipath device is created, -+to receive a change event from udev for the device, before printing a warning -+message. This warning message will print every -+.I missing_uev_msg_delay -+seconds until the uevent is received. the default is -+.I 30 - . - .SH "blacklist section" - The diff --git a/SOURCES/0134-RHBZ-1241528-check-mpath-prefix.patch b/SOURCES/0134-RHBZ-1241528-check-mpath-prefix.patch new file mode 100644 index 0000000..9701a36 --- /dev/null +++ b/SOURCES/0134-RHBZ-1241528-check-mpath-prefix.patch @@ -0,0 +1,168 @@ +--- + libmpathpersist/mpath_persist.c | 4 +- + libmultipath/devmapper.c | 67 +++++++++++++++++++++++++++++----------- + libmultipath/devmapper.h | 1 + multipathd/main.c | 2 - + 4 files changed, 53 insertions(+), 21 deletions(-) + +Index: multipath-tools-130222/libmpathpersist/mpath_persist.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.c ++++ multipath-tools-130222/libmpathpersist/mpath_persist.c +@@ -160,7 +160,7 @@ int mpath_persistent_reserve_in (int fd, + + condlog(3, "alias = %s", alias); + map_present = dm_map_present(alias); +- if (map_present && dm_type(alias, TGT_MPATH) <= 0){ ++ if (map_present && !dm_is_mpath(alias)){ + condlog( 0, "%s: not a multipath device.", alias); + ret = MPATH_PR_DMMP_ERROR; + goto out; +@@ -250,7 +250,7 @@ int mpath_persistent_reserve_out ( int f + condlog(3, "alias = %s", alias); + map_present = dm_map_present(alias); + +- if (map_present && dm_type(alias, TGT_MPATH) <= 0){ ++ if (map_present && !dm_is_mpath(alias)){ + condlog(3, "%s: not a multipath device.", alias); + ret = MPATH_PR_DMMP_ERROR; + goto out; +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -564,6 +564,48 @@ out: + return r; + } + ++extern int ++dm_is_mpath(const char * name) ++{ ++ int r = 0; ++ struct dm_task *dmt; ++ struct dm_info info; ++ uint64_t start, length; ++ char *target_type = NULL; ++ char *params; ++ const char *uuid; ++ ++ if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) ++ return 0; ++ ++ if (!dm_task_set_name(dmt, name)) ++ goto out; ++ ++ dm_task_no_open_count(dmt); ++ ++ if (!dm_task_run(dmt)) ++ goto out; ++ ++ if (!dm_task_get_info(dmt, &info) || !info.exists) ++ goto out; ++ ++ uuid = dm_task_get_uuid(dmt); ++ ++ if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0) ++ goto out; ++ ++ /* Fetch 1st target */ ++ dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms); ++ ++ if (!target_type || strcmp(target_type, TGT_MPATH) != 0) ++ goto out; ++ ++ r = 1; ++out: ++ dm_task_destroy(dmt); ++ return r; ++} ++ + static int + dm_dev_t (const char * mapname, char * dev_t, int len) + { +@@ -672,10 +714,7 @@ _dm_flush_map (const char * mapname, int + { + int r; + +- if (!dm_map_present(mapname)) +- return 0; +- +- if (dm_type(mapname, TGT_MPATH) <= 0) ++ if (!dm_is_mpath(mapname)) + return 0; /* nothing to do */ + + if (dm_remove_partmaps(mapname, need_sync, deferred_remove)) +@@ -725,10 +764,7 @@ dm_suspend_and_flush_map (const char * m + unsigned long long mapsize; + char params[PARAMS_SIZE] = {0}; + +- if (!dm_map_present(mapname)) +- return 0; +- +- if (dm_type(mapname, TGT_MPATH) <= 0) ++ if (!dm_is_mpath(mapname)) + return 0; /* nothing to do */ + + if (!dm_get_map(mapname, &mapsize, params)) { +@@ -899,7 +935,6 @@ dm_get_maps (vector mp) + { + struct multipath * mpp; + int r = 1; +- int info; + struct dm_task *dmt; + struct dm_names *names; + unsigned next = 0; +@@ -924,9 +959,7 @@ dm_get_maps (vector mp) + } + + do { +- info = dm_type(names->name, TGT_MPATH); +- +- if (info <= 0) ++ if (!dm_is_mpath(names->name)) + goto next; + + mpp = alloc_multipath(); +@@ -939,13 +972,11 @@ dm_get_maps (vector mp) + if (!mpp->alias) + goto out1; + +- if (info > 0) { +- if (dm_get_map(names->name, &mpp->size, NULL)) +- goto out1; ++ if (dm_get_map(names->name, &mpp->size, NULL)) ++ goto out1; + +- dm_get_uuid(names->name, mpp->wwid); +- dm_get_info(names->name, &mpp->dmi); +- } ++ dm_get_uuid(names->name, mpp->wwid); ++ dm_get_info(names->name, &mpp->dmi); + + if (!vector_alloc_slot(mp)) + goto out1; +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -23,6 +23,7 @@ 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_is_mpath(const char *); + 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) +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -285,7 +285,7 @@ ev_add_map (char * dev, char * alias, st + + map_present = dm_map_present(alias); + +- if (map_present && dm_type(alias, TGT_MPATH) <= 0) { ++ if (map_present && !dm_is_mpath(alias)) { + condlog(4, "%s: not a multipath map", alias); + return 0; + } diff --git a/SOURCES/0134-UPBZ-1328515-dont-fail-discovery.patch b/SOURCES/0134-UPBZ-1328515-dont-fail-discovery.patch deleted file mode 100644 index 742348f..0000000 --- a/SOURCES/0134-UPBZ-1328515-dont-fail-discovery.patch +++ /dev/null @@ -1,236 +0,0 @@ ---- - libmpathpersist/mpath_persist.c | 14 ++++++------ - libmultipath/discovery.c | 46 ++++++++++++++++++++-------------------- - libmultipath/discovery.h | 4 +++ - multipath/main.c | 2 - - multipathd/main.c | 6 +++-- - 5 files changed, 39 insertions(+), 33 deletions(-) - -Index: multipath-bz1328515/libmpathpersist/mpath_persist.c -=================================================================== ---- multipath-bz1328515.orig/libmpathpersist/mpath_persist.c -+++ multipath-bz1328515/libmpathpersist/mpath_persist.c -@@ -178,7 +178,7 @@ int mpath_persistent_reserve_in (int fd, - goto out; - } - -- if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) { -+ if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) { - ret = MPATH_PR_DMMP_ERROR; - goto out1; - } -@@ -262,13 +262,13 @@ int mpath_persistent_reserve_out ( int f - curmp = vector_alloc (); - pathvec = vector_alloc (); - -- if (!curmp || !pathvec){ -- condlog (0, "%s: vector allocation failed.", alias); -- ret = MPATH_PR_DMMP_ERROR; -- goto out; -- } -+ if (!curmp || !pathvec){ -+ condlog (0, "%s: vector allocation failed.", alias); -+ ret = MPATH_PR_DMMP_ERROR; -+ goto out; -+ } - -- if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) { -+ if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) { - ret = MPATH_PR_DMMP_ERROR; - goto out1; - } -Index: multipath-bz1328515/libmultipath/discovery.c -=================================================================== ---- multipath-bz1328515.orig/libmultipath/discovery.c -+++ multipath-bz1328515/libmultipath/discovery.c -@@ -32,7 +32,7 @@ int - store_pathinfo (vector pathvec, vector hwtable, struct udev_device *udevice, - int flag, struct path **pp_ptr) - { -- int err = 1; -+ int err = PATHINFO_FAILED; - struct path * pp; - const char * devname; - -@@ -41,12 +41,12 @@ store_pathinfo (vector pathvec, vector h - - devname = udev_device_get_sysname(udevice); - if (!devname) -- return 1; -+ return PATHINFO_FAILED; - - pp = alloc_path(); - - if (!pp) -- return 1; -+ return PATHINFO_FAILED; - - if(safe_sprintf(pp->dev, "%s", devname)) { - condlog(0, "pp->dev too small"); -@@ -80,19 +80,16 @@ path_discover (vector pathvec, struct co - - devname = udev_device_get_sysname(udevice); - if (!devname) -- return 0; -+ return PATHINFO_FAILED; - - if (filter_devnode(conf->blist_devnode, conf->elist_devnode, - (char *)devname) > 0) -- return 0; -+ return PATHINFO_SKIPPED; - - pp = find_path_by_dev(pathvec, (char *)devname); - if (!pp) { -- if (store_pathinfo(pathvec, conf->hwtable, -- udevice, flag, NULL) != 1) -- return 0; -- else -- return 1; -+ return store_pathinfo(pathvec, conf->hwtable, -+ udevice, flag, NULL); - } - return pathinfo(pp, conf->hwtable, flag); - } -@@ -104,11 +101,11 @@ path_discovery (vector pathvec, struct c - struct udev_list_entry *entry; - struct udev_device *udevice; - const char *devpath; -- int r = 0; -+ int num_paths = 0, total_paths = 0; - - udev_iter = udev_enumerate_new(conf->udev); - if (!udev_iter) -- return 1; -+ return -ENOMEM; - - udev_enumerate_add_match_subsystem(udev_iter, "block"); - udev_enumerate_scan_devices(udev_iter); -@@ -121,17 +118,20 @@ path_discovery (vector pathvec, struct c - udevice = udev_device_new_from_syspath(conf->udev, devpath); - if (!udevice) { - condlog(4, "%s: no udev information", devpath); -- r++; - continue; - } - devtype = udev_device_get_devtype(udevice); -- if(devtype && !strncmp(devtype, "disk", 4)) -- r += path_discover(pathvec, conf, udevice, flag); -+ if(devtype && !strncmp(devtype, "disk", 4)) { -+ total_paths++; -+ if (path_discover(pathvec, conf, -+ udevice, flag) == PATHINFO_OK) -+ num_paths++; -+ } - udev_device_unref(udevice); - } - udev_enumerate_unref(udev_iter); -- condlog(4, "Discovery status %d", r); -- return r; -+ condlog(4, "Discovered %d/%d paths", num_paths, total_paths); -+ return (total_paths - num_paths); - } - - #define declare_sysfs_get_str(fname) \ -@@ -1021,7 +1021,7 @@ get_state (struct path * pp, int daemon) - - if (!checker_selected(c)) { - if (daemon) { -- if (pathinfo(pp, conf->hwtable, DI_SYSFS) != 0) { -+ if (pathinfo(pp, conf->hwtable, DI_SYSFS) != PATHINFO_OK) { - condlog(3, "%s: couldn't get sysfs pathinfo", - pp->dev); - return PATH_UNCHECKED; -@@ -1140,7 +1140,7 @@ pathinfo (struct path *pp, vector hwtabl - int path_state; - - if (!pp) -- return 1; -+ return PATHINFO_FAILED; - - condlog(3, "%s: mask = 0x%x", pp->dev, mask); - -@@ -1148,12 +1148,12 @@ pathinfo (struct path *pp, vector hwtabl - * fetch info available in sysfs - */ - if (mask & DI_SYSFS && sysfs_pathinfo(pp)) -- return 1; -+ return PATHINFO_FAILED; - - if (mask & DI_BLACKLIST && mask & DI_SYSFS) { - if (filter_device(conf->blist_device, conf->elist_device, - pp->vendor_id, pp->product_id) > 0) { -- return 2; -+ return PATHINFO_SKIPPED; - } - } - -@@ -1199,7 +1199,7 @@ pathinfo (struct path *pp, vector hwtabl - if (mask & DI_BLACKLIST && mask & DI_WWID) { - if (filter_wwid(conf->blist_wwid, conf->elist_wwid, - pp->wwid) > 0) { -- return 2; -+ return PATHINFO_SKIPPED; - } - } - -@@ -1213,7 +1213,7 @@ pathinfo (struct path *pp, vector hwtabl - } - } - -- return 0; -+ return PATHINFO_OK; - - blank: - /* -Index: multipath-bz1328515/libmultipath/discovery.h -=================================================================== ---- multipath-bz1328515.orig/libmultipath/discovery.h -+++ multipath-bz1328515/libmultipath/discovery.h -@@ -24,6 +24,10 @@ - #define SCSI_COMMAND_TERMINATED 0x22 - #define SG_ERR_DRIVER_SENSE 0x08 - -+#define PATHINFO_OK 0 -+#define PATHINFO_FAILED 1 -+#define PATHINFO_SKIPPED 2 -+ - struct config; - - int sysfs_get_dev (struct udev_device *udev, char * buff, size_t len); -Index: multipath-bz1328515/multipath/main.c -=================================================================== ---- multipath-bz1328515.orig/multipath/main.c -+++ multipath-bz1328515/multipath/main.c -@@ -344,7 +344,7 @@ configure (void) - /* maximum info */ - di_flag = DI_ALL; - -- if (path_discovery(pathvec, conf, di_flag)) -+ if (path_discovery(pathvec, conf, di_flag) < 0) - goto out; - - if (conf->verbosity > 2) -Index: multipath-bz1328515/multipathd/main.c -=================================================================== ---- multipath-bz1328515.orig/multipathd/main.c -+++ multipath-bz1328515/multipathd/main.c -@@ -1481,7 +1481,7 @@ configure (struct vectors * vecs, int st - struct multipath * mpp; - struct path * pp; - vector mpvec; -- int i; -+ int i, ret; - - if (!vecs->pathvec && !(vecs->pathvec = vector_alloc())) - return 1; -@@ -1495,7 +1495,9 @@ configure (struct vectors * vecs, int st - /* - * probe for current path (from sysfs) and map (from dm) sets - */ -- path_discovery(vecs->pathvec, conf, DI_ALL); -+ ret = path_discovery(vecs->pathvec, conf, DI_ALL); -+ if (ret < 0) -+ return 1; - - vector_foreach_slot (vecs->pathvec, pp, i){ - if (filter_path(conf, pp) > 0){ diff --git a/SOURCES/0135-RHBZ-1299600-path-dev-uevents.patch b/SOURCES/0135-RHBZ-1299600-path-dev-uevents.patch new file mode 100644 index 0000000..2de58a4 --- /dev/null +++ b/SOURCES/0135-RHBZ-1299600-path-dev-uevents.patch @@ -0,0 +1,121 @@ +--- + libmultipath/configure.c | 30 ++++++++++++++++++++++++++++-- + libmultipath/configure.h | 1 + + libmultipath/wwids.c | 4 ++-- + multipath/main.c | 2 +- + multipathd/main.c | 3 ++- + 5 files changed, 34 insertions(+), 6 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -38,6 +38,7 @@ + #include "util.h" + #include "uxsock.h" + #include "wwids.h" ++#include "sysfs.h" + + /* group paths in pg by host adapter + */ +@@ -569,6 +570,29 @@ fail: + return 1; + } + ++void ++trigger_uevents (struct multipath *mpp) ++{ ++ struct pathgroup * pgp; ++ struct path * pp; ++ int i, j; ++ ++ if (!mpp || !mpp->pg) ++ return; ++ ++ vector_foreach_slot (mpp->pg, pgp, i) { ++ if (!pgp->paths) ++ continue; ++ vector_foreach_slot(pgp->paths, pp, j) { ++ if (!pp->udev) ++ continue; ++ sysfs_attr_set_value(pp->udev, "uevent", "change", ++ strlen("change")); ++ } ++ } ++} ++ ++ + /* + * Return value: + */ +@@ -658,8 +682,10 @@ domap (struct multipath * mpp, char * pa + * DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD + * succeeded + */ +- if (mpp->action == ACT_CREATE) +- remember_wwid(mpp->wwid); ++ if (mpp->action == ACT_CREATE) { ++ if (remember_wwid(mpp->wwid) == 1) ++ trigger_uevents(mpp); ++ } + if (!conf->daemon) { + /* multipath client mode */ + dm_switchgroup(mpp->alias, mpp->bestpg); +Index: multipath-tools-130222/libmultipath/wwids.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.c ++++ multipath-tools-130222/libmultipath/wwids.c +@@ -310,7 +310,7 @@ remember_wwid(char *wwid) + } + else + condlog(4, "wwid %s already in wwids file", wwid); +- return 0; ++ return ret; + } + + int remember_cmdline_wwid(void) +@@ -344,7 +344,7 @@ int remember_cmdline_wwid(void) + next++; + } + if (strlen(ptr)) { +- if (remember_wwid(ptr) != 0) ++ if (remember_wwid(ptr) < 0) + ret = -1; + } + else { +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -303,7 +303,7 @@ configure (void) + } + if (conf->cmd == CMD_ADD_WWID) { + r = remember_wwid(refwwid); +- if (r == 0) ++ if (r >= 0) + printf("wwid '%s' added\n", refwwid); + else + printf("failed adding '%s' to wwids file\n", +Index: multipath-tools-130222/libmultipath/configure.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.h ++++ multipath-tools-130222/libmultipath/configure.h +@@ -31,3 +31,4 @@ int coalesce_paths (struct vectors *vecs + int get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid); + int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh); + int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name); ++void trigger_uevents (struct multipath *mpp); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1435,7 +1435,8 @@ configure (struct vectors * vecs, int st + + sync_maps_state(mpvec); + vector_foreach_slot(mpvec, mpp, i){ +- remember_wwid(mpp->wwid); ++ if (remember_wwid(mpp->wwid) > 0) ++ trigger_uevents(mpp); + update_map_pr(mpp); + } + diff --git a/SOURCES/0135-RHBZ-1330480-kpartx-sync.patch b/SOURCES/0135-RHBZ-1330480-kpartx-sync.patch deleted file mode 100644 index ba95135..0000000 --- a/SOURCES/0135-RHBZ-1330480-kpartx-sync.patch +++ /dev/null @@ -1,59 +0,0 @@ ---- - kpartx/kpartx.c | 10 +++++++--- - multipath/multipath.rules | 2 +- - 2 files changed, 8 insertions(+), 4 deletions(-) - -Index: multipath-bz1330480/kpartx/kpartx.c -=================================================================== ---- multipath-bz1330480.orig/kpartx/kpartx.c -+++ multipath-bz1330480/kpartx/kpartx.c -@@ -57,7 +57,7 @@ struct pt { - } pts[MAXTYPES]; - - int ptct = 0; --int udev_sync = 0; -+int udev_sync = 1; - - static void - addpts(char *t, ptreader f) -@@ -85,7 +85,7 @@ initpts(void) - addpts("ps3", read_ps3_pt); - } - --static char short_opts[] = "rladfgvp:t:su"; -+static char short_opts[] = "rladfgvp:t:snu"; - - /* Used in gpt.c */ - int force_gpt=0; -@@ -104,7 +104,8 @@ usage(void) { - printf("\t-g force GUID partition table (GPT)\n"); - printf("\t-f force devmap create\n"); - printf("\t-v verbose\n"); -- printf("\t-s sync mode. Don't return until the partitions are created\n"); -+ printf("\t-n nosync mode. Return before the partitions are created\n"); -+ printf("\t-s sync mode. Don't return until the partitions are created. Default.\n"); - return 1; - } - -@@ -270,6 +271,9 @@ main(int argc, char **argv){ - case 's': - udev_sync = 1; - break; -+ case 'n': -+ udev_sync = 0; -+ break; - case 'u': - what = UPDATE; - break; -Index: multipath-bz1330480/multipath/multipath.rules -=================================================================== ---- multipath-bz1330480.orig/multipath/multipath.rules -+++ multipath-bz1330480/multipath/multipath.rules -@@ -48,6 +48,6 @@ ENV{DM_ACTIVATION}=="1", ENV{DM_MULTIPAT - ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" - ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" - ENV{DM_ACTIVATION}!="1", ENV{DM_MULTIPATH_NEED_KPARTX}!="1", GOTO="end_mpath" --RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode", \ -+RUN+="$env{MPATH_SBIN_PATH}/kpartx -an $tempnode", \ - ENV{DM_MULTIPATH_NEED_KPARTX}="" - LABEL="end_mpath" diff --git a/SOURCES/0136-RHBZ-1304687-wait-for-map-add.patch b/SOURCES/0136-RHBZ-1304687-wait-for-map-add.patch new file mode 100644 index 0000000..dbada98 --- /dev/null +++ b/SOURCES/0136-RHBZ-1304687-wait-for-map-add.patch @@ -0,0 +1,508 @@ +--- + libmultipath/config.c | 1 + libmultipath/config.h | 2 + libmultipath/configure.c | 4 + + libmultipath/defaults.h | 1 + libmultipath/dict.c | 25 ++++++++ + libmultipath/structs.h | 2 + multipath.conf.defaults | 1 + multipath/multipath.conf.5 | 8 ++ + multipathd/cli_handlers.c | 65 ++++++++++++++++++---- + multipathd/main.c | 132 +++++++++++++++++++++++++++++++++++++++++++-- + multipathd/main.h | 1 + 11 files changed, 229 insertions(+), 13 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -701,6 +701,10 @@ domap (struct multipath * mpp, char * pa + */ + if (mpp->action != ACT_CREATE) + mpp->action = ACT_NOTHING; ++ else { ++ mpp->wait_for_udev = 1; ++ mpp->uev_wait_tick = conf->uev_wait_timeout; ++ } + } + dm_setgeometry(mpp); + return DOMAP_OK; +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -217,6 +217,8 @@ struct multipath { + int bestpg; + int queuedio; + int action; ++ int wait_for_udev; ++ int uev_wait_tick; + int pgfailback; + int failback_tick; + int rr_weight; +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -548,6 +548,11 @@ cli_reload(void *v, char **reply, int *l + condlog(0, "%s: invalid map name. cannot reload", mapname); + return 1; + } ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing reload", ++ mpp->alias); ++ return 1; ++ } + + return reload_map(vecs, mpp, 0); + } +@@ -592,6 +597,12 @@ cli_resize(void *v, char **reply, int *l + return 1; + } + ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing resize", ++ mpp->alias); ++ return 1; ++ } ++ + pgp = VECTOR_SLOT(mpp->pg, 0); + + if (!pgp){ +@@ -756,6 +767,12 @@ cli_reconfigure(void * v, char ** reply, + { + struct vectors * vecs = (struct vectors *)data; + ++ if (need_to_delay_reconfig(vecs)) { ++ conf->delayed_reconfig = 1; ++ condlog(2, "delaying reconfigure (operator)"); ++ return 0; ++ } ++ + condlog(2, "reconfigure (operator)"); + + return reconfigure(vecs); +@@ -766,17 +783,25 @@ cli_suspend(void * v, char ** reply, int + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); +- int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0); ++ int r; ++ struct multipath * mpp; + + param = convert_dev(param, 0); +- condlog(2, "%s: suspend (operator)", param); ++ mpp = find_mp_by_alias(vecs->mpvec, param); ++ if (!mpp) ++ return 1; + +- if (!r) /* error */ ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing suspend", ++ mpp->alias); + return 1; ++ } + +- struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); ++ r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0); + +- if (!mpp) ++ condlog(2, "%s: suspend (operator)", param); ++ ++ if (!r) /* error */ + return 1; + + dm_get_info(param, &mpp->dmi); +@@ -788,17 +813,25 @@ cli_resume(void * v, char ** reply, int + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); +- int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); ++ int r; ++ struct multipath * mpp; + + param = convert_dev(param, 0); +- condlog(2, "%s: resume (operator)", param); ++ mpp = find_mp_by_alias(vecs->mpvec, param); ++ if (!mpp) ++ return 1; + +- if (!r) /* error */ ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing resume", ++ mpp->alias); + return 1; ++ } + +- struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); + +- if (!mpp) ++ condlog(2, "%s: resume (operator)", param); ++ ++ if (!r) /* error */ + return 1; + + dm_get_info(param, &mpp->dmi); +@@ -831,9 +864,21 @@ cli_reinstate(void * v, char ** reply, i + int + cli_reassign (void * v, char ** reply, int * len, void * data) + { ++ struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); ++ struct multipath *mpp; + + param = convert_dev(param, 0); ++ mpp = find_mp_by_alias(vecs->mpvec, param); ++ if (!mpp) ++ return 1; ++ ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing reassign", ++ mpp->alias); ++ return 1; ++ } ++ + condlog(3, "%s: reset devices (operator)", param); + + dm_reassign(param); +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -142,6 +142,8 @@ struct config { + int retrigger_tries; + int retrigger_delay; + int new_bindings_in_boot; ++ int delayed_reconfig; ++ int uev_wait_timeout; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -251,6 +251,47 @@ flush_map(struct multipath * mpp, struct + return 0; + } + ++int ++update_map (struct multipath *mpp, struct vectors *vecs) ++{ ++ int retries = 3; ++ char params[PARAMS_SIZE] = {0}; ++ ++retry: ++ condlog(4, "%s: updating new map", mpp->alias); ++ if (adopt_paths(vecs->pathvec, mpp, 1)) { ++ condlog(0, "%s: failed to adopt paths for new map update", ++ mpp->alias); ++ retries = -1; ++ goto fail; ++ } ++ verify_paths(mpp, vecs, NULL); ++ mpp->flush_on_last_del = FLUSH_UNDEF; ++ mpp->action = ACT_RELOAD; ++ ++ if (setup_map(mpp, params, PARAMS_SIZE)) { ++ condlog(0, "%s: failed to setup new map in update", mpp->alias); ++ retries = -1; ++ goto fail; ++ } ++ if (domap(mpp, params) <= 0 && retries-- > 0) { ++ condlog(0, "%s: map_udate sleep", mpp->alias); ++ sleep(1); ++ goto retry; ++ } ++ dm_lib_release(); ++ ++fail: ++ if (setup_multipath(vecs, mpp)) ++ return 1; ++ ++ sync_map_state(mpp); ++ ++ if (retries < 0) ++ condlog(0, "%s: failed reload in new map update", mpp->alias); ++ return 0; ++} ++ + static int + uev_add_map (struct uevent * uev, struct vectors * vecs) + { +@@ -293,6 +334,20 @@ ev_add_map (char * dev, char * alias, st + mpp = find_mp_by_alias(vecs->mpvec, alias); + + if (mpp) { ++ if (mpp->wait_for_udev > 1) { ++ if (update_map(mpp, vecs)) ++ /* setup multipathd removed the map */ ++ return 1; ++ } ++ if (mpp->wait_for_udev) { ++ mpp->wait_for_udev = 0; ++ if (conf->delayed_reconfig && ++ !need_to_delay_reconfig(vecs)) { ++ condlog(2, "reconfigure (delayed)"); ++ reconfigure(vecs); ++ return 0; ++ } ++ } + /* + * Not really an error -- we generate our own uevent + * if we create a multipath mapped device as a result +@@ -471,7 +526,14 @@ ev_add_path (struct path * pp, struct ve + condlog(0, "%s: failed to get path uid", pp->dev); + goto fail; /* leave path added to pathvec */ + } +- mpp = pp->mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); ++ mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); ++ if (mpp && mpp->wait_for_udev) { ++ mpp->wait_for_udev = 2; ++ orphan_path(pp); ++ return 0; ++ } ++ ++ pp->mpp = mpp; + rescan: + if (mpp) { + if ((!pp->size) || (mpp->size != pp->size)) { +@@ -670,6 +732,12 @@ ev_remove_path (struct path *pp, struct + " removal of path %s", mpp->alias, pp->dev); + goto fail; + } ++ ++ if (mpp->wait_for_udev) { ++ mpp->wait_for_udev = 2; ++ goto out; ++ } ++ + /* + * reload the map + */ +@@ -731,6 +799,11 @@ uev_update_path (struct uevent *uev, str + condlog(2, "%s: update path write_protect to '%d' (uevent)", + uev->kernel, ro); + if (pp->mpp) { ++ if (pp->mpp->wait_for_udev) { ++ pp->mpp->wait_for_udev = 2; ++ return 0; ++ } ++ + retval = reload_map(vecs, pp->mpp, 0); + + condlog(2, "%s: map %s reloaded (retval %d)", +@@ -1063,6 +1136,33 @@ followover_should_failback(struct path * + } + + static void ++missing_uev_wait_tick(struct vectors *vecs) ++{ ++ struct multipath * mpp; ++ unsigned int i; ++ int timed_out = 0; ++ ++ vector_foreach_slot (vecs->mpvec, mpp, i) { ++ if (mpp->wait_for_udev && --mpp->uev_wait_tick <= 0) { ++ timed_out = 1; ++ condlog(0, "%s: timeout waiting on creation uevent. enabling reloads", mpp->alias); ++ if (mpp->wait_for_udev > 1 && update_map(mpp, vecs)) { ++ /* update_map removed map */ ++ i--; ++ continue; ++ } ++ mpp->wait_for_udev = 0; ++ } ++ } ++ ++ if (timed_out && conf->delayed_reconfig && ++ !need_to_delay_reconfig(vecs)) { ++ condlog(2, "reconfigure (delayed)"); ++ reconfigure(vecs); ++ } ++} ++ ++static void + defered_failback_tick (vector mpvec) + { + struct multipath * mpp; +@@ -1316,6 +1416,9 @@ check_path (struct vectors * vecs, struc + + pp->state = newstate; + ++ ++ if (pp->mpp->wait_for_udev) ++ return; + /* + * path prio refreshing + */ +@@ -1369,6 +1472,7 @@ checkerloop (void *ap) + if (vecs->mpvec) { + defered_failback_tick(vecs->mpvec); + retry_count_tick(vecs->mpvec); ++ missing_uev_wait_tick(vecs); + } + if (count) + count--; +@@ -1465,6 +1569,22 @@ configure (struct vectors * vecs, int st + } + + int ++need_to_delay_reconfig(struct vectors * vecs) ++{ ++ struct multipath *mpp; ++ int i; ++ ++ if (!VECTOR_SIZE(vecs->mpvec)) ++ return 0; ++ ++ vector_foreach_slot(vecs->mpvec, mpp, i) { ++ if (mpp->wait_for_udev) ++ return 1; ++ } ++ return 0; ++} ++ ++int + reconfigure (struct vectors * vecs) + { + struct config * old = conf; +@@ -1544,12 +1664,18 @@ void + handle_signals(void) + { + if (reconfig_sig && running_state == DAEMON_RUNNING) { +- condlog(2, "reconfigure (signal)"); + pthread_cleanup_push(cleanup_lock, + &gvecs->lock); + lock(gvecs->lock); + pthread_testcancel(); +- reconfigure(gvecs); ++ if (need_to_delay_reconfig(gvecs)) { ++ conf->delayed_reconfig = 1; ++ condlog(2, "delaying reconfigure (signal)"); ++ } ++ else { ++ condlog(2, "reconfigure (signal)"); ++ reconfigure(gvecs); ++ } + lock_cleanup_pop(gvecs->lock); + } + if (log_reset_sig) { +Index: multipath-tools-130222/multipathd/main.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.h ++++ multipath-tools-130222/multipathd/main.h +@@ -18,6 +18,7 @@ extern pid_t daemon_pid; + + void exit_daemon(void); + const char * daemon_status(void); ++int need_to_delay_reconfig (struct vectors *); + int reconfigure (struct vectors *); + int ev_add_path (struct path *, struct vectors *); + int ev_remove_path (struct path *, struct vectors *); +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -676,6 +676,7 @@ load_config (char * file, struct udev *u + conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; + conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; + conf->new_bindings_in_boot = 0; ++ conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT; + + /* + * preload default hwtable +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -23,6 +23,7 @@ + #define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF + #define DEFAULT_RETRIGGER_DELAY 10 + #define DEFAULT_RETRIGGER_TRIES 3 ++#define DEFAULT_UEV_WAIT_TIMEOUT 30 + + #define DEFAULT_CHECKINT 5 + #define MAX_CHECKINT(a) (a << 2) +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -872,6 +872,24 @@ def_retrigger_delay_handler(vector strve + } + + static int ++def_uev_wait_timeout_handler(vector strvec) ++{ ++ char *buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ conf->uev_wait_timeout = atoi(buff); ++ if (conf->uev_wait_timeout <= 0) ++ conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT; ++ FREE(buff); ++ ++ return 0; ++} ++ ++static int + def_new_bindings_in_boot_handler(vector strvec) + { + char * buff; +@@ -3261,6 +3279,12 @@ snprint_def_retrigger_delay (char * buff + } + + static int ++snprint_def_uev_wait_timeout (char * buff, int len, void * data) ++{ ++ return snprintf(buff, len, "%i", conf->uev_wait_timeout); ++} ++ ++static int + snprint_def_new_bindings_in_boot(char * buff, int len, void * data) + { + if (conf->new_bindings_in_boot == 1) +@@ -3345,6 +3369,7 @@ init_keywords(void) + install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks); + install_keyword("retrigger_tries", &def_retrigger_tries_handler, &snprint_def_retrigger_tries); + install_keyword("retrigger_delay", &def_retrigger_delay_handler, &snprint_def_retrigger_delay); ++ install_keyword("missing_uev_wait_timeout", &def_uev_wait_timeout_handler, &snprint_def_uev_wait_timeout); + install_keyword("new_bindings_in_boot", &def_new_bindings_in_boot_handler, &snprint_def_new_bindings_in_boot); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); +Index: multipath-tools-130222/multipath.conf.defaults +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.defaults ++++ multipath-tools-130222/multipath.conf.defaults +@@ -29,6 +29,7 @@ + # config_dir "/etc/multipath/conf.d" + # delay_watch_checks no + # delay_wait_checks no ++# missing_uev_wait_timeout 30 + #} + #blacklist { + # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -478,6 +478,14 @@ used until it has passed + .I delay_wait_checks + checks. Default is + .I no ++.TP ++.B missing_uev_wait_timeout ++Controls how many seconds multipathd will wait, after a new multipath device ++is created, to receive a change event from udev for the device, before ++automatically enabling device reloads. Usually multipathd will delay reloads ++on a device until it receives a change uevent from the initial table load. The ++default is ++.I 30 + . + .SH "blacklist section" + The diff --git a/SOURCES/0136-RHBZ-1335746-clear-chkr-msg.patch b/SOURCES/0136-RHBZ-1335746-clear-chkr-msg.patch deleted file mode 100644 index 3a25c5b..0000000 --- a/SOURCES/0136-RHBZ-1335746-clear-chkr-msg.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- - multipathd/main.c | 2 ++ - 1 file changed, 2 insertions(+) - -Index: multipath-7.2.z/multipathd/main.c -=================================================================== ---- multipath-7.2.z.orig/multipathd/main.c -+++ multipath-7.2.z/multipathd/main.c -@@ -1257,6 +1257,8 @@ check_path (struct vectors * vecs, struc - newstate = path_offline(pp); - if (newstate == PATH_UP) - newstate = get_state(pp, 1); -+ else -+ checker_clear_message(&pp->checker); - - if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) { - condlog(2, "%s: unusable path", pp->dev); diff --git a/SOURCES/0137-RHBZ-1280524-clear-chkr-msg.patch b/SOURCES/0137-RHBZ-1280524-clear-chkr-msg.patch new file mode 100644 index 0000000..c05e28e --- /dev/null +++ b/SOURCES/0137-RHBZ-1280524-clear-chkr-msg.patch @@ -0,0 +1,17 @@ +--- + multipathd/main.c | 2 ++ + 1 file changed, 2 insertions(+) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1270,6 +1270,8 @@ check_path (struct vectors * vecs, struc + newstate = path_offline(pp); + if (newstate == PATH_UP) + newstate = get_state(pp, 1); ++ else ++ checker_clear_message(&pp->checker); + + if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) { + condlog(2, "%s: unusable path", pp->dev); diff --git a/SOURCES/0137-RHBZ-1364905-ordering.patch b/SOURCES/0137-RHBZ-1364905-ordering.patch deleted file mode 100644 index b0794d9..0000000 --- a/SOURCES/0137-RHBZ-1364905-ordering.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- - multipathd/multipathd.service | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: multipath-1364905/multipathd/multipathd.service -=================================================================== ---- multipath-1364905.orig/multipathd/multipathd.service -+++ multipath-1364905/multipathd/multipathd.service -@@ -2,7 +2,7 @@ - Description=Device-Mapper Multipath Device Controller - Requires=blk-availability.service - Before=iscsi.service iscsid.service lvm2-activation-early.service --After=syslog.target -+After=syslog.target systemd-udev-trigger.service - ConditionPathExists=/etc/multipath.conf - ConditionKernelCommandLine=!nompath - DefaultDependencies=no diff --git a/SOURCES/0138-RHBZ-1288660-fix-mpathconf-allow.patch b/SOURCES/0138-RHBZ-1288660-fix-mpathconf-allow.patch new file mode 100644 index 0000000..9050fc7 --- /dev/null +++ b/SOURCES/0138-RHBZ-1288660-fix-mpathconf-allow.patch @@ -0,0 +1,86 @@ +--- + multipath/mpathconf | 37 ++++++++++++++++++++++++++----------- + 1 file changed, 26 insertions(+), 11 deletions(-) + +Index: multipath-tools-130222/multipath/mpathconf +=================================================================== +--- multipath-tools-130222.orig/multipath/mpathconf ++++ multipath-tools-130222/multipath/mpathconf +@@ -42,6 +42,19 @@ function usage + echo "" + } + ++function add_wwid ++{ ++ INDEX=0 ++ while [ "$INDEX" -lt "$WWIDS" ] ; do ++ if [ "$1" = "${WWID_LIST[$INDEX]}" ] ; then ++ return ++ fi ++ ((INDEX++)) ++ done ++ WWID_LIST[$WWIDS]="$1" ++ ((WWIDS++)) ++} ++ + function get_dm_deps + { + shift 3 +@@ -59,11 +72,9 @@ function get_dm_deps + function set_dm_wwid + { + if [[ "$1" =~ ^part[[:digit:]]+-mpath- ]] ; then +- WWID_LIST[$WWIDS]="${1##part*-mpath-}" +- ((WWIDS++)) ++ add_wwid "${1##part*-mpath-}" + elif [[ "$1" =~ ^mpath- ]] ; then +- WWID_LIST[$WWIDS]="${1##mpath-}" +- ((WWIDS++)) ++ add_wwid "${1##mpath-}" + else + get_dm_deps `dmsetup deps -u $1` + fi +@@ -82,8 +93,7 @@ function set_wwid + if [ -n "$UUID" ] ; then + set_dm_wwid $UUID + else +- WWID_LIST[$WWIDS]="$1" +- ((WWIDS++)) ++ add_wwid "$1" + fi + } + +@@ -198,13 +208,13 @@ function validate_args + + function add_blacklist_exceptions + { +- echo "blacklist_exceptions {" >> $TMPFILE + INDEX=0 + while [ "$INDEX" -lt "$WWIDS" ] ; do +- echo " wwid \"${WWID_LIST[$INDEX]}\"" >> $TMPFILE ++ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\ ++ wwid '"\"${WWID_LIST[$INDEX]}\""' ++' $TMPFILE + ((INDEX++)) + done +- echo "}" >> $TMPFILE + } + + umask 0077 +@@ -350,9 +360,14 @@ if [ "$ENABLE" = 2 ]; then + sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE + fi + if [ "$HAVE_EXCEPTIONS" = 1 ]; then +- sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/d' $TMPFILE ++ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE ++ else ++ cat >> $TMPFILE <<- _EOF_ ++ ++blacklist_exceptions { ++} ++_EOF_ + fi +- echo $HAVE_WWID_DISABLE + add_blacklist_exceptions + elif [ "$ENABLE" = 1 ]; then + if [ "$HAVE_DISABLE" = 1 ]; then diff --git a/SOURCES/0139-RHBZ-1273173-queue-no-daemon-doc.patch b/SOURCES/0139-RHBZ-1273173-queue-no-daemon-doc.patch new file mode 100644 index 0000000..da5f63d --- /dev/null +++ b/SOURCES/0139-RHBZ-1273173-queue-no-daemon-doc.patch @@ -0,0 +1,158 @@ +--- + multipath.conf.defaults | 54 ++++++++++++++++++++++++++++++++++++++------- + multipath/multipath.conf.5 | 2 - + 2 files changed, 47 insertions(+), 9 deletions(-) + +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -377,7 +377,7 @@ multipathd running, access to the paths + cannot be told to stop queueing IO. Setting queue_without_daemon to + .I no + , avoids this problem. Default is +-.I yes ++.I no + .TP + .B bindings_file + The full pathname of the binding file to be used when the user_friendly_names option is set. Defaults to +Index: multipath-tools-130222/multipath.conf.defaults +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.defaults ++++ multipath-tools-130222/multipath.conf.defaults +@@ -4,6 +4,9 @@ + #defaults { + # verbosity 2 + # polling_interval 5 ++# max_polling_interval 20 ++# reassign_maps "yes" ++# multipath_dir "/lib64/multipath" + # path_selector "service-time 0" + # path_grouping_policy "failover" + # uid_attribute "ID_SERIAL" +@@ -12,28 +15,36 @@ + # features "0" + # path_checker "directio" + # alias_prefix "mpath" ++# failback "manual" + # rr_min_io 1000 + # rr_min_io_rq 1 + # max_fds 1048576 + # rr_weight "uniform" +-# queue_without_daemon "yes" +-# pg_timeout "none" ++# queue_without_daemon "no" + # flush_on_last_del "no" + # user_friendly_names "no" + # fast_io_fail_tmo 5 + # bindings_file "/etc/multipath/bindings" + # wwids_file /etc/multipath/wwids + # log_checker_err always ++# find_multipaths no + # retain_attached_hw_handler no + # detect_prio no ++# hw_str_match no ++# force_sync no ++# deferred_remove no ++# ignore_new_boot_devs no + # config_dir "/etc/multipath/conf.d" + # delay_watch_checks no + # delay_wait_checks no ++# retrigger_tries 3 ++# retrigger_delay 10 + # missing_uev_wait_timeout 30 ++# new_bindings_in_boot no + #} + #blacklist { + # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" +-# devnode "^hd[a-z]" ++# devnode "^(td|hd|vd)[a-z]" + # devnode "^dcssblk[0-9]*" + # device { + # vendor "DGC" +@@ -68,7 +79,7 @@ + # product "Universal Xport" + # } + # device { +-# vendor "(LSI|ENGENIO)" ++# vendor "(NETAPP|LSI|ENGENIO)" + # product "Universal Xport" + # } + #} +@@ -666,7 +677,7 @@ + # features "2 pg_init_retries 50" + # hardware_handler "1 rdac" + # prio "rdac" +-# failback "immediate" ++# failback immediate + # rr_weight "uniform" + # no_path_retry 15 + # } +@@ -679,7 +690,7 @@ + # features "2 pg_init_retries 50" + # hardware_handler "1 rdac" + # prio "rdac" +-# failback "immediate" ++# failback immediate + # rr_weight "uniform" + # no_path_retry 15 + # } +@@ -696,6 +707,7 @@ + # rr_min_io 128 + # flush_on_last_del "yes" + # dev_loss_tmo "infinity" ++# user_friendly_names no + # retain_attached_hw_handler yes + # detect_prio yes + # } +@@ -876,7 +888,7 @@ + # rr_min_io_rq 1 + # } + # device { +-# vendor "(LSI|ENGENIO)" ++# vendor "(NETAPP|LSI|ENGENIO)" + # product "INF-01-00" + # product_blacklist "Universal Xport" + # path_grouping_policy "group_by_prio" +@@ -886,7 +898,9 @@ + # prio "rdac" + # failback immediate + # rr_weight "uniform" +-# no_path_retry 15 ++# no_path_retry 30 ++# retain_attached_hw_handler yes ++# detect_prio yes + # } + # device { + # vendor "STK" +@@ -925,6 +939,30 @@ + # rr_weight "uniform" + # no_path_retry "queue" + # } ++# device { ++# vendor "DataCore" ++# product "Virtual Disk" ++# path_grouping_policy "group_by_prio" ++# path_checker "tur" ++# features "0" ++# hardware_handler "0" ++# prio "alua" ++# failback immediate ++# rr_weight "uniform" ++# no_path_retry "queue" ++# } ++# device { ++# vendor "XtremIO" ++# product "XtremApp" ++# path_grouping_policy "multibus" ++# path_selector "queue-length 0" ++# path_checker "directio" ++# features "0" ++# hardware_handler "0" ++# prio "const" ++# failback immediate ++# fast_io_fail_tmo 15 ++# } + #} + #multipaths { + #} diff --git a/SOURCES/0140-RHBZ-1299647-fix-help.patch b/SOURCES/0140-RHBZ-1299647-fix-help.patch new file mode 100644 index 0000000..c504974 --- /dev/null +++ b/SOURCES/0140-RHBZ-1299647-fix-help.patch @@ -0,0 +1,16 @@ +--- + multipath/main.c | 1 - + 1 file changed, 1 deletion(-) + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -111,7 +111,6 @@ usage (char * progname) + " -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" \ + " -w remove a device from the wwids file\n" \ + " -W reset the wwids file include only the current devices\n" \ diff --git a/SOURCES/0141-RHBZ-1303953-mpathpersist-typo.patch b/SOURCES/0141-RHBZ-1303953-mpathpersist-typo.patch new file mode 100644 index 0000000..7525902 --- /dev/null +++ b/SOURCES/0141-RHBZ-1303953-mpathpersist-typo.patch @@ -0,0 +1,17 @@ +--- + libmpathpersist/mpath_persist.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmpathpersist/mpath_persist.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.c ++++ multipath-tools-130222/libmpathpersist/mpath_persist.c +@@ -822,7 +822,7 @@ int update_map_pr(struct multipath *mpp) + if (!mpp->reservation_key) + { + /* Nothing to do. Assuming pr mgmt feature is disabled*/ +- condlog(3, "%s: reservation_key not set in multiapth.conf", mpp->alias); ++ condlog(3, "%s: reservation_key not set in multipath.conf", mpp->alias); + return MPATH_PR_SUCCESS; + } + diff --git a/SOURCES/0142-RHBZ-1283750-kpartx-fix.patch b/SOURCES/0142-RHBZ-1283750-kpartx-fix.patch new file mode 100644 index 0000000..0bc21b8 --- /dev/null +++ b/SOURCES/0142-RHBZ-1283750-kpartx-fix.patch @@ -0,0 +1,189 @@ +--- + kpartx/devmapper.c | 17 +++++++++++++-- + kpartx/devmapper.h | 2 - + kpartx/kpartx.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++--- + 3 files changed, 69 insertions(+), 7 deletions(-) + +Index: multipath-tools-130222/kpartx/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.c ++++ multipath-tools-130222/kpartx/devmapper.c +@@ -140,12 +140,16 @@ addout: + } + + extern int +-dm_map_present (char * str) ++dm_map_present (char * str, char **uuid) + { + int r = 0; + struct dm_task *dmt; ++ const char *uuidtmp; + struct dm_info info; + ++ if (uuid) ++ *uuid = NULL; ++ + if (!(dmt = dm_task_create(DM_DEVICE_INFO))) + return 0; + +@@ -160,8 +164,15 @@ dm_map_present (char * str) + if (!dm_task_get_info(dmt, &info)) + goto out; + +- if (info.exists) +- r = 1; ++ if (!info.exists) ++ goto out; ++ ++ r = 1; ++ if (uuid) { ++ uuidtmp = dm_task_get_uuid(dmt); ++ if (uuidtmp && strlen(uuidtmp)) ++ *uuid = strdup(uuidtmp); ++ } + out: + dm_task_destroy(dmt); + return r; +Index: multipath-tools-130222/kpartx/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.h ++++ multipath-tools-130222/kpartx/devmapper.h +@@ -14,7 +14,7 @@ int dm_prereq (char *, int, int, int); + int dm_simplecmd (int, const char *, int, uint32_t *, uint16_t); + int dm_addmap (int, const char *, const char *, const char *, uint64_t, + int, const char *, int, mode_t, uid_t, gid_t, uint32_t *); +-int dm_map_present (char *); ++int dm_map_present (char *, char **); + char * dm_mapname(int major, int minor); + dev_t dm_get_first_dep(char *devname); + char * dm_mapuuid(int major, int minor); +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -191,6 +191,21 @@ get_hotplug_device(void) + return device; + } + ++static int ++check_uuid(char *uuid, char *part_uuid, char **err_msg) { ++ char *map_uuid = strchr(part_uuid, '-'); ++ if (!map_uuid || strncmp(part_uuid, "part", 4) != 0) { ++ *err_msg = "not a kpartx partition"; ++ return -1; ++ } ++ map_uuid++; ++ if (strcmp(uuid, map_uuid) != 0) { ++ *err_msg = "a partition of a different device"; ++ return -1; ++ } ++ return 0; ++} ++ + int + main(int argc, char **argv){ + int i, j, m, n, op, off, arg, ro=0; +@@ -410,6 +425,8 @@ main(int argc, char **argv){ + + case DELETE: + for (j = MAXSLICES-1; j >= 0; j--) { ++ char *part_uuid, *reason; ++ + if (safe_sprintf(partname, "%s%s%d", + mapname, delim, j+1)) { + fprintf(stderr, "partname too small\n"); +@@ -417,9 +434,18 @@ main(int argc, char **argv){ + } + strip_slash(partname); + +- if (!dm_map_present(partname)) ++ if (!dm_map_present(partname, &part_uuid)) + continue; + ++ if (part_uuid && uuid) { ++ if (check_uuid(uuid, part_uuid, &reason) != 0) { ++ fprintf(stderr, "%s is %s. Not removing\n", partname, reason); ++ free(part_uuid); ++ continue; ++ } ++ free(part_uuid); ++ } ++ + if (!dm_simplecmd(DM_DEVICE_REMOVE, partname, + 0, &cookie, 0)) { + r++; +@@ -444,6 +470,8 @@ main(int argc, char **argv){ + case UPDATE: + /* ADD and UPDATE share the same code that adds new partitions. */ + for (j = 0; j < n; j++) { ++ char *part_uuid, *reason; ++ + if (slices[j].size == 0) + continue; + +@@ -460,9 +488,19 @@ main(int argc, char **argv){ + exit(1); + } + +- op = (dm_map_present(partname) ? ++ op = (dm_map_present(partname, &part_uuid) ? + DM_DEVICE_RELOAD : DM_DEVICE_CREATE); + ++ if (part_uuid && uuid) { ++ if (check_uuid(uuid, part_uuid, &reason) != 0) { ++ fprintf(stderr, "%s is already in use, and %s\n", partname, reason); ++ r++; ++ free(part_uuid); ++ continue; ++ } ++ free(part_uuid); ++ } ++ + if (!dm_addmap(op, partname, DM_TARGET, params, + slices[j].size, ro, uuid, j+1, + buf.st_mode & 0777, buf.st_uid, +@@ -470,6 +508,7 @@ main(int argc, char **argv){ + fprintf(stderr, "create/reload failed on %s\n", + partname); + r++; ++ continue; + } + if (op == DM_DEVICE_RELOAD && + !dm_simplecmd(DM_DEVICE_RESUME, partname, +@@ -477,6 +516,7 @@ main(int argc, char **argv){ + fprintf(stderr, "resume failed on %s\n", + partname); + r++; ++ continue; + } + dm_devn(partname, &slices[j].major, + &slices[j].minor); +@@ -494,6 +534,7 @@ main(int argc, char **argv){ + } + + for (j = MAXSLICES-1; j >= 0; j--) { ++ char *part_uuid, *reason; + if (safe_sprintf(partname, "%s%s%d", + mapname, delim, j+1)) { + fprintf(stderr, "partname too small\n"); +@@ -501,9 +542,19 @@ main(int argc, char **argv){ + } + strip_slash(partname); + +- if (slices[j].size || !dm_map_present(partname)) ++ if (slices[j].size || ++ !dm_map_present(partname, &part_uuid)) + continue; + ++ if (part_uuid && uuid) { ++ if (check_uuid(uuid, part_uuid, &reason) != 0) { ++ fprintf(stderr, "%s is %s. Not removing\n", partname, reason); ++ free(part_uuid); ++ continue; ++ } ++ free(part_uuid); ++ } ++ + if (!dm_simplecmd(DM_DEVICE_REMOVE, + partname, 1, &cookie, 0)) { + r++; diff --git a/SOURCES/0143-RHBZ-1299648-kpartx-sync.patch b/SOURCES/0143-RHBZ-1299648-kpartx-sync.patch new file mode 100644 index 0000000..5e9928d --- /dev/null +++ b/SOURCES/0143-RHBZ-1299648-kpartx-sync.patch @@ -0,0 +1,59 @@ +--- + kpartx/kpartx.c | 10 +++++++--- + multipath/multipath.rules | 2 +- + 2 files changed, 8 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -57,7 +57,7 @@ struct pt { + } pts[MAXTYPES]; + + int ptct = 0; +-int udev_sync = 0; ++int udev_sync = 1; + + static void + addpts(char *t, ptreader f) +@@ -85,7 +85,7 @@ initpts(void) + addpts("ps3", read_ps3_pt); + } + +-static char short_opts[] = "rladfgvp:t:su"; ++static char short_opts[] = "rladfgvp:t:snu"; + + /* Used in gpt.c */ + int force_gpt=0; +@@ -104,7 +104,8 @@ usage(void) { + printf("\t-g force GUID partition table (GPT)\n"); + printf("\t-f force devmap create\n"); + printf("\t-v verbose\n"); +- printf("\t-s sync mode. Don't return until the partitions are created\n"); ++ printf("\t-n nosync mode. Return before the partitions are created\n"); ++ printf("\t-s sync mode. Don't return until the partitions are created. Default.\n"); + return 1; + } + +@@ -285,6 +286,9 @@ main(int argc, char **argv){ + case 's': + udev_sync = 1; + break; ++ case 'n': ++ udev_sync = 0; ++ break; + case 'u': + what = UPDATE; + break; +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -48,6 +48,6 @@ ENV{DM_ACTIVATION}=="1", ENV{DM_MULTIPAT + ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" + ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" + ENV{DM_ACTIVATION}!="1", ENV{DM_MULTIPATH_NEED_KPARTX}!="1", GOTO="end_mpath" +-RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode", \ ++RUN+="$env{MPATH_SBIN_PATH}/kpartx -an $tempnode", \ + ENV{DM_MULTIPATH_NEED_KPARTX}="" + LABEL="end_mpath" diff --git a/SOURCES/0144-RHBZ-1299652-alua-pref-arg.patch b/SOURCES/0144-RHBZ-1299652-alua-pref-arg.patch new file mode 100644 index 0000000..9ae0b40 --- /dev/null +++ b/SOURCES/0144-RHBZ-1299652-alua-pref-arg.patch @@ -0,0 +1,136 @@ +--- + libmultipath/prioritizers/alua.c | 20 +++++++++++++++++++- + libmultipath/propsel.c | 18 ++++++++++-------- + multipath/multipath.conf.5 | 19 ++++++++++++++++--- + 3 files changed, 45 insertions(+), 12 deletions(-) + +Index: multipath-tools-130222/libmultipath/prioritizers/alua.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua.c ++++ multipath-tools-130222/libmultipath/prioritizers/alua.c +@@ -86,15 +86,33 @@ get_alua_info(int fd, struct alua_contex + return rc; + } + ++int get_exclusive_perf_arg(char *args) ++{ ++ char *ptr; ++ ++ if (args == NULL) ++ return 0; ++ ptr = strstr(args, "exclusive_pref_bit"); ++ if (!ptr) ++ return 0; ++ if (ptr[18] != '\0' && ptr[18] != ' ' && ptr[18] != '\t') ++ return 0; ++ if (ptr != args && ptr[-1] != ' ' && ptr[-1] != '\t') ++ return 0; ++ return 1; ++} ++ + int getprio (struct path * pp, char * args) + { + int rc; + int aas; + int priopath; ++ int exclusive_perf; + + if (pp->fd < 0) + return -ALUA_PRIO_NO_INFORMATION; + ++ exclusive_perf = get_exclusive_perf_arg(args); + rc = get_alua_info(pp->fd, pp->prio.context); + if (rc >= 0) { + aas = (rc & 0x0f); +@@ -115,7 +133,7 @@ int getprio (struct path * pp, char * ar + default: + rc = 0; + } +- if (priopath && aas != AAS_OPTIMIZED) ++ if (priopath && (aas != AAS_OPTIMIZED || exclusive_perf)) + rc += 80; + } else { + switch(-rc) { +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -420,17 +420,19 @@ select_prio (struct path * pp) + if (prio_selected(p)) { + condlog(3, "%s: prio = %s (detected setting)", + pp->dev, prio_name(p)); ++ condlog(3, "%s: prio args = %s (detected setting)", ++ pp->dev, prio_args(p)); + return 0; + } + } + +- if ((mpe = find_mpe(pp->wwid))) { +- if (mpe->prio_name) { +- prio_get(p, mpe->prio_name, mpe->prio_args); +- condlog(3, "%s: prio = %s (LUN setting)", +- pp->dev, prio_name(p)); +- return 0; +- } ++ if ((mpe = find_mpe(pp->wwid)) && mpe->prio_name) { ++ prio_get(p, mpe->prio_name, mpe->prio_args); ++ condlog(3, "%s: prio = %s (LUN setting)", ++ pp->dev, prio_name(p)); ++ condlog(3, "%s: prio args = %s (LUN setting)", ++ pp->dev, prio_args(p)); ++ return 0; + } + + if (pp->hwe && pp->hwe->prio_name) { +@@ -452,7 +454,7 @@ select_prio (struct path * pp) + prio_get(p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS); + condlog(3, "%s: prio = %s (internal default)", + pp->dev, DEFAULT_PRIO); +- condlog(3, "%s: prio = %s (internal default)", ++ condlog(3, "%s: prio args = %s (internal default)", + pp->dev, DEFAULT_PRIO_ARGS); + 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 +@@ -182,7 +182,9 @@ Return a constant priority of \fI1\fR. + Generate the path priority for EMC arrays. + .TP + .B alua +-Generate the path priority based on the SCSI-3 ALUA settings. ++Generate the path priority based on the SCSI-3 ALUA settings. This prioritizer ++accepts the optional prio_arg ++.I exclusive_pref_bit + .TP + .B ontap + Generate the path priority for NetApp arrays. +@@ -208,14 +210,25 @@ Default value is \fBconst\fR. + .RE + .TP + .B prio_args +-Arguments to pass to to the prio function. Currently only used with +-.I weighted, which needs a value of the form ++Arguments to pass to to the prio function. This only applies to certain ++prioritizers ++.RS ++.TP 12 ++.B weighted ++Needs a value of the form + .I " ..." + .I hbtl + regex can be of SCSI H:B:T:L format Ex: 1:0:.:. , *:0:0:. + .I devname + regex can be of device name format Ex: sda , sd.e + .TP ++.B alua ++If ++.I exclusive_pref_bit ++is set, paths with the TPGS pref bit set will always be in their own path ++group. ++.RE ++.TP + .B features + Specify any device-mapper features to be used. Syntax is + .I num list diff --git a/SOURCES/0145-UP-resize-help-msg.patch b/SOURCES/0145-UP-resize-help-msg.patch new file mode 100644 index 0000000..33ca0f6 --- /dev/null +++ b/SOURCES/0145-UP-resize-help-msg.patch @@ -0,0 +1,172 @@ +diff --git a/multipathd/cli.c b/multipathd/cli.c +index acc4249..8d26956 100644 +--- a/multipathd/cli.c ++++ b/multipathd/cli.c +@@ -320,52 +320,90 @@ alloc_handlers (void) + } + + static int +-genhelp_sprint_aliases (char * reply, vector keys, struct key * refkw) ++genhelp_sprint_aliases (char * reply, int maxlen, vector keys, ++ struct key * refkw) + { +- int i, fwd = 0; ++ int i, len = 0; + struct key * kw; + +- vector_foreach_slot (keys, kw, i) +- if (kw->code == refkw->code && kw != refkw) +- fwd += sprintf(reply, "|%s", kw->str); ++ vector_foreach_slot (keys, kw, i) { ++ if (kw->code == refkw->code && kw != refkw) { ++ len += snprintf(reply + len, maxlen - len, ++ "|%s", kw->str); ++ if (len >= maxlen) ++ return len; ++ } ++ } + +- return fwd; ++ return len; + } + +-static char * +-genhelp_handler (void) +-{ ++static int ++do_genhelp(char *reply, int maxlen) { ++ int len = 0; + int i, j; + unsigned long fp; + struct handler * h; + struct key * kw; +- char * reply; +- char * p; +- +- reply = MALLOC(INITIAL_REPLY_LEN); + +- if (!reply) +- return NULL; +- +- p = reply; +- p += sprintf(p, VERSION_STRING); +- p += sprintf(p, "CLI commands reference:\n"); ++ len += snprintf(reply + len, maxlen - len, VERSION_STRING); ++ if (len >= maxlen) ++ goto out; ++ len += snprintf(reply + len, maxlen - len, "CLI commands reference:\n"); ++ if (len >= maxlen) ++ goto out; + + vector_foreach_slot (handlers, h, i) { + fp = h->fingerprint; + vector_foreach_slot (keys, kw, j) { + if ((kw->code & fp)) { + fp -= kw->code; +- p += sprintf(p, " %s", kw->str); +- p += genhelp_sprint_aliases(p, keys, kw); +- +- if (kw->has_param) +- p += sprintf(p, " $%s", kw->str); ++ len += snprintf(reply + len , maxlen - len, ++ " %s", kw->str); ++ if (len >= maxlen) ++ goto out; ++ len += genhelp_sprint_aliases(reply + len, ++ maxlen - len, ++ keys, kw); ++ if (len >= maxlen) ++ goto out; ++ ++ if (kw->has_param) { ++ len += snprintf(reply + len, ++ maxlen - len, ++ " $%s", kw->str); ++ if (len >= maxlen) ++ goto out; ++ } + } + } +- p += sprintf(p, "\n"); ++ len += snprintf(reply + len, maxlen - len, "\n"); ++ if (len >= maxlen) ++ goto out; + } ++out: ++ return len; ++} ++ + ++static char * ++genhelp_handler (void) ++{ ++ char * reply; ++ char * p = NULL; ++ int maxlen = INITIAL_REPLY_LEN; ++ int again = 1; ++ ++ reply = MALLOC(maxlen); ++ ++ while (again) { ++ if (!reply) ++ return NULL; ++ p = reply; ++ p += do_genhelp(reply, maxlen); ++ again = ((p - reply) >= maxlen); ++ REALLOC_REPLY(reply, again, maxlen); ++ } + return reply; + } + +diff --git a/multipathd/cli.h b/multipathd/cli.h +index 09fdc68..2e0e1da 100644 +--- a/multipathd/cli.h ++++ b/multipathd/cli.h +@@ -71,7 +71,21 @@ enum { + #define SETPRSTATUS (1UL << __SETPRSTATUS) + #define UNSETPRSTATUS (1UL << __UNSETPRSTATUS) + +-#define INITIAL_REPLY_LEN 1100 ++#define INITIAL_REPLY_LEN 1200 ++ ++#define REALLOC_REPLY(r, a, m) \ ++ do { \ ++ if ((a)) { \ ++ char *tmp = (r); \ ++ (r) = REALLOC((r), (m) * 2); \ ++ if ((r)) { \ ++ memset((r) + (m), 0, (m)); \ ++ (m) *= 2; \ ++ } \ ++ else \ ++ free(tmp); \ ++ } \ ++ } while (0) + + struct key { + char * str; +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index e47899a..23683f2 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -23,20 +23,6 @@ + #include "cli.h" + #include "uevent.h" + +-#define REALLOC_REPLY(r, a, m) \ +- do { \ +- if ((a)) { \ +- char *tmp = (r); \ +- (r) = REALLOC((r), (m) * 2); \ +- if ((r)) { \ +- memset((r) + (m), 0, (m)); \ +- (m) *= 2; \ +- } \ +- else \ +- free(tmp); \ +- } \ +- } while (0) +- + int + show_paths (char ** r, int * len, struct vectors * vecs, char * style) + { diff --git a/SOURCES/0146-UPBZ-1299651-raw-output.patch b/SOURCES/0146-UPBZ-1299651-raw-output.patch new file mode 100644 index 0000000..93a171e --- /dev/null +++ b/SOURCES/0146-UPBZ-1299651-raw-output.patch @@ -0,0 +1,393 @@ +--- + libmultipath/print.c | 42 ++++++++++++++++++++++++---------------- + libmultipath/print.h | 4 +-- + multipathd/cli.c | 5 +++- + multipathd/cli.h | 6 +++-- + multipathd/cli_handlers.c | 48 ++++++++++++++++++++++++++++++++++------------ + multipathd/cli_handlers.h | 2 + + multipathd/main.c | 2 + + 7 files changed, 76 insertions(+), 33 deletions(-) + +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -32,14 +32,21 @@ + #define MAX(x,y) (x > y) ? x : y + #define TAIL (line + len - 1 - c) + #define NOPAD s = c +-#define PAD(x) while ((int)(c - s) < (x) && (c < (line + len - 1))) \ +- *c++ = ' '; s = c ++#define PAD(x) \ ++do { \ ++ while ((int)(c - s) < (x) && (c < (line + len - 1))) \ ++ *c++ = ' '; \ ++ s = c; \ ++} while (0) ++ + #define ENDLINE \ + if (c > line) \ + line[c - line - 1] = '\n' +-#define PRINT(var, size, format, args...) \ +- fwd = snprintf(var, size, format, ##args); \ +- c += (fwd >= size) ? size : fwd; ++#define PRINT(var, size, format, args...) \ ++do { \ ++ fwd = snprintf(var, size, format, ##args); \ ++ c += (fwd >= size) ? size : fwd; \ ++} while (0) + + /* + * information printing helpers +@@ -720,7 +727,7 @@ snprint_multipath_header (char * line, i + + int + snprint_multipath (char * line, int len, char * format, +- struct multipath * mpp) ++ struct multipath * mpp, int pad) + { + char * c = line; /* line cursor */ + char * s = line; /* for padding */ +@@ -747,7 +754,8 @@ snprint_multipath (char * line, int len, + + data->snprint(buff, MAX_FIELD_LEN, mpp); + PRINT(c, TAIL, "%s", buff); +- PAD(data->width); ++ if (pad) ++ PAD(data->width); + buff[0] = '\0'; + } while (*f++); + +@@ -790,7 +798,7 @@ snprint_path_header (char * line, int le + + int + snprint_path (char * line, int len, char * format, +- struct path * pp) ++ struct path * pp, int pad) + { + char * c = line; /* line cursor */ + char * s = line; /* for padding */ +@@ -817,7 +825,8 @@ snprint_path (char * line, int len, char + + data->snprint(buff, MAX_FIELD_LEN, pp); + PRINT(c, TAIL, "%s", buff); +- PAD(data->width); ++ if (pad) ++ PAD(data->width); + } while (*f++); + + ENDLINE; +@@ -909,7 +918,7 @@ snprint_multipath_topology (char * buff, + reset_multipath_layout(); + + if (verbosity == 1) +- return snprint_multipath(buff, len, "%n", mpp); ++ return snprint_multipath(buff, len, "%n", mpp, 1); + + if(isatty(1)) + c += sprintf(c, "%c[%dm", 0x1B, 1); /* bold on */ +@@ -928,10 +937,11 @@ snprint_multipath_topology (char * buff, + if(isatty(1)) + c += sprintf(c, "%c[%dm", 0x1B, 0); /* bold off */ + +- fwd += snprint_multipath(buff + fwd, len - fwd, style, mpp); ++ fwd += snprint_multipath(buff + fwd, len - fwd, style, mpp, 1); + if (fwd > len) + return len; +- fwd += snprint_multipath(buff + fwd, len - fwd, PRINT_MAP_PROPS, mpp); ++ fwd += snprint_multipath(buff + fwd, len - fwd, PRINT_MAP_PROPS, mpp, ++ 1); + if (fwd > len) + return len; + +@@ -958,7 +968,7 @@ snprint_multipath_topology (char * buff, + strcpy(f, " |- " PRINT_PATH_INDENT); + else + strcpy(f, " `- " PRINT_PATH_INDENT); +- fwd += snprint_path(buff + fwd, len - fwd, fmt, pp); ++ fwd += snprint_path(buff + fwd, len - fwd, fmt, pp, 1); + if (fwd > len) + return len; + } +@@ -1425,7 +1435,7 @@ snprint_devices (char * buff, int len, s + if (r > 0) + fwd += snprintf(buff + fwd, len - fwd, + " devnode blacklisted, unmonitored"); +- else if (r < 0) ++ else if (r <= 0) + fwd += snprintf(buff + fwd, len - fwd, + " devnode whitelisted, unmonitored"); + } else +@@ -1455,7 +1465,7 @@ print_path (struct path * pp, char * sty + char line[MAX_LINE_LEN]; + + memset(&line[0], 0, MAX_LINE_LEN); +- snprint_path(&line[0], MAX_LINE_LEN, style, pp); ++ snprint_path(&line[0], MAX_LINE_LEN, style, pp, 1); + printf("%s", line); + } + +@@ -1465,7 +1475,7 @@ print_multipath (struct multipath * mpp, + char line[MAX_LINE_LEN]; + + memset(&line[0], 0, MAX_LINE_LEN); +- snprint_multipath(&line[0], MAX_LINE_LEN, style, mpp); ++ snprint_multipath(&line[0], MAX_LINE_LEN, style, mpp, 1); + printf("%s", line); + } + +Index: multipath-tools-130222/libmultipath/print.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.h ++++ multipath-tools-130222/libmultipath/print.h +@@ -37,8 +37,8 @@ void get_path_layout (vector pathvec, in + void get_multipath_layout (vector mpvec, int header); + int snprint_path_header (char *, int, char *); + int snprint_multipath_header (char *, int, char *); +-int snprint_path (char *, int, char *, struct path *); +-int snprint_multipath (char *, int, char *, struct multipath *); ++int snprint_path (char *, int, char *, struct path *, int); ++int snprint_multipath (char *, int, char *, struct multipath *, int); + int snprint_multipath_topology (char *, int, struct multipath * mpp, + int verbosity); + int snprint_defaults (char *, int); +Index: multipath-tools-130222/multipathd/cli.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.c ++++ multipath-tools-130222/multipathd/cli.c +@@ -180,7 +180,7 @@ load_keys (void) + r += add_key(keys, "config", CONFIG, 0); + r += add_key(keys, "blacklist", BLACKLIST, 0); + r += add_key(keys, "devices", DEVICES, 0); +- r += add_key(keys, "format", FMT, 1); ++ r += add_key(keys, "raw", RAW, 0); + r += add_key(keys, "wildcards", WILDCARDS, 0); + r += add_key(keys, "quit", QUIT, 0); + r += add_key(keys, "exit", QUIT, 0); +@@ -188,6 +188,7 @@ load_keys (void) + r += add_key(keys, "getprstatus", GETPRSTATUS, 0); + r += add_key(keys, "setprstatus", SETPRSTATUS, 0); + r += add_key(keys, "unsetprstatus", UNSETPRSTATUS, 0); ++ r += add_key(keys, "format", FMT, 1); + + if (r) { + free_keys(keys); +@@ -463,12 +464,14 @@ cli_init (void) { + + add_handler(LIST+PATHS, NULL); + add_handler(LIST+PATHS+FMT, NULL); ++ add_handler(LIST+PATHS+RAW+FMT, NULL); + add_handler(LIST+STATUS, NULL); + add_handler(LIST+DAEMON, NULL); + add_handler(LIST+MAPS, NULL); + add_handler(LIST+MAPS+STATUS, NULL); + add_handler(LIST+MAPS+STATS, NULL); + add_handler(LIST+MAPS+FMT, NULL); ++ add_handler(LIST+MAPS+RAW+FMT, NULL); + add_handler(LIST+MAPS+TOPOLOGY, NULL); + add_handler(LIST+TOPOLOGY, NULL); + add_handler(LIST+MAP+TOPOLOGY, NULL); +Index: multipath-tools-130222/multipathd/cli.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.h ++++ multipath-tools-130222/multipathd/cli.h +@@ -26,13 +26,14 @@ enum { + __CONFIG, + __BLACKLIST, + __DEVICES, +- __FMT, ++ __RAW, + __WILDCARDS, + __QUIT, + __SHUTDOWN, + __GETPRSTATUS, + __SETPRSTATUS, + __UNSETPRSTATUS, ++ __FMT, + }; + + #define LIST (1 << __LIST) +@@ -62,7 +63,7 @@ enum { + #define CONFIG (1 << __CONFIG) + #define BLACKLIST (1 << __BLACKLIST) + #define DEVICES (1 << __DEVICES) +-#define FMT (1 << __FMT) ++#define RAW (1 << __RAW) + #define COUNT (1 << __COUNT) + #define WILDCARDS (1 << __WILDCARDS) + #define QUIT (1 << __QUIT) +@@ -70,6 +71,7 @@ enum { + #define GETPRSTATUS (1UL << __GETPRSTATUS) + #define SETPRSTATUS (1UL << __SETPRSTATUS) + #define UNSETPRSTATUS (1UL << __UNSETPRSTATUS) ++#define FMT (1UL << __FMT) + + #define INITIAL_REPLY_LEN 1200 + +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -24,7 +24,8 @@ + #include "uevent.h" + + int +-show_paths (char ** r, int * len, struct vectors * vecs, char * style) ++show_paths (char ** r, int * len, struct vectors * vecs, char * style, ++ int pretty) + { + int i; + struct path * pp; +@@ -42,13 +43,13 @@ show_paths (char ** r, int * len, struct + + c = reply; + +- if (VECTOR_SIZE(vecs->pathvec) > 0) ++ if (pretty && VECTOR_SIZE(vecs->pathvec) > 0) + c += snprint_path_header(c, reply + maxlen - c, + style); + + vector_foreach_slot(vecs->pathvec, pp, i) + c += snprint_path(c, reply + maxlen - c, +- style, pp); ++ style, pp, pretty); + + again = ((c - reply) == (maxlen - 1)); + +@@ -183,7 +184,7 @@ cli_list_paths (void * v, char ** reply, + + condlog(3, "list paths (operator)"); + +- return show_paths(reply, len, vecs, PRINT_PATH_CHECKER); ++ return show_paths(reply, len, vecs, PRINT_PATH_CHECKER, 1); + } + + int +@@ -194,7 +195,18 @@ cli_list_paths_fmt (void * v, char ** re + + condlog(3, "list paths (operator)"); + +- return show_paths(reply, len, vecs, fmt); ++ return show_paths(reply, len, vecs, fmt, 1); ++} ++ ++int ++cli_list_paths_raw (void * v, char ** reply, int * len, void * data) ++{ ++ struct vectors * vecs = (struct vectors *)data; ++ char * fmt = get_keyparam(v, FMT); ++ ++ condlog(3, "list paths (operator)"); ++ ++ return show_paths(reply, len, vecs, fmt, 0); + } + + int +@@ -285,7 +297,8 @@ show_daemon (char ** r, int *len) + } + + int +-show_maps (char ** r, int *len, struct vectors * vecs, char * style) ++show_maps (char ** r, int *len, struct vectors * vecs, char * style, ++ int pretty) + { + int i; + struct multipath * mpp; +@@ -302,13 +315,13 @@ show_maps (char ** r, int *len, struct v + return 1; + + c = reply; +- if (VECTOR_SIZE(vecs->mpvec) > 0) ++ if (pretty && VECTOR_SIZE(vecs->mpvec) > 0) + c += snprint_multipath_header(c, reply + maxlen - c, + style); + + vector_foreach_slot(vecs->mpvec, mpp, i) + c += snprint_multipath(c, reply + maxlen - c, +- style, mpp); ++ style, mpp, pretty); + + again = ((c - reply) == (maxlen - 1)); + +@@ -327,7 +340,18 @@ cli_list_maps_fmt (void * v, char ** rep + + condlog(3, "list maps (operator)"); + +- return show_maps(reply, len, vecs, fmt); ++ return show_maps(reply, len, vecs, fmt, 1); ++} ++ ++int ++cli_list_maps_raw (void * v, char ** reply, int * len, void * data) ++{ ++ struct vectors * vecs = (struct vectors *)data; ++ char * fmt = get_keyparam(v, FMT); ++ ++ condlog(3, "list maps (operator)"); ++ ++ return show_maps(reply, len, vecs, fmt, 0); + } + + int +@@ -337,7 +361,7 @@ cli_list_maps (void * v, char ** reply, + + condlog(3, "list maps (operator)"); + +- return show_maps(reply, len, vecs, PRINT_MAP_NAMES); ++ return show_maps(reply, len, vecs, PRINT_MAP_NAMES, 1); + } + + int +@@ -357,7 +381,7 @@ cli_list_maps_status (void * v, char ** + + condlog(3, "list maps status (operator)"); + +- return show_maps(reply, len, vecs, PRINT_MAP_STATUS); ++ return show_maps(reply, len, vecs, PRINT_MAP_STATUS, 1); + } + + int +@@ -367,7 +391,7 @@ cli_list_maps_stats (void * v, char ** r + + condlog(3, "list maps stats (operator)"); + +- return show_maps(reply, len, vecs, PRINT_MAP_STATS); ++ return show_maps(reply, len, vecs, PRINT_MAP_STATS, 1); + } + + int +Index: multipath-tools-130222/multipathd/cli_handlers.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.h ++++ multipath-tools-130222/multipathd/cli_handlers.h +@@ -1,9 +1,11 @@ + int cli_list_paths (void * v, char ** reply, int * len, void * data); + int cli_list_paths_fmt (void * v, char ** reply, int * len, void * data); ++int cli_list_paths_raw (void * v, char ** reply, int * len, void * data); + int cli_list_status (void * v, char ** reply, int * len, void * data); + int cli_list_daemon (void * v, char ** reply, int * len, void * data); + int cli_list_maps (void * v, char ** reply, int * len, void * data); + int cli_list_maps_fmt (void * v, char ** reply, int * len, void * data); ++int cli_list_maps_raw (void * v, char ** reply, int * len, void * data); + int cli_list_maps_status (void * v, char ** reply, int * len, void * data); + int cli_list_maps_stats (void * v, char ** reply, int * len, void * data); + int cli_list_map_topology (void * v, char ** reply, int * len, void * data); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -967,12 +967,14 @@ uxlsnrloop (void * ap) + + set_handler_callback(LIST+PATHS, cli_list_paths); + set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt); ++ set_handler_callback(LIST+PATHS+RAW+FMT, cli_list_paths_raw); + set_handler_callback(LIST+MAPS, cli_list_maps); + set_handler_callback(LIST+STATUS, cli_list_status); + set_handler_callback(LIST+DAEMON, cli_list_daemon); + set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status); + set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats); + set_handler_callback(LIST+MAPS+FMT, cli_list_maps_fmt); ++ set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw); + set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology); + set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology); + set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology); diff --git a/SOURCES/0147-RHBZ-1272620-fail-rm-msg.patch b/SOURCES/0147-RHBZ-1272620-fail-rm-msg.patch new file mode 100644 index 0000000..b48ed6b --- /dev/null +++ b/SOURCES/0147-RHBZ-1272620-fail-rm-msg.patch @@ -0,0 +1,60 @@ +--- + multipathd/cli_handlers.c | 8 ++++---- + multipathd/main.c | 4 ++-- + 2 files changed, 6 insertions(+), 6 deletions(-) + +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -459,7 +459,7 @@ cli_del_path (void * v, char ** reply, i + pp = find_path_by_dev(vecs->pathvec, param); + if (!pp) { + condlog(0, "%s: path already removed", param); +- return 0; ++ return 1; + } + return ev_remove_path(pp, vecs); + } +@@ -520,19 +520,19 @@ cli_del_map (void * v, char ** reply, in + minor = dm_get_minor(param); + if (minor < 0) { + condlog(2, "%s: not a device mapper table", param); +- return 0; ++ return 1; + } + major = dm_get_major(param); + if (major < 0) { + condlog(2, "%s: not a device mapper table", param); +- return 0; ++ return 1; + } + sprintf(dev_path,"dm-%d", minor); + alias = dm_mapname(major, minor); + if (!alias) { + condlog(2, "%s: mapname not found for %d:%d", + param, major, minor); +- return 0; ++ return 1; + } + rc = ev_remove_map(param, alias, minor, vecs); + FREE(alias); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -437,12 +437,12 @@ ev_remove_map (char * devname, char * al + if (!mpp) { + condlog(2, "%s: devmap not registered, can't remove", + devname); +- return 0; ++ return 1; + } + if (strcmp(mpp->alias, alias)) { + condlog(2, "%s: minor number mismatch (map %d, event %d)", + mpp->alias, mpp->dmi->minor, minor); +- return 0; ++ return 1; + } + return flush_map(mpp, vecs, 0); + } diff --git a/SOURCES/0148-RHBZ-1292599-verify-before-remove.patch b/SOURCES/0148-RHBZ-1292599-verify-before-remove.patch new file mode 100644 index 0000000..3e33b89 --- /dev/null +++ b/SOURCES/0148-RHBZ-1292599-verify-before-remove.patch @@ -0,0 +1,142 @@ +--- + libmultipath/devmapper.c | 45 +++++++++++++++++++++++++++++++++++++-------- + libmultipath/devmapper.h | 2 +- + 2 files changed, 38 insertions(+), 9 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -33,6 +33,9 @@ + #define UUID_PREFIX_LEN 6 + + static int dm_cancel_remove_partmaps(const char * mapname); ++static int do_foreach_partmaps (const char * mapname, ++ int (*partmap_func)(const char *, void *), ++ void *data); + + #ifndef LIBDM_API_COOKIE + static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c, int a) +@@ -709,6 +712,26 @@ out: + return r; + } + ++static int ++partmap_in_use(const char *name, void *data) ++{ ++ int part_count, *ret_count = (int *)data; ++ int open_count = dm_get_opencount(name); ++ ++ if (ret_count) ++ (*ret_count)++; ++ part_count = 0; ++ if (open_count) { ++ if (do_foreach_partmaps(name, partmap_in_use, &part_count)) ++ return 1; ++ if (open_count != part_count) { ++ condlog(2, "%s: map in use", name); ++ return 1; ++ } ++ } ++ return 0; ++} ++ + extern int + _dm_flush_map (const char * mapname, int need_sync, int deferred_remove) + { +@@ -717,6 +740,11 @@ _dm_flush_map (const char * mapname, int + if (!dm_is_mpath(mapname)) + return 0; /* nothing to do */ + ++ /* If you aren't doing a deferred remove, make sure that no ++ * devices are in use */ ++ if (!do_deferred(deferred_remove) && partmap_in_use(mapname, NULL)) ++ return 1; ++ + if (dm_remove_partmaps(mapname, need_sync, deferred_remove)) + return 1; + +@@ -825,7 +853,7 @@ dm_flush_maps (void) + } + + int +-dm_message(char * mapname, char * message) ++dm_message(const char * mapname, char * message) + { + int r = 1; + struct dm_task *dmt; +@@ -1076,7 +1104,8 @@ bad: + } + + static int +-do_foreach_partmaps (const char * mapname, int (*partmap_func)(char *, void *), ++do_foreach_partmaps (const char * mapname, ++ int (*partmap_func)(const char *, void *), + void *data) + { + struct dm_task *dmt; +@@ -1149,7 +1178,7 @@ struct remove_data { + }; + + static int +-remove_partmap(char *name, void *data) ++remove_partmap(const char *name, void *data) + { + struct remove_data *rd = (struct remove_data *)data; + +@@ -1176,7 +1205,7 @@ dm_remove_partmaps (const char * mapname + #ifdef LIBDM_API_DEFERRED + + static int +-cancel_remove_partmap (char *name, void *unused) ++cancel_remove_partmap (const char *name, void *unused) + { + if (dm_get_opencount(name)) + dm_cancel_remove_partmaps(name); +@@ -1296,13 +1325,13 @@ out: + } + + struct rename_data { +- char *old; ++ const char *old; + char *new; + char *delim; + }; + + static int +-rename_partmap (char *name, void *data) ++rename_partmap (const char *name, void *data) + { + char buff[PARAMS_SIZE]; + int offset; +@@ -1319,7 +1348,7 @@ rename_partmap (char *name, void *data) + } + + int +-dm_rename_partmaps (char * old, char * new) ++dm_rename_partmaps (const char * old, char * new) + { + struct rename_data rd; + +@@ -1333,7 +1362,7 @@ dm_rename_partmaps (char * old, char * n + } + + int +-dm_rename (char * old, char * new) ++dm_rename (const char * old, char * new) + { + int r = 0; + struct dm_task *dmt; +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -47,7 +47,7 @@ int dm_remove_partmaps (const char * map + int deferred_remove); + int dm_get_uuid(char *name, char *uuid); + int dm_get_info (char * mapname, struct dm_info ** dmi); +-int dm_rename (char * old, char * new); ++int dm_rename (const char * old, char * new); + int dm_reassign(const char * mapname); + int dm_reassign_table(const char *name, char *old, char *new); + int dm_setgeometry(struct multipath *mpp); diff --git a/SOURCES/0149-RHBZ-1292599-restore-removed-parts.patch b/SOURCES/0149-RHBZ-1292599-restore-removed-parts.patch new file mode 100644 index 0000000..62757c4 --- /dev/null +++ b/SOURCES/0149-RHBZ-1292599-restore-removed-parts.patch @@ -0,0 +1,82 @@ +--- + libmultipath/configure.c | 8 ++++++-- + libmultipath/structs.h | 1 + + multipathd/main.c | 1 + + 3 files changed, 8 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -398,6 +398,7 @@ select_action (struct multipath * mpp, v + cmpp->alias, mpp->alias); + strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE); + mpp->action = ACT_RENAME; ++ mpp->force_udev_reload = force_reload; + if (force_reload) + mpp->action = ACT_RENAME2; + return; +@@ -437,11 +438,13 @@ select_action (struct multipath * mpp, v + return; + } + if (force_reload) { ++ mpp->force_udev_reload = 1; + mpp->action = ACT_RELOAD; + condlog(3, "%s: set ACT_RELOAD (forced by user)", + mpp->alias); + return; + } ++ mpp->force_udev_reload = !pathcount(mpp, PATH_WILD); + if (cmpp->size != mpp->size) { + mpp->action = ACT_RESIZE; + condlog(3, "%s: set ACT_RESIZE (size change)", +@@ -651,7 +654,7 @@ domap (struct multipath * mpp, char * pa + case ACT_RELOAD: + r = dm_addmap_reload(mpp, params); + if (r) +- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, MPATH_UDEV_RELOAD_FLAG); ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG); + break; + + case ACT_RESIZE: +@@ -669,7 +672,7 @@ domap (struct multipath * mpp, char * pa + if (r) { + r = dm_addmap_reload(mpp, params); + if (r) +- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, MPATH_UDEV_RELOAD_FLAG); ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG); + } + break; + +@@ -682,6 +685,7 @@ domap (struct multipath * mpp, char * pa + * DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD + * succeeded + */ ++ mpp->force_udev_reload = 0; + if (mpp->action == ACT_CREATE) { + if (remember_wwid(mpp->wwid) == 1) + trigger_uevents(mpp); +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -234,6 +234,7 @@ struct multipath { + int deferred_remove; + int delay_watch_checks; + int delay_wait_checks; ++ int force_udev_reload; + 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 +@@ -554,6 +554,7 @@ rescan: + + condlog(4,"%s: adopting all paths for path %s", + mpp->alias, pp->dev); ++ mpp->force_udev_reload = !pathcount(mpp, PATH_WILD); + if (adopt_paths(vecs->pathvec, mpp, 1)) + goto fail; /* leave path added to pathvec */ + diff --git a/SOURCES/0150-RHBZ-1253913-fix-startup-msg.patch b/SOURCES/0150-RHBZ-1253913-fix-startup-msg.patch new file mode 100644 index 0000000..8a020ce --- /dev/null +++ b/SOURCES/0150-RHBZ-1253913-fix-startup-msg.patch @@ -0,0 +1,128 @@ +--- + multipathd/main.c | 38 +++++++++++++++++++++++++++++--------- + 1 file changed, 29 insertions(+), 9 deletions(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -87,6 +87,7 @@ unsigned int mpath_mx_alloc_len; + int logsink; + enum daemon_status running_state; + pid_t daemon_pid; ++pid_t parent_pid = -1; + + static sem_t exit_sem; + /* +@@ -1718,6 +1719,12 @@ sigusr2 (int sig) + } + + static void ++sigalrm (int sig) ++{ ++ exit(0); ++} ++ ++static void + signal_init(void) + { + sigset_t set; +@@ -1820,6 +1827,9 @@ child (void * param) + } + + running_state = DAEMON_START; ++ pid_rc = pidfile_create(DEFAULT_PIDFILE, daemon_pid); ++ if (parent_pid > 0) ++ kill(parent_pid, SIGALRM); + + condlog(2, "--------start up--------"); + condlog(2, "read " DEFAULT_CONFIGFILE); +@@ -1911,8 +1921,6 @@ child (void * param) + } + pthread_attr_destroy(&misc_attr); + +- /* Startup complete, create logfile */ +- pid_rc = pidfile_create(DEFAULT_PIDFILE, daemon_pid); + update_timestamp(1); + /* Ignore errors, we can live without */ + +@@ -1992,7 +2000,10 @@ daemonize(void) + { + int pid; + int dev_null_fd; ++ struct sigaction oldsig; + ++ oldsig.sa_handler = signal_set(SIGALRM, sigalrm); ++ parent_pid = getpid(); + if( (pid = fork()) < 0){ + fprintf(stderr, "Failed first fork : %s\n", strerror(errno)); + return -1; +@@ -2000,10 +2011,13 @@ daemonize(void) + else if (pid != 0) + return pid; + ++ signal_set(SIGALRM, oldsig.sa_handler); + setsid(); + +- if ( (pid = fork()) < 0) ++ if ( (pid = fork()) < 0) { + fprintf(stderr, "Failed second fork : %s\n", strerror(errno)); ++ goto fail; ++ } + else if (pid != 0) + _exit(0); + +@@ -2014,30 +2028,34 @@ daemonize(void) + if (dev_null_fd < 0){ + fprintf(stderr, "cannot open /dev/null for input & output : %s\n", + strerror(errno)); +- _exit(0); ++ goto fail; + } + + close(STDIN_FILENO); + if (dup(dev_null_fd) < 0) { + fprintf(stderr, "cannot dup /dev/null to stdin : %s\n", + strerror(errno)); +- _exit(0); ++ goto fail; + } + close(STDOUT_FILENO); + if (dup(dev_null_fd) < 0) { + fprintf(stderr, "cannot dup /dev/null to stdout : %s\n", + strerror(errno)); +- _exit(0); ++ goto fail; + } + close(STDERR_FILENO); + if (dup(dev_null_fd) < 0) { + fprintf(stderr, "cannot dup /dev/null to stderr : %s\n", + strerror(errno)); +- _exit(0); ++ goto fail; + } + close(dev_null_fd); + daemon_pid = getpid(); + return 0; ++ ++fail: ++ kill(parent_pid, SIGALRM); ++ _exit(0); + } + + int +@@ -2116,10 +2134,12 @@ main (int argc, char *argv[]) + if (err < 0) + /* error */ + exit(1); +- else if (err > 0) ++ else if (err > 0) { ++ /* wait up to 3 seconds for the child to start */ ++ sleep(3); + /* parent dies */ + exit(0); +- else ++ } else + /* child lives */ + return (child(NULL)); + } diff --git a/SOURCES/0151-RHBZ-1297456-weighted-fix.patch b/SOURCES/0151-RHBZ-1297456-weighted-fix.patch new file mode 100644 index 0000000..57b2fed --- /dev/null +++ b/SOURCES/0151-RHBZ-1297456-weighted-fix.patch @@ -0,0 +1,156 @@ +--- + libmultipath/print.c | 8 +++--- + libmultipath/print.h | 4 +++ + libmultipath/prioritizers/weightedpath.c | 37 +++++++++++++++++++++++++++++++ + libmultipath/prioritizers/weightedpath.h | 1 + multipath/multipath.conf.5 | 8 +++++- + 5 files changed, 53 insertions(+), 5 deletions(-) + +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -468,19 +468,19 @@ out: + return ret; + } + +-static int ++int + snprint_host_wwnn (char * buff, size_t len, struct path * pp) + { + return snprint_host_attr(buff, len, pp, "node_name"); + } + +-static int ++int + snprint_host_wwpn (char * buff, size_t len, struct path * pp) + { + return snprint_host_attr(buff, len, pp, "port_name"); + } + +-static int ++int + snprint_tgt_wwpn (char * buff, size_t len, struct path * pp) + { + struct udev_device *rport_dev = NULL; +@@ -510,7 +510,7 @@ out: + } + + +-static int ++int + snprint_tgt_wwnn (char * buff, size_t len, struct path * pp) + { + if (pp->tgt_node_name[0] == '\0') +Index: multipath-tools-130222/libmultipath/print.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.h ++++ multipath-tools-130222/libmultipath/print.h +@@ -50,6 +50,10 @@ int snprint_status (char *, int, struct + int snprint_devices (char *, int, struct vectors *); + int snprint_hwtable (char *, int, vector); + int snprint_mptable (char *, int, vector); ++int snprint_host_wwnn (char *, size_t, struct path *); ++int snprint_host_wwpn (char *, size_t, struct path *); ++int snprint_tgt_wwnn (char *, size_t, struct path *); ++int snprint_tgt_wwpn (char *, size_t, struct path *); + + void print_multipath_topology (struct multipath * mpp, int verbosity); + void print_path (struct path * pp, char * style); +Index: multipath-tools-130222/libmultipath/prioritizers/weightedpath.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/weightedpath.c ++++ multipath-tools-130222/libmultipath/prioritizers/weightedpath.c +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++#include + #include "def_func.h" + + char *get_next_string(char **temp, char *split_char) +@@ -43,6 +45,36 @@ char *get_next_string(char **temp, char + return token; + } + ++#define CHECK_LEN \ ++do { \ ++ if ((p - str) >= (len - 1)) { \ ++ condlog(0, "%s: %s - buffer size too small", pp->dev, pp->prio.name); \ ++ return -1; \ ++ } \ ++} while(0) ++ ++static int ++build_wwn_path(struct path *pp, char *str, int len) ++{ ++ char *p = str; ++ ++ p += snprint_host_wwnn(p, str + len - p, pp); ++ CHECK_LEN; ++ p += snprintf(p, str + len - p, ":"); ++ CHECK_LEN; ++ p += snprint_host_wwpn(p, str + len - p, pp); ++ CHECK_LEN; ++ p += snprintf(p, str + len - p, ":"); ++ CHECK_LEN; ++ p += snprint_tgt_wwnn(p, str + len - p, pp); ++ CHECK_LEN; ++ p += snprintf(p, str + len - p, ":"); ++ CHECK_LEN; ++ p += snprint_tgt_wwpn(p, str + len - p, pp); ++ CHECK_LEN; ++ return 0; ++} ++ + /* main priority routine */ + int prio_path_weight(struct path *pp, char *prio_args) + { +@@ -72,6 +104,11 @@ int prio_path_weight(struct path *pp, ch + pp->sg_id.channel, pp->sg_id.scsi_id, pp->sg_id.lun); + } else if (!strcmp(regex, DEV_NAME)) { + strcpy(path, pp->dev); ++ } else if (!strcmp(regex, WWN)) { ++ if (build_wwn_path(pp, path, FILE_NAME_SIZE) != 0) { ++ FREE(arg); ++ return priority; ++ } + } else { + condlog(0, "%s: %s - Invalid arguments", pp->dev, + pp->prio.name); +Index: multipath-tools-130222/libmultipath/prioritizers/weightedpath.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/weightedpath.h ++++ multipath-tools-130222/libmultipath/prioritizers/weightedpath.h +@@ -4,6 +4,7 @@ + #define PRIO_WEIGHTED_PATH "weightedpath" + #define HBTL "hbtl" + #define DEV_NAME "devname" ++#define WWN "wwn" + #define DEFAULT_PRIORITY 0 + + int prio_path_weight(struct path *pp, char *prio_args); +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -216,11 +216,17 @@ prioritizers + .TP 12 + .B weighted + Needs a value of the form +-.I " ..." ++.I " ..." + .I hbtl + regex can be of SCSI H:B:T:L format Ex: 1:0:.:. , *:0:0:. + .I devname + regex can be of device name format Ex: sda , sd.e ++.I wwn ++regex can be of the form ++.I "host_wwnn:host_wwpn:target_wwnn:target_wwpn" ++these values can be looked up through sysfs or by running ++.I mulitpathd show paths format "%N:%R:%n:%r" ++Ex: 0x200100e08ba0aea0:0x210100e08ba0aea0:.*:.* , .*:.*:iqn.2009-10.com.redhat.msp.lab.ask-06:.* + .TP + .B alua + If diff --git a/SOURCES/0152-RHBZ-1269293-fix-blk-unit-file.patch b/SOURCES/0152-RHBZ-1269293-fix-blk-unit-file.patch new file mode 100644 index 0000000..cadc3f3 --- /dev/null +++ b/SOURCES/0152-RHBZ-1269293-fix-blk-unit-file.patch @@ -0,0 +1,16 @@ +--- + multipathd/multipathd.service | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipathd/multipathd.service +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.service ++++ multipath-tools-130222/multipathd/multipathd.service +@@ -1,6 +1,6 @@ + [Unit] + Description=Device-Mapper Multipath Device Controller +-Requires=blk-availability.service ++Wants=blk-availability.service + Before=iscsi.service iscsid.service lvm2-activation-early.service + After=syslog.target + ConditionPathExists=/etc/multipath.conf diff --git a/SOURCES/0153-RH-fix-i686-size-bug.patch b/SOURCES/0153-RH-fix-i686-size-bug.patch new file mode 100644 index 0000000..325ec9d --- /dev/null +++ b/SOURCES/0153-RH-fix-i686-size-bug.patch @@ -0,0 +1,156 @@ +--- + multipathd/cli.c | 22 +++++++++++----------- + multipathd/cli.h | 20 +++++++++++--------- + 2 files changed, 22 insertions(+), 20 deletions(-) + +Index: multipath-tools-130222/multipathd/cli.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.c ++++ multipath-tools-130222/multipathd/cli.c +@@ -26,7 +26,7 @@ alloc_handler (void) + } + + static int +-add_key (vector vec, char * str, unsigned long code, int has_param) ++add_key (vector vec, char * str, uint64_t code, int has_param) + { + struct key * kw; + +@@ -57,7 +57,7 @@ out: + } + + int +-add_handler (unsigned long fp, int (*fn)(void *, char **, int *, void *)) ++add_handler (uint64_t fp, int (*fn)(void *, char **, int *, void *)) + { + struct handler * h; + +@@ -79,7 +79,7 @@ add_handler (unsigned long fp, int (*fn) + } + + static struct handler * +-find_handler (unsigned long fp) ++find_handler (uint64_t fp) + { + int i; + struct handler *h; +@@ -92,7 +92,7 @@ find_handler (unsigned long fp) + } + + int +-set_handler_callback (unsigned long fp, int (*fn)(void *, char **, int *, void *)) ++set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *)) + { + struct handler * h = find_handler(fp); + +@@ -293,11 +293,11 @@ out: + return r; + } + +-static unsigned long ++static uint64_t + fingerprint(vector vec) + { + int i; +- unsigned long fp = 0; ++ uint64_t fp = 0; + struct key * kw; + + if (!vec) +@@ -343,7 +343,7 @@ static int + do_genhelp(char *reply, int maxlen) { + int len = 0; + int i, j; +- unsigned long fp; ++ uint64_t fp; + struct handler * h; + struct key * kw; + +@@ -442,7 +442,7 @@ parse_cmd (char * cmd, char ** reply, in + } + + char * +-get_keyparam (vector v, unsigned long code) ++get_keyparam (vector v, uint64_t code) + { + struct key * kw; + int i; +@@ -515,7 +515,7 @@ void cli_exit(void) + } + + static int +-key_match_fingerprint (struct key * kw, unsigned long fp) ++key_match_fingerprint (struct key * kw, uint64_t fp) + { + if (!fp) + return 0; +@@ -530,7 +530,7 @@ char * + key_generator (const char * str, int state) + { + static int index, len, has_param; +- static unsigned long rlfp; ++ static uint64_t rlfp; + struct key * kw; + int i; + struct handler *h; +@@ -600,7 +600,7 @@ key_generator (const char * str, int sta + * nfp is the candidate fingerprint we try to + * validate against all known command fingerprints. + */ +- unsigned long nfp = rlfp | kw->code; ++ uint64_t nfp = rlfp | kw->code; + vector_foreach_slot(handlers, h, i) { + if (!rlfp || ((h->fingerprint & nfp) == nfp)) { + /* +Index: multipath-tools-130222/multipathd/cli.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.h ++++ multipath-tools-130222/multipathd/cli.h +@@ -1,3 +1,5 @@ ++#include ++ + enum { + __LIST, + __ADD, +@@ -68,10 +70,10 @@ enum { + #define WILDCARDS (1 << __WILDCARDS) + #define QUIT (1 << __QUIT) + #define SHUTDOWN (1 << __SHUTDOWN) +-#define GETPRSTATUS (1UL << __GETPRSTATUS) +-#define SETPRSTATUS (1UL << __SETPRSTATUS) +-#define UNSETPRSTATUS (1UL << __UNSETPRSTATUS) +-#define FMT (1UL << __FMT) ++#define GETPRSTATUS (1ULL << __GETPRSTATUS) ++#define SETPRSTATUS (1ULL << __SETPRSTATUS) ++#define UNSETPRSTATUS (1ULL << __UNSETPRSTATUS) ++#define FMT (1ULL << __FMT) + + #define INITIAL_REPLY_LEN 1200 + +@@ -92,21 +94,21 @@ enum { + struct key { + char * str; + char * param; +- unsigned long code; ++ uint64_t code; + int has_param; + }; + + struct handler { +- unsigned long fingerprint; ++ uint64_t fingerprint; + int (*fn)(void *, char **, int *, void *); + }; + + int alloc_handlers (void); +-int add_handler (unsigned long fp, int (*fn)(void *, char **, int *, void *)); +-int set_handler_callback (unsigned long fp, int (*fn)(void *, char **, int *, void *)); ++int add_handler (uint64_t fp, int (*fn)(void *, char **, int *, void *)); ++int set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *)); + int parse_cmd (char * cmd, char ** reply, int * len, void *); + int load_keys (void); +-char * get_keyparam (vector v, unsigned long code); ++char * get_keyparam (vector v, uint64_t code); + void free_keys (vector vec); + void free_handlers (void); + int cli_init (void); diff --git a/SOURCES/0154-UPBZ-1291406-disable-reinstate.patch b/SOURCES/0154-UPBZ-1291406-disable-reinstate.patch new file mode 100644 index 0000000..2da4e3f --- /dev/null +++ b/SOURCES/0154-UPBZ-1291406-disable-reinstate.patch @@ -0,0 +1,154 @@ +--- + libmultipath/propsel.c | 20 ++++++++++++++++---- + libmultipath/structs.h | 1 + + multipathd/main.c | 37 ++++++++++++++++++++++++++----------- + 3 files changed, 43 insertions(+), 15 deletions(-) + +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -398,9 +398,11 @@ detect_prio(struct path * pp) + { + int ret; + struct prio *p = &pp->prio; ++ int tpgs = 0; + +- if (get_target_port_group_support(pp->fd) <= 0) ++ if ((tpgs = get_target_port_group_support(pp->fd)) <= 0) + return; ++ pp->tpgs = tpgs; + ret = get_target_port_group(pp->fd, NULL); + if (ret < 0) + return; +@@ -432,7 +434,7 @@ select_prio (struct path * pp) + pp->dev, prio_name(p)); + condlog(3, "%s: prio args = %s (LUN setting)", + pp->dev, prio_args(p)); +- return 0; ++ goto out; + } + + if (pp->hwe && pp->hwe->prio_name) { +@@ -441,7 +443,7 @@ select_prio (struct path * pp) + pp->dev, pp->hwe->prio_name); + condlog(3, "%s: prio args = %s (controller setting)", + pp->dev, pp->hwe->prio_args); +- return 0; ++ goto out; + } + if (conf->prio_name) { + prio_get(p, conf->prio_name, conf->prio_args); +@@ -449,13 +451,23 @@ select_prio (struct path * pp) + pp->dev, conf->prio_name); + condlog(3, "%s: prio args = %s (config file default)", + pp->dev, conf->prio_args); +- return 0; ++ goto out; + } + prio_get(p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS); + condlog(3, "%s: prio = %s (internal default)", + pp->dev, DEFAULT_PRIO); + condlog(3, "%s: prio args = %s (internal default)", + pp->dev, DEFAULT_PRIO_ARGS); ++out: ++ /* ++ * fetch tpgs mode for alua ++ */ ++ if (!strncmp(prio_name(p), PRIO_ALUA, PRIO_NAME_LEN)) { ++ int tpgs = 0; ++ if (!pp->tpgs && ++ (tpgs = get_target_port_group_support(pp->fd)) >= 0) ++ pp->tpgs = tpgs; ++ } + return 0; + } + +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -193,6 +193,7 @@ struct path { + int detect_prio; + int watch_checks; + int wait_checks; ++ int tpgs; + char * uid_attribute; + struct prio prio; + char * prio_args; +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include "prioritizers/alua_rtpg.h" + + /* + * libcheckers +@@ -1248,6 +1249,7 @@ check_path (struct vectors * vecs, struc + int newstate; + int new_path_up = 0; + int chkr_new_path_up = 0; ++ int disable_reinstate = 0; + int oldchkrstate = pp->chkrstate; + + if (!pp->mpp && (pp->missing_udev_info != INFO_MISSING || +@@ -1312,6 +1314,16 @@ check_path (struct vectors * vecs, struc + pp->wait_checks = 0; + } + ++ /* ++ * don't reinstate failed path, if its in stand-by ++ * and if target supports only implicit tpgs mode. ++ * this will prevent unnecessary i/o by dm on stand-by ++ * paths if there are no other active paths in map. ++ */ ++ disable_reinstate = (newstate == PATH_GHOST && ++ pp->mpp->nr_active == 0 && ++ pp->tpgs == TPGS_IMPLICIT) ? 1 : 0; ++ + pp->chkrstate = newstate; + if (newstate != pp->state) { + int oldstate = pp->state; +@@ -1367,15 +1379,17 @@ check_path (struct vectors * vecs, struc + /* + * reinstate this path + */ +- if (oldstate != PATH_UP && +- oldstate != PATH_GHOST) { +- if (pp->mpp->delay_watch_checks > 0) +- pp->watch_checks = pp->mpp->delay_watch_checks; +- reinstate_path(pp, 1); +- } else { +- if (pp->watch_checks > 0) +- pp->watch_checks--; +- reinstate_path(pp, 0); ++ if (!disable_reinstate) { ++ if (oldstate != PATH_UP && ++ oldstate != PATH_GHOST) { ++ if (pp->mpp->delay_watch_checks > 0) ++ pp->watch_checks = pp->mpp->delay_watch_checks; ++ reinstate_path(pp, 1); ++ } else { ++ if (pp->watch_checks > 0) ++ pp->watch_checks--; ++ reinstate_path(pp, 0); ++ } + } + new_path_up = 1; + +@@ -1390,8 +1404,9 @@ check_path (struct vectors * vecs, struc + enable_group(pp); + } + else if (newstate == PATH_UP || newstate == PATH_GHOST) { +- if (pp->dmstate == PSTATE_FAILED || +- pp->dmstate == PSTATE_UNDEF) { ++ if ((pp->dmstate == PSTATE_FAILED || ++ pp->dmstate == PSTATE_UNDEF) && ++ !disable_reinstate) { + /* Clear IO errors */ + reinstate_path(pp, 0); + } else { diff --git a/SOURCES/0155-UPBZ-1300415-PURE-config.patch b/SOURCES/0155-UPBZ-1300415-PURE-config.patch new file mode 100644 index 0000000..9be598c --- /dev/null +++ b/SOURCES/0155-UPBZ-1300415-PURE-config.patch @@ -0,0 +1,54 @@ +--- + libmultipath/hwtable.c | 16 ++++++++++++++++ + multipath.conf.defaults | 11 +++++++++++ + 2 files changed, 27 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1166,6 +1166,22 @@ static struct hwentry default_hw[] = { + .prio_name = DEFAULT_PRIO, + .prio_args = NULL, + }, ++ { ++ .vendor = "PURE", ++ .product = "FlashArray", ++ .features = DEFAULT_FEATURES, ++ .hwhandler = DEFAULT_HWHANDLER, ++ .selector = "queue-length 0", ++ .pgpolicy = MULTIBUS, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .checker_name = TUR, ++ .fast_io_fail = 10, ++ .user_friendly_names = USER_FRIENDLY_NAMES_OFF, ++ .prio_name = DEFAULT_PRIO, ++ .no_path_retry = 0, ++ .dev_loss = 60, ++ .prio_args = NULL, ++ }, + /* + * EOL + */ +Index: multipath-tools-130222/multipath.conf.defaults +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.defaults ++++ multipath-tools-130222/multipath.conf.defaults +@@ -963,6 +963,17 @@ + # failback immediate + # fast_io_fail_tmo 15 + # } ++# device { ++# vendor "PURE" ++# path_selector "queue-length 0" ++# path_grouping_policy "multibus" ++# path_checker "tur" ++# fast_io_fail_tmo 10 ++# user_friendly_names "no" ++# no_path_retry 0 ++# features 0 ++# dev_loss_tmo 60 ++# } + #} + #multipaths { + #} diff --git a/SOURCES/0156-UPBZ-1313324-dont-fail-discovery.patch b/SOURCES/0156-UPBZ-1313324-dont-fail-discovery.patch new file mode 100644 index 0000000..7e33cfe --- /dev/null +++ b/SOURCES/0156-UPBZ-1313324-dont-fail-discovery.patch @@ -0,0 +1,236 @@ +--- + libmpathpersist/mpath_persist.c | 14 ++++++------ + libmultipath/discovery.c | 46 ++++++++++++++++++++-------------------- + libmultipath/discovery.h | 4 +++ + multipath/main.c | 2 - + multipathd/main.c | 6 +++-- + 5 files changed, 39 insertions(+), 33 deletions(-) + +Index: multipath-tools-130222/libmpathpersist/mpath_persist.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.c ++++ multipath-tools-130222/libmpathpersist/mpath_persist.c +@@ -178,7 +178,7 @@ int mpath_persistent_reserve_in (int fd, + goto out; + } + +- if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) { ++ if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) { + ret = MPATH_PR_DMMP_ERROR; + goto out1; + } +@@ -262,13 +262,13 @@ int mpath_persistent_reserve_out ( int f + curmp = vector_alloc (); + pathvec = vector_alloc (); + +- if (!curmp || !pathvec){ +- condlog (0, "%s: vector allocation failed.", alias); +- ret = MPATH_PR_DMMP_ERROR; +- goto out; +- } ++ if (!curmp || !pathvec){ ++ condlog (0, "%s: vector allocation failed.", alias); ++ ret = MPATH_PR_DMMP_ERROR; ++ goto out; ++ } + +- if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) { ++ if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) { + ret = MPATH_PR_DMMP_ERROR; + goto out1; + } +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -32,7 +32,7 @@ int + store_pathinfo (vector pathvec, vector hwtable, struct udev_device *udevice, + int flag, struct path **pp_ptr) + { +- int err = 1; ++ int err = PATHINFO_FAILED; + struct path * pp; + const char * devname; + +@@ -41,12 +41,12 @@ store_pathinfo (vector pathvec, vector h + + devname = udev_device_get_sysname(udevice); + if (!devname) +- return 1; ++ return PATHINFO_FAILED; + + pp = alloc_path(); + + if (!pp) +- return 1; ++ return PATHINFO_FAILED; + + if(safe_sprintf(pp->dev, "%s", devname)) { + condlog(0, "pp->dev too small"); +@@ -80,19 +80,16 @@ path_discover (vector pathvec, struct co + + devname = udev_device_get_sysname(udevice); + if (!devname) +- return 0; ++ return PATHINFO_FAILED; + + if (filter_devnode(conf->blist_devnode, conf->elist_devnode, + (char *)devname) > 0) +- return 0; ++ return PATHINFO_SKIPPED; + + pp = find_path_by_dev(pathvec, (char *)devname); + if (!pp) { +- if (store_pathinfo(pathvec, conf->hwtable, +- udevice, flag, NULL) != 1) +- return 0; +- else +- return 1; ++ return store_pathinfo(pathvec, conf->hwtable, ++ udevice, flag, NULL); + } + return pathinfo(pp, conf->hwtable, flag); + } +@@ -104,11 +101,11 @@ path_discovery (vector pathvec, struct c + struct udev_list_entry *entry; + struct udev_device *udevice; + const char *devpath; +- int r = 0; ++ int num_paths = 0, total_paths = 0; + + udev_iter = udev_enumerate_new(conf->udev); + if (!udev_iter) +- return 1; ++ return -ENOMEM; + + udev_enumerate_add_match_subsystem(udev_iter, "block"); + udev_enumerate_scan_devices(udev_iter); +@@ -121,17 +118,20 @@ path_discovery (vector pathvec, struct c + udevice = udev_device_new_from_syspath(conf->udev, devpath); + if (!udevice) { + condlog(4, "%s: no udev information", devpath); +- r++; + continue; + } + devtype = udev_device_get_devtype(udevice); +- if(devtype && !strncmp(devtype, "disk", 4)) +- r += path_discover(pathvec, conf, udevice, flag); ++ if(devtype && !strncmp(devtype, "disk", 4)) { ++ total_paths++; ++ if (path_discover(pathvec, conf, ++ udevice, flag) == PATHINFO_OK) ++ num_paths++; ++ } + udev_device_unref(udevice); + } + udev_enumerate_unref(udev_iter); +- condlog(4, "Discovery status %d", r); +- return r; ++ condlog(4, "Discovered %d/%d paths", num_paths, total_paths); ++ return (total_paths - num_paths); + } + + #define declare_sysfs_get_str(fname) \ +@@ -1021,7 +1021,7 @@ get_state (struct path * pp, int daemon) + + if (!checker_selected(c)) { + if (daemon) { +- if (pathinfo(pp, conf->hwtable, DI_SYSFS) != 0) { ++ if (pathinfo(pp, conf->hwtable, DI_SYSFS) != PATHINFO_OK) { + condlog(3, "%s: couldn't get sysfs pathinfo", + pp->dev); + return PATH_UNCHECKED; +@@ -1140,7 +1140,7 @@ pathinfo (struct path *pp, vector hwtabl + int path_state; + + if (!pp) +- return 1; ++ return PATHINFO_FAILED; + + condlog(3, "%s: mask = 0x%x", pp->dev, mask); + +@@ -1148,12 +1148,12 @@ pathinfo (struct path *pp, vector hwtabl + * fetch info available in sysfs + */ + if (mask & DI_SYSFS && sysfs_pathinfo(pp)) +- return 1; ++ return PATHINFO_FAILED; + + if (mask & DI_BLACKLIST && mask & DI_SYSFS) { + if (filter_device(conf->blist_device, conf->elist_device, + pp->vendor_id, pp->product_id) > 0) { +- return 2; ++ return PATHINFO_SKIPPED; + } + } + +@@ -1199,7 +1199,7 @@ pathinfo (struct path *pp, vector hwtabl + if (mask & DI_BLACKLIST && mask & DI_WWID) { + if (filter_wwid(conf->blist_wwid, conf->elist_wwid, + pp->wwid) > 0) { +- return 2; ++ return PATHINFO_SKIPPED; + } + } + +@@ -1213,7 +1213,7 @@ pathinfo (struct path *pp, vector hwtabl + } + } + +- return 0; ++ return PATHINFO_OK; + + blank: + /* +Index: multipath-tools-130222/libmultipath/discovery.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.h ++++ multipath-tools-130222/libmultipath/discovery.h +@@ -24,6 +24,10 @@ + #define SCSI_COMMAND_TERMINATED 0x22 + #define SG_ERR_DRIVER_SENSE 0x08 + ++#define PATHINFO_OK 0 ++#define PATHINFO_FAILED 1 ++#define PATHINFO_SKIPPED 2 ++ + struct config; + + int sysfs_get_dev (struct udev_device *udev, char * buff, size_t len); +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -343,7 +343,7 @@ configure (void) + /* maximum info */ + di_flag = DI_ALL; + +- if (path_discovery(pathvec, conf, di_flag)) ++ if (path_discovery(pathvec, conf, di_flag) < 0) + goto out; + + if (conf->verbosity > 2) +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1515,7 +1515,7 @@ configure (struct vectors * vecs, int st + struct multipath * mpp; + struct path * pp; + vector mpvec; +- int i; ++ int i, ret; + + if (!vecs->pathvec && !(vecs->pathvec = vector_alloc())) + return 1; +@@ -1529,7 +1529,9 @@ configure (struct vectors * vecs, int st + /* + * probe for current path (from sysfs) and map (from dm) sets + */ +- path_discovery(vecs->pathvec, conf, DI_ALL); ++ ret = path_discovery(vecs->pathvec, conf, DI_ALL); ++ if (ret < 0) ++ return 1; + + vector_foreach_slot (vecs->pathvec, pp, i){ + if (filter_path(conf, pp) > 0){ diff --git a/SOURCES/0157-RHBZ-1319853-multipath-c-error-msg.patch b/SOURCES/0157-RHBZ-1319853-multipath-c-error-msg.patch new file mode 100644 index 0000000..dbf47c7 --- /dev/null +++ b/SOURCES/0157-RHBZ-1319853-multipath-c-error-msg.patch @@ -0,0 +1,63 @@ +--- + libmultipath/alias.c | 8 ++++++++ + libmultipath/alias.h | 1 + + multipath/main.c | 7 ++++++- + 3 files changed, 15 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/alias.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.c ++++ multipath-tools-130222/libmultipath/alias.c +@@ -36,6 +36,14 @@ + * See the file COPYING included with this distribution for more details. + */ + ++int ++valid_alias(char *alias) ++{ ++ if (strchr(alias, '/') != NULL) ++ return 0; ++ return 1; ++} ++ + + static int + format_devname(char *name, int id, int len, char *prefix) +Index: multipath-tools-130222/libmultipath/alias.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.h ++++ multipath-tools-130222/libmultipath/alias.h +@@ -7,6 +7,7 @@ + "# alias wwid\n" \ + "#\n" + ++int valid_alias(char *alias); + 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); +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -454,8 +454,9 @@ get_dev_type(char *dev) { + } + else if (sscanf(dev, "%d:%d", &i, &i) == 2) + return DEV_DEVT; +- else ++ else if (valid_alias(dev)) + return DEV_DEVMAP; ++ return DEV_NONE; + } + + int +@@ -607,6 +608,10 @@ main (int argc, char *argv[]) + + strncpy(conf->dev, argv[optind], FILE_NAME_SIZE); + conf->dev_type = get_dev_type(conf->dev); ++ if (conf->dev_type == DEV_NONE) { ++ condlog(0, "'%s' is not a valid argument\n", conf->dev); ++ goto out; ++ } + } + conf->daemon = 0; + diff --git a/SOURCES/0158-RHBZ-1318581-timestamp-doc-fix.patch b/SOURCES/0158-RHBZ-1318581-timestamp-doc-fix.patch new file mode 100644 index 0000000..d9af360 --- /dev/null +++ b/SOURCES/0158-RHBZ-1318581-timestamp-doc-fix.patch @@ -0,0 +1,26 @@ +--- + multipath/multipath.8 | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +Index: multipath-tools-130222/multipath/multipath.8 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.8 ++++ multipath-tools-130222/multipath/multipath.8 +@@ -83,6 +83,17 @@ remove the wwid for the specified device + .B \-W + reset the wwids file to only include the current multipath devices + .TP ++.B \-T "tm:valid" ++check if ++.I tm ++matches the multipathd configuration timestamp value from ++.I "/run/multipathd/timestamp" ++If so, return success if ++.I valid ++is 1. Otherwise, return failure. If the timestamp doesn't match continue ++with multipath execution. This option is designed to be used with -c by ++the udev rules. ++.TP + .BI \-p " policy" + force new maps to use the specified policy: + .RS 1.2i diff --git a/SOURCES/0159-UPBZ-1255885-udev-waits.patch b/SOURCES/0159-UPBZ-1255885-udev-waits.patch new file mode 100644 index 0000000..9e0921b --- /dev/null +++ b/SOURCES/0159-UPBZ-1255885-udev-waits.patch @@ -0,0 +1,287 @@ +--- + kpartx/devmapper.c | 41 ++++++++++++++++++++++++++++------------- + kpartx/devmapper.h | 4 ++-- + kpartx/kpartx.c | 16 ++++++++-------- + libmultipath/config.h | 1 - + libmultipath/devmapper.c | 19 +++++++++++++------ + multipath/main.c | 2 -- + 6 files changed, 51 insertions(+), 32 deletions(-) + +Index: multipath-tools-130222/kpartx/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.c ++++ multipath-tools-130222/kpartx/devmapper.c +@@ -14,13 +14,6 @@ + #define MAX_PREFIX_LEN 8 + #define PARAMS_SIZE 1024 + +-#ifndef LIBDM_API_COOKIE +-static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c, int a) +-{ +- return 1; +-} +-#endif +- + extern int + dm_prereq (char * str, int x, int y, int z) + { +@@ -60,10 +53,13 @@ dm_prereq (char * str, int x, int y, int + } + + extern int +-dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie, uint16_t udev_flags) { ++dm_simplecmd (int task, const char *name, int no_flush, uint16_t udev_flags) { + int r = 0; + int udev_wait_flag = (task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE); ++#ifdef LIBDM_API_COOKIE ++ uint32_t cookie = 0; ++#endif + struct dm_task *dmt; + + if (!(dmt = dm_task_create(task))) +@@ -78,10 +74,17 @@ dm_simplecmd (int task, const char *name + if (no_flush) + dm_task_no_flush(dmt); + +- if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, ((udev_sync)? 0 : DM_UDEV_DISABLE_LIBRARY_FALLBACK) | udev_flags)) ++#ifdef LIBDM_API_COOKIE ++ if (!udev_sync) ++ udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK; ++ if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags)) + goto out; ++#endif + r = dm_task_run(dmt); +- ++#ifdef LIBDM_API_COOKIE ++ if (udev_wait_flag) ++ dm_udev_wait(cookie); ++#endif + out: + dm_task_destroy(dmt); + return r; +@@ -90,10 +93,14 @@ dm_simplecmd (int task, const char *name + extern int + dm_addmap (int task, const char *name, const char *target, + const char *params, uint64_t size, int ro, const char *uuid, int part, +- mode_t mode, uid_t uid, gid_t gid, uint32_t *cookie) { ++ mode_t mode, uid_t uid, gid_t gid) { + int r = 0; + struct dm_task *dmt; + char *prefixed_uuid = NULL; ++#ifdef LIBDM_API_COOKIE ++ uint32_t cookie = 0; ++ uint16_t udev_flags = 0; ++#endif + + if (!(dmt = dm_task_create (task))) + return 0; +@@ -128,10 +135,18 @@ dm_addmap (int task, const char *name, c + + dm_task_no_open_count(dmt); + +- if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, cookie, (udev_sync)? 0 : DM_UDEV_DISABLE_LIBRARY_FALLBACK)) ++#ifdef LIBDM_API_COOKIE ++ if (!udev_sync) ++ udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK; ++ if (task == DM_DEVICE_CREATE && ++ !dm_task_set_cookie(dmt, &cookie, udev_flags)) + goto addout; ++#endif + r = dm_task_run (dmt); +- ++#ifdef LIBDM_API_COOKIE ++ if (task == DM_DEVICE_CREATE) ++ dm_udev_wait(cookie); ++#endif + addout: + dm_task_destroy (dmt); + free(prefixed_uuid); +Index: multipath-tools-130222/kpartx/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.h ++++ multipath-tools-130222/kpartx/devmapper.h +@@ -11,9 +11,9 @@ + extern int udev_sync; + + int dm_prereq (char *, int, int, int); +-int dm_simplecmd (int, const char *, int, uint32_t *, uint16_t); ++int dm_simplecmd (int, const char *, int, uint16_t); + int dm_addmap (int, const char *, const char *, const char *, uint64_t, +- int, const char *, int, mode_t, uid_t, gid_t, uint32_t *); ++ int, const char *, int, mode_t, uid_t, gid_t); + int dm_map_present (char *, char **); + char * dm_mapname(int major, int minor); + dev_t dm_get_first_dep(char *devname); +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -224,7 +224,6 @@ main(int argc, char **argv){ + int hotplug = 0; + int loopcreated = 0; + struct stat buf; +- uint32_t cookie = 0; + + initpts(); + init_crc32(); +@@ -300,6 +299,8 @@ main(int argc, char **argv){ + #ifdef LIBDM_API_COOKIE + if (!udev_sync) + dm_udev_set_sync_support(0); ++ else ++ dm_udev_set_sync_support(1); + #endif + + if (dm_prereq(DM_TARGET, 0, 0, 0) && (what == ADD || what == DELETE || what == UPDATE)) { +@@ -451,7 +452,7 @@ main(int argc, char **argv){ + } + + if (!dm_simplecmd(DM_DEVICE_REMOVE, partname, +- 0, &cookie, 0)) { ++ 0, 0)) { + r++; + continue; + } +@@ -508,7 +509,7 @@ main(int argc, char **argv){ + if (!dm_addmap(op, partname, DM_TARGET, params, + slices[j].size, ro, uuid, j+1, + buf.st_mode & 0777, buf.st_uid, +- buf.st_gid, &cookie)) { ++ buf.st_gid)) { + fprintf(stderr, "create/reload failed on %s\n", + partname); + r++; +@@ -516,12 +517,13 @@ main(int argc, char **argv){ + } + if (op == DM_DEVICE_RELOAD && + !dm_simplecmd(DM_DEVICE_RESUME, partname, +- 1, &cookie, MPATH_UDEV_RELOAD_FLAG)) { ++ 1, MPATH_UDEV_RELOAD_FLAG)) { + fprintf(stderr, "resume failed on %s\n", + partname); + r++; + continue; + } ++ + dm_devn(partname, &slices[j].major, + &slices[j].minor); + +@@ -560,7 +562,7 @@ main(int argc, char **argv){ + } + + if (!dm_simplecmd(DM_DEVICE_REMOVE, +- partname, 1, &cookie, 0)) { ++ partname, 1, 0)) { + r++; + continue; + } +@@ -586,9 +588,7 @@ main(int argc, char **argv){ + } + printf("loop deleted : %s\n", device); + } +-#ifdef LIBDM_API_COOKIE +- dm_udev_wait(cookie); +-#endif ++ + dm_lib_release(); + dm_lib_exit(); + +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -129,7 +129,6 @@ struct config { + uid_t uid; + gid_t gid; + mode_t mode; +- uint32_t cookie; + int reassign_maps; + int retain_hwhandler; + int detect_prio; +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -215,6 +215,7 @@ dm_simplecmd (int task, const char *name + int r = 0; + int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE)); ++ uint32_t cookie = 0; + struct dm_task *dmt; + + if (!(dmt = dm_task_create (task))) +@@ -233,10 +234,12 @@ dm_simplecmd (int task, const char *name + if (do_deferred(deferred_remove)) + dm_task_deferred_remove(dmt); + #endif +- if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags)) ++ if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags)) + goto out; + r = dm_task_run (dmt); + ++ if (udev_wait_flag) ++ udev_wait(cookie); + out: + dm_task_destroy (dmt); + return r; +@@ -264,6 +267,7 @@ dm_addmap (int task, const char *target, + int r = 0; + struct dm_task *dmt; + char *prefixed_uuid = NULL; ++ uint32_t cookie = 0; + + if (!(dmt = dm_task_create (task))) + return 0; +@@ -304,10 +308,12 @@ dm_addmap (int task, const char *target, + dm_task_no_open_count(dmt); + + if (task == DM_DEVICE_CREATE && +- !dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) ++ !dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) + goto freeout; + r = dm_task_run (dmt); + ++ if (task == DM_DEVICE_CREATE) ++ udev_wait(cookie); + freeout: + if (prefixed_uuid) + FREE(prefixed_uuid); +@@ -1366,6 +1372,7 @@ dm_rename (const char * old, char * new) + { + int r = 0; + struct dm_task *dmt; ++ uint32_t cookie; + + if (dm_rename_partmaps(old, new)) + return r; +@@ -1381,12 +1388,12 @@ dm_rename (const char * old, char * new) + + dm_task_no_open_count(dmt); + +- if (!dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) +- goto out; +- if (!dm_task_run(dmt)) ++ if (!dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) + goto out; ++ r = dm_task_run(dmt); ++ ++ udev_wait(cookie); + +- r = 1; + out: + dm_task_destroy(dmt); + return r; +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -681,8 +681,6 @@ main (int argc, char *argv[]) + condlog(3, "restart multipath configuration process"); + + out: +- udev_wait(conf->cookie); +- + dm_lib_release(); + dm_lib_exit(); + diff --git a/SOURCES/0160-RH-udev-flags.patch b/SOURCES/0160-RH-udev-flags.patch new file mode 100644 index 0000000..29a2c9c --- /dev/null +++ b/SOURCES/0160-RH-udev-flags.patch @@ -0,0 +1,20 @@ +--- + libmultipath/devmapper.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -213,8 +213,9 @@ dm_prereq (void) + static int + dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags, int deferred_remove) { + int r = 0; +- int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME || +- task == DM_DEVICE_REMOVE)); ++ int udev_wait_flag = ((need_sync && (task == DM_DEVICE_RESUME || ++ task == DM_DEVICE_REMOVE)) || ++ udev_flags); + uint32_t cookie = 0; + struct dm_task *dmt; + diff --git a/SOURCES/0161-RHBZ-1311659-no-kpartx.patch b/SOURCES/0161-RHBZ-1311659-no-kpartx.patch new file mode 100644 index 0000000..8656548 --- /dev/null +++ b/SOURCES/0161-RHBZ-1311659-no-kpartx.patch @@ -0,0 +1,618 @@ +--- + libmultipath/config.c | 3 + + libmultipath/config.h | 3 + + libmultipath/configure.c | 15 +++-- + libmultipath/defaults.h | 1 + libmultipath/devmapper.c | 35 +++++++++---- + libmultipath/devmapper.h | 8 ++- + libmultipath/dict.c | 114 +++++++++++++++++++++++++++++++++++++++++++++ + libmultipath/propsel.c | 26 ++++++++++ + libmultipath/propsel.h | 1 + libmultipath/structs.h | 7 ++ + multipath/multipath.conf.5 | 10 +++ + multipath/multipath.rules | 1 + multipathd/cli_handlers.c | 4 + + 13 files changed, 211 insertions(+), 17 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -343,6 +343,7 @@ merge_hwe (struct hwentry * dst, struct + merge_num(deferred_remove); + merge_num(delay_watch_checks); + merge_num(delay_wait_checks); ++ merge_num(skip_kpartx); + + /* + * Make sure features is consistent with +@@ -403,6 +404,7 @@ overwrite_hwe (struct hwentry * dst, str + overwrite_num(deferred_remove); + overwrite_num(delay_watch_checks); + overwrite_num(delay_wait_checks); ++ overwrite_num(skip_kpartx); + + /* + * Make sure features is consistent with +@@ -677,6 +679,7 @@ load_config (char * file, struct udev *u + conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; + conf->new_bindings_in_boot = 0; + conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT; ++ conf->skip_kpartx = DEFAULT_SKIP_KPARTX; + + /* + * preload default hwtable +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -64,6 +64,7 @@ struct hwentry { + int deferred_remove; + int delay_watch_checks; + int delay_wait_checks; ++ int skip_kpartx; + char * bl_product; + }; + +@@ -90,6 +91,7 @@ struct mpentry { + int deferred_remove; + int delay_watch_checks; + int delay_wait_checks; ++ int skip_kpartx; + uid_t uid; + gid_t gid; + mode_t mode; +@@ -143,6 +145,7 @@ struct config { + int new_bindings_in_boot; + int delayed_reconfig; + int uev_wait_timeout; ++ int skip_kpartx; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -294,6 +294,7 @@ setup_map (struct multipath * mpp, char + select_deferred_remove(mpp); + select_delay_watch_checks(mpp); + select_delay_wait_checks(mpp); ++ select_skip_kpartx(mpp); + + sysfs_set_scsi_tmo(mpp); + /* +@@ -446,6 +447,7 @@ select_action (struct multipath * mpp, v + } + mpp->force_udev_reload = !pathcount(mpp, PATH_WILD); + if (cmpp->size != mpp->size) { ++ mpp->force_udev_reload = 1; + mpp->action = ACT_RESIZE; + condlog(3, "%s: set ACT_RESIZE (size change)", + mpp->alias); +@@ -609,6 +611,7 @@ extern int + domap (struct multipath * mpp, char * params) + { + int r = 0; ++ uint16_t udev_flags = ((mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG) | ((mpp->skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0); + + /* + * last chance to quit before touching the devmaps +@@ -654,25 +657,27 @@ domap (struct multipath * mpp, char * pa + case ACT_RELOAD: + r = dm_addmap_reload(mpp, params); + if (r) +- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG); ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, ++ udev_flags); + break; + + case ACT_RESIZE: + r = dm_addmap_reload(mpp, params); + if (r) +- r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1, 0); ++ r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1, ++ udev_flags); + break; + + case ACT_RENAME: +- r = dm_rename(mpp->alias_old, mpp->alias); ++ r = dm_rename(mpp->alias_old, mpp->alias, mpp->skip_kpartx); + break; + + case ACT_RENAME2: +- r = dm_rename(mpp->alias_old, mpp->alias); ++ r = dm_rename(mpp->alias_old, mpp->alias, mpp->skip_kpartx); + if (r) { + r = dm_addmap_reload(mpp, params); + if (r) +- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, (mpp->force_udev_reload)? 0 : MPATH_UDEV_RELOAD_FLAG); ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, udev_flags); + } + break; + +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -24,6 +24,7 @@ + #define DEFAULT_RETRIGGER_DELAY 10 + #define DEFAULT_RETRIGGER_TRIES 3 + #define DEFAULT_UEV_WAIT_TIMEOUT 30 ++#define DEFAULT_SKIP_KPARTX SKIP_KPARTX_OFF + + #define DEFAULT_CHECKINT 5 + #define MAX_CHECKINT(a) (a << 2) +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -262,13 +262,14 @@ dm_device_remove (const char *name, int + deferred_remove); + } + +-extern int ++static int + dm_addmap (int task, const char *target, struct multipath *mpp, char * params, +- int use_uuid, int ro) { ++ int use_uuid, int ro, int skip_kpartx) { + int r = 0; + struct dm_task *dmt; + char *prefixed_uuid = NULL; + uint32_t cookie = 0; ++ uint16_t udev_flags = ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0); + + if (!(dmt = dm_task_create (task))) + return 0; +@@ -309,7 +310,7 @@ dm_addmap (int task, const char *target, + dm_task_no_open_count(dmt); + + if (task == DM_DEVICE_CREATE && +- !dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) ++ !dm_task_set_cookie(dmt, &cookie, udev_flags)) + goto freeout; + r = dm_task_run (dmt); + +@@ -332,7 +333,8 @@ dm_addmap_create (struct multipath *mpp, + for (ro = 0; ro <= 1; ro++) { + int err; + +- if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, 1, ro)) ++ if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, ++ mpp, params, 1, ro, mpp->skip_kpartx)) + return 1; + /* + * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD. +@@ -354,11 +356,11 @@ dm_addmap_create (struct multipath *mpp, + + extern int + dm_addmap_reload (struct multipath *mpp, char *params) { +- if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW)) ++ if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW, SKIP_KPARTX_OFF)) + return 1; + if (errno != EROFS) + return 0; +- return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO); ++ return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO, SKIP_KPARTX_OFF); + } + + extern int +@@ -720,6 +722,12 @@ out: + } + + static int ++has_partmap(const char *name, void *data) ++{ ++ return 1; ++} ++ ++static int + partmap_in_use(const char *name, void *data) + { + int part_count, *ret_count = (int *)data; +@@ -798,10 +806,16 @@ dm_suspend_and_flush_map (const char * m + int s = 0, queue_if_no_path = 0; + unsigned long long mapsize; + char params[PARAMS_SIZE] = {0}; ++ int udev_flags = 0; + + if (!dm_is_mpath(mapname)) + return 0; /* nothing to do */ + ++ /* if the device currently has no partitions, do not ++ run kpartx on it if you fail to delete it */ ++ if (do_foreach_partmaps(mapname, has_partmap, NULL) == 0) ++ udev_flags |= MPATH_UDEV_NO_KPARTX_FLAG; ++ + if (!dm_get_map(mapname, &mapsize, params)) { + if (strstr(params, "queue_if_no_path")) + queue_if_no_path = 1; +@@ -820,7 +834,7 @@ dm_suspend_and_flush_map (const char * m + return 0; + } + condlog(2, "failed to remove multipath map %s", mapname); +- dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 0); ++ dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, udev_flags); + if (queue_if_no_path) + s = dm_queue_if_no_path((char *)mapname, 1); + return 1; +@@ -1349,7 +1363,7 @@ rename_partmap (const char *name, void * + for (offset = strlen(rd->old); name[offset] && !(isdigit(name[offset])); offset++); /* do nothing */ + snprintf(buff, PARAMS_SIZE, "%s%s%s", rd->new, rd->delim, + name + offset); +- dm_rename(name, buff); ++ dm_rename(name, buff, SKIP_KPARTX_OFF); + condlog(4, "partition map %s renamed", name); + return 0; + } +@@ -1369,11 +1383,12 @@ dm_rename_partmaps (const char * old, ch + } + + int +-dm_rename (const char * old, char * new) ++dm_rename (const char * old, char * new, int skip_kpartx) + { + int r = 0; + struct dm_task *dmt; + uint32_t cookie; ++ uint16_t udev_flags = ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0); + + if (dm_rename_partmaps(old, new)) + return r; +@@ -1389,7 +1404,7 @@ dm_rename (const char * old, char * new) + + dm_task_no_open_count(dmt); + +- if (!dm_task_set_cookie(dmt, &cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) ++ if (!dm_task_set_cookie(dmt, &cookie, udev_flags)) + goto out; + r = dm_task_run(dmt); + +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -12,6 +12,12 @@ + #define MPATH_UDEV_RELOAD_FLAG 0 + #endif + ++#ifdef DM_SUBSYSTEM_UDEV_FLAG1 ++#define MPATH_UDEV_NO_KPARTX_FLAG DM_SUBSYSTEM_UDEV_FLAG1 ++#else ++#define MPATH_UDEV_NO_KPARTX_FLAG 0 ++#endif ++ + void dm_init(void); + int dm_prereq (void); + int dm_drv_version (unsigned int * version, char * str); +@@ -47,7 +53,7 @@ int dm_remove_partmaps (const char * map + int deferred_remove); + int dm_get_uuid(char *name, char *uuid); + int dm_get_info (char * mapname, struct dm_info ** dmi); +-int dm_rename (const char * old, char * new); ++int dm_rename (const char * old, char * new, int skip_kpartx); + int dm_reassign(const char * mapname); + int dm_reassign_table(const char *name, char *old, char *new); + int dm_setgeometry(struct multipath *mpp); +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -779,6 +779,29 @@ def_deferred_remove_handler(vector strve + } + + static int ++def_skip_kpartx_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->skip_kpartx = SKIP_KPARTX_OFF; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ conf->skip_kpartx = SKIP_KPARTX_ON; ++ else ++ conf->skip_kpartx = DEFAULT_SKIP_KPARTX; ++ ++ FREE(buff); ++ return 0; ++} ++ ++static int + def_ignore_new_boot_devs_handler(vector strvec) + { + char * buff; +@@ -1629,6 +1652,33 @@ hw_deferred_remove_handler(vector strvec + } + + static int ++hw_skip_kpartx_handler(vector strvec) ++{ ++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); ++ char * buff; ++ ++ if (!hwe) ++ return 1; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ hwe->skip_kpartx = SKIP_KPARTX_OFF; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ hwe->skip_kpartx = SKIP_KPARTX_ON; ++ else ++ hwe->skip_kpartx = SKIP_KPARTX_UNDEF; ++ ++ FREE(buff); ++ return 0; ++} ++ ++static int + hw_delay_watch_checks_handler(vector strvec) + { + struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); +@@ -2154,6 +2204,32 @@ mp_deferred_remove_handler(vector strvec + } + + static int ++mp_skip_kpartx_handler(vector strvec) ++{ ++ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); ++ char * buff; ++ ++ if (!mpe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && strcmp(buff, "no") == 0) || ++ (strlen(buff) == 1 && strcmp(buff, "0") == 0)) ++ mpe->skip_kpartx = SKIP_KPARTX_OFF; ++ else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) || ++ (strlen(buff) == 1 && strcmp(buff, "1") == 0)) ++ mpe->skip_kpartx = SKIP_KPARTX_ON; ++ else ++ mpe->skip_kpartx = SKIP_KPARTX_UNDEF; ++ ++ FREE(buff); ++ return 0; ++} ++ ++static int + mp_delay_watch_checks_handler(vector strvec) + { + struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); +@@ -2461,6 +2537,19 @@ snprint_mp_deferred_remove (char * buff, + } + + static int ++snprint_mp_skip_kpartx (char * buff, int len, void * data) ++{ ++ struct mpentry * mpe = (struct mpentry *)data; ++ ++ if (mpe->skip_kpartx == SKIP_KPARTX_UNDEF) ++ return 0; ++ else if (mpe->skip_kpartx == SKIP_KPARTX_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return snprintf(buff, len, "yes"); ++} ++ ++static int + snprint_mp_delay_watch_checks(char * buff, int len, void * data) + { + struct mpentry * mpe = (struct mpentry *)data; +@@ -2813,6 +2902,19 @@ snprint_hw_deferred_remove(char * buff, + } + + static int ++snprint_hw_skip_kpartx(char * buff, int len, void * data) ++{ ++ struct hwentry * hwe = (struct hwentry *)data; ++ ++ if (hwe->skip_kpartx == SKIP_KPARTX_ON) ++ return snprintf(buff, len, "yes"); ++ else if (hwe->skip_kpartx == SKIP_KPARTX_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return 0; ++} ++ ++static int + snprint_hw_delay_watch_checks(char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -3231,6 +3333,15 @@ snprint_def_deferred_remove(char * buff, + } + + static int ++snprint_def_skip_kpartx(char * buff, int len, void * data) ++{ ++ if (conf->skip_kpartx == SKIP_KPARTX_ON) ++ return snprintf(buff, len, "yes"); ++ else ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_def_ignore_new_boot_devs(char * buff, int len, void * data) + { + if (conf->ignore_new_boot_devs == 1) +@@ -3364,6 +3475,7 @@ init_keywords(void) + install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync); + install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove); + install_keyword("ignore_new_boot_devs", &def_ignore_new_boot_devs_handler, &snprint_def_ignore_new_boot_devs); ++ install_keyword("skip_kpartx", &def_skip_kpartx_handler, &snprint_def_skip_kpartx); + install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir); + install_keyword("delay_watch_checks", &def_delay_watch_checks_handler, &snprint_def_delay_watch_checks); + install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks); +@@ -3438,6 +3550,7 @@ init_keywords(void) + install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove); + install_keyword("delay_watch_checks", &hw_delay_watch_checks_handler, &snprint_hw_delay_watch_checks); + install_keyword("delay_wait_checks", &hw_delay_wait_checks_handler, &snprint_hw_delay_wait_checks); ++ install_keyword("skip_kpartx", &hw_skip_kpartx_handler, &snprint_hw_skip_kpartx); + install_sublevel_end(); + + install_keyword_root("multipaths", &multipaths_handler); +@@ -3465,5 +3578,6 @@ init_keywords(void) + install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove); + install_keyword("delay_watch_checks", &mp_delay_watch_checks_handler, &snprint_mp_delay_watch_checks); + install_keyword("delay_wait_checks", &mp_delay_wait_checks_handler, &snprint_mp_delay_wait_checks); ++ install_keyword("skip_kpartx", &mp_skip_kpartx_handler, &snprint_mp_skip_kpartx); + install_sublevel_end(); + } +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -854,3 +854,29 @@ select_delay_wait_checks (struct multipa + condlog(3, "delay_wait_checks = DISABLED (internal default)"); + return 0; + } ++ ++extern int ++select_skip_kpartx (struct multipath * mp) ++{ ++ if (mp->mpe && mp->mpe->skip_kpartx != SKIP_KPARTX_UNDEF) { ++ mp->skip_kpartx = mp->mpe->skip_kpartx; ++ condlog(3, "skip_kpartx = %i (multipath setting)", ++ mp->skip_kpartx); ++ return 0; ++ } ++ if (mp->hwe && mp->hwe->skip_kpartx != SKIP_KPARTX_UNDEF) { ++ mp->skip_kpartx = mp->hwe->skip_kpartx; ++ condlog(3, "skip_kpartx = %i (controler setting)", ++ mp->skip_kpartx); ++ return 0; ++ } ++ if (conf->skip_kpartx != SKIP_KPARTX_UNDEF) { ++ mp->skip_kpartx = conf->skip_kpartx; ++ condlog(3, "skip_kpartx = %i (config file default)", ++ mp->skip_kpartx); ++ return 0; ++ } ++ mp->skip_kpartx = DEFAULT_SKIP_KPARTX; ++ condlog(3, "skip_kpartx = DISABLED (internal default)"); ++ return 0; ++} +Index: multipath-tools-130222/libmultipath/propsel.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.h ++++ multipath-tools-130222/libmultipath/propsel.h +@@ -23,3 +23,4 @@ int select_detect_prio(struct path * pp) + int select_deferred_remove(struct multipath *mp); + int select_delay_watch_checks (struct multipath * mp); + int select_delay_wait_checks (struct multipath * mp); ++int select_skip_kpartx (struct multipath * mp); +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -121,6 +121,12 @@ enum deferred_remove_states { + DEFERRED_REMOVE_IN_PROGRESS, + }; + ++enum skip_kpartx_states { ++ SKIP_KPARTX_UNDEF, ++ SKIP_KPARTX_OFF, ++ SKIP_KPARTX_ON, ++}; ++ + enum scsi_protocol { + SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */ + SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */ +@@ -236,6 +242,7 @@ struct multipath { + int delay_watch_checks; + int delay_wait_checks; + int force_udev_reload; ++ int skip_kpartx; + unsigned int dev_loss; + uid_t uid; + gid_t gid; +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -44,6 +44,7 @@ KERNEL!="dm-*", GOTO="end_mpath" + ENV{DM_UUID}=="mpath-?*|part[0-9]*-mpath-?*", OPTIONS+="link_priority=10" + ACTION!="change", GOTO="end_mpath" + ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath" ++ENV{DM_SUBSYSTEM_UDEV_FLAG1}=="1", GOTO="end_mpath" + ENV{DM_ACTIVATION}=="1", ENV{DM_MULTIPATH_NEED_KPARTX}="1" + ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" + ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -825,19 +825,21 @@ cli_resume(void * v, char ** reply, int + char * param = get_keyparam(v, MAP); + int r; + struct multipath * mpp; ++ uint16_t udev_flags; + + param = convert_dev(param, 0); + mpp = find_mp_by_alias(vecs->mpvec, param); + if (!mpp) + return 1; + ++ udev_flags = (mpp->skip_kpartx)? MPATH_UDEV_NO_KPARTX_FLAG : 0; + if (mpp->wait_for_udev) { + condlog(2, "%s: device not fully created, failing resume", + mpp->alias); + return 1; + } + +- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, udev_flags); + + condlog(2, "%s: resume (operator)", param); + +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -505,6 +505,12 @@ automatically enabling device reloads. U + on a device until it receives a change uevent from the initial table load. The + default is + .I 30 ++.TP ++.B skip_kpartx ++If set to ++.I yes ++, kpartx will not automatically create partitions on the device. The default is ++.I no + . + .SH "blacklist section" + The +@@ -612,6 +618,8 @@ section: + .B delay_watch_checks + .TP + .B delay_wait_checks ++.TP ++.B skip_kpartx + .RE + .PD + .LP +@@ -708,6 +716,8 @@ section: + .B delay_watch_checks + .TP + .B delay_wait_checks ++.TP ++.B skip_kpartx + .RE + .PD + .LP diff --git a/SOURCES/0162-RHBZ-1333331-huawei-config.patch b/SOURCES/0162-RHBZ-1333331-huawei-config.patch new file mode 100644 index 0000000..7b97e07 --- /dev/null +++ b/SOURCES/0162-RHBZ-1333331-huawei-config.patch @@ -0,0 +1,24 @@ +--- + libmultipath/hwtable.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1182,6 +1182,15 @@ static struct hwentry default_hw[] = { + .dev_loss = 60, + .prio_args = NULL, + }, ++ { ++ .vendor = "HUAWEI", ++ .product = "XSG1", ++ .features = DEFAULT_FEATURES, ++ .hwhandler = DEFAULT_HWHANDLER, ++ .pgpolicy = MULTIBUS, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .checker_name = TUR, ++ }, + /* + * EOL + */ diff --git a/SOURCES/0163-UPBZ-1333492-resize-map.patch b/SOURCES/0163-UPBZ-1333492-resize-map.patch new file mode 100644 index 0000000..cc24b6f --- /dev/null +++ b/SOURCES/0163-UPBZ-1333492-resize-map.patch @@ -0,0 +1,24 @@ +--- + multipathd/cli_handlers.c | 2 ++ + 1 file changed, 2 insertions(+) + +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -571,6 +571,7 @@ int resize_map(struct multipath *mpp, un + struct vectors * vecs) + { + char params[PARAMS_SIZE] = {0}; ++ unsigned long long orig_size = mpp->size; + + mpp->size = size; + update_mpp_paths(mpp, vecs->pathvec); +@@ -579,6 +580,7 @@ int resize_map(struct multipath *mpp, un + if (domap(mpp, params) <= 0) { + condlog(0, "%s: failed to resize map : %s", mpp->alias, + strerror(errno)); ++ mpp->size = orig_size; + return 1; + } + return 0; diff --git a/SOURCES/0164-RHBZ-1311463-dos-part-rollover.patch b/SOURCES/0164-RHBZ-1311463-dos-part-rollover.patch new file mode 100644 index 0000000..dc511f2 --- /dev/null +++ b/SOURCES/0164-RHBZ-1311463-dos-part-rollover.patch @@ -0,0 +1,17 @@ +--- + kpartx/dos.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/kpartx/dos.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/dos.c ++++ multipath-tools-130222/kpartx/dos.c +@@ -78,7 +78,7 @@ read_dos_pt(int fd, struct slice all, st + unsigned long offset = all.start; + int i, n=4; + unsigned char *bp; +- int sector_size_mul = get_sector_size(fd)/512; ++ uint64_t sector_size_mul = get_sector_size(fd)/512; + + bp = (unsigned char *)getblock(fd, offset); + if (bp == NULL) diff --git a/SOURCES/0165-UPBZ-1341748-MSA-2040-conf.patch b/SOURCES/0165-UPBZ-1341748-MSA-2040-conf.patch new file mode 100644 index 0000000..6c6e64a --- /dev/null +++ b/SOURCES/0165-UPBZ-1341748-MSA-2040-conf.patch @@ -0,0 +1,30 @@ +--- + libmultipath/hwtable.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -175,6 +175,21 @@ static struct hwentry default_hw[] = { + .prio_name = PRIO_ALUA, + .prio_args = NULL, + }, ++ { ++ /* HP MSA 1040/2040 product family */ ++ .vendor = "HP", ++ .product = "MSA (1|2)040 SA(N|S)", ++ .features = DEFAULT_FEATURES, ++ .hwhandler = DEFAULT_HWHANDLER, ++ .pgpolicy = GROUP_BY_PRIO, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .rr_weight = RR_WEIGHT_NONE, ++ .no_path_retry = 18, ++ .minio = 100, ++ .checker_name = TUR, ++ .prio_name = PRIO_ALUA, ++ .prio_args = NULL, ++ }, + + { + /* HP SVSP */ diff --git a/SOURCES/0166-RHBZ-1323429-dont-allow-new-wwid.patch b/SOURCES/0166-RHBZ-1323429-dont-allow-new-wwid.patch new file mode 100644 index 0000000..b0fc664 --- /dev/null +++ b/SOURCES/0166-RHBZ-1323429-dont-allow-new-wwid.patch @@ -0,0 +1,24 @@ +--- + libmultipath/dmparser.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +Index: multipath-tools-130222/libmultipath/dmparser.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dmparser.c ++++ multipath-tools-130222/libmultipath/dmparser.c +@@ -360,6 +360,15 @@ disassemble_map (vector pathvec, char * + else if (!strlen(pp->wwid)) + strncpy(pp->wwid, mpp->wwid, WWID_SIZE); + ++ /* ++ * Something went wrong. Likely the user changed the ++ * path uid_attribute after creating a device ++ */ ++ else if (strcmp(pp->wwid, mpp->wwid) != 0) { ++ condlog(0, "%s: path wwid appears to have changed. Using old wwid.\n", pp->dev_t); ++ strncpy(pp->wwid, mpp->wwid, WWID_SIZE); ++ } ++ + pgp->id ^= (long)pp; + pp->pgindex = i + 1; + diff --git a/SOURCES/0167-RHBZ-1335176-fix-show-cmds.patch b/SOURCES/0167-RHBZ-1335176-fix-show-cmds.patch new file mode 100644 index 0000000..cbc5817 --- /dev/null +++ b/SOURCES/0167-RHBZ-1335176-fix-show-cmds.patch @@ -0,0 +1,138 @@ +--- + libmultipath/print.c | 7 +++++++ + libmultipath/structs.h | 1 + + libmultipath/structs_vec.c | 24 ++++++++++++++---------- + multipathd/cli_handlers.c | 11 ++++++++++- + multipathd/main.c | 2 ++ + 5 files changed, 34 insertions(+), 11 deletions(-) + +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -248,6 +248,12 @@ snprint_q_timeouts (char * buff, size_t + } + + static int ++snprint_map_failures (char * buff, size_t len, struct multipath * mpp) ++{ ++ return snprint_uint(buff, len, mpp->stat_map_failures); ++} ++ ++static int + snprint_multipath_uuid (char * buff, size_t len, struct multipath * mpp) + { + return snprint_str(buff, len, mpp->wwid); +@@ -546,6 +552,7 @@ struct multipath_data mpd[] = { + {'t', "dm-st", 0, snprint_dm_map_state}, + {'S', "size", 0, snprint_multipath_size}, + {'f', "features", 0, snprint_features}, ++ {'x', "failures", 0, snprint_map_failures}, + {'h', "hwhandler", 0, snprint_hwhandler}, + {'A', "action", 0, snprint_action}, + {'0', "path_faults", 0, snprint_path_faults}, +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -270,6 +270,7 @@ struct multipath { + unsigned int stat_map_loads; + unsigned int stat_total_queueing_time; + unsigned int stat_queueing_timeouts; ++ unsigned int stat_map_failures; + + /* checkers shared data */ + void * mpcontext; +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -579,16 +579,20 @@ int update_multipath (struct vectors *ve + */ + void update_queue_mode_del_path(struct multipath *mpp) + { +- if (--mpp->nr_active == 0 && mpp->no_path_retry > 0) { +- /* +- * Enter retry mode. +- * meaning of +1: retry_tick may be decremented in +- * checkerloop before starting retry. +- */ +- mpp->stat_queueing_timeouts++; +- mpp->retry_tick = mpp->no_path_retry * conf->checkint + 1; +- condlog(1, "%s: Entering recovery mode: max_retries=%d", +- mpp->alias, mpp->no_path_retry); ++ if (--mpp->nr_active == 0) { ++ if (mpp->no_path_retry > 0) { ++ /* ++ * Enter retry mode. ++ * meaning of +1: retry_tick may be decremented in ++ * checkerloop before starting retry. ++ */ ++ mpp->stat_queueing_timeouts++; ++ mpp->retry_tick = mpp->no_path_retry * ++ conf->checkint + 1; ++ condlog(1, "%s: Entering recovery mode: max_retries=%d", ++ mpp->alias, mpp->no_path_retry); ++ } else if (mpp->no_path_retry != NO_PATH_RETRY_QUEUE) ++ mpp->stat_map_failures++; + } + condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active); + } +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -319,9 +319,14 @@ show_maps (char ** r, int *len, struct v + c += snprint_multipath_header(c, reply + maxlen - c, + style); + +- vector_foreach_slot(vecs->mpvec, mpp, i) ++ vector_foreach_slot(vecs->mpvec, mpp, i) { ++ if (update_multipath(vecs, mpp->alias, 0)) { ++ i--; ++ continue; ++ } + c += snprint_multipath(c, reply + maxlen - c, + style, mpp, pretty); ++ } + + again = ((c - reply) == (maxlen - 1)); + +@@ -742,6 +747,8 @@ cli_disable_queueing(void *v, char **rep + return 1; + } + ++ if (mpp->nr_active == 0) ++ mpp->stat_map_failures++; + mpp->retry_tick = 0; + dm_queue_if_no_path(mpp->alias, 0); + return 0; +@@ -756,6 +763,8 @@ cli_disable_all_queueing(void *v, char * + + condlog(2, "disable queueing (operator)"); + vector_foreach_slot(vecs->mpvec, mpp, i) { ++ if (mpp->nr_active == 0) ++ mpp->stat_map_failures++; + mpp->retry_tick = 0; + dm_queue_if_no_path(mpp->alias, 0); + } +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -716,6 +716,7 @@ ev_remove_path (struct path *pp, struct + mpp->retry_tick = 0; + mpp->no_path_retry = NO_PATH_RETRY_FAIL; + mpp->flush_on_last_del = FLUSH_IN_PROGRESS; ++ mpp->stat_map_failures++; + dm_queue_if_no_path(mpp->alias, 0); + } + if (!flush_map(mpp, vecs, 1)) { +@@ -1197,6 +1198,7 @@ retry_count_tick(vector mpvec) + mpp->stat_total_queueing_time++; + condlog(4, "%s: Retrying.. No active path", mpp->alias); + if(--mpp->retry_tick == 0) { ++ mpp->stat_map_failures++; + dm_queue_if_no_path(mpp->alias, 0); + condlog(2, "%s: Disable queueing", mpp->alias); + } diff --git a/SOURCES/0168-RHBZ-1347769-shared-lock.patch b/SOURCES/0168-RHBZ-1347769-shared-lock.patch new file mode 100644 index 0000000..084d112 --- /dev/null +++ b/SOURCES/0168-RHBZ-1347769-shared-lock.patch @@ -0,0 +1,17 @@ +--- + libmultipath/configure.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -552,7 +552,7 @@ lock_multipath (struct multipath * mpp, + if (!pgp->paths) + continue; + vector_foreach_slot(pgp->paths, pp, j) { +- if (lock && flock(pp->fd, LOCK_EX | LOCK_NB) && ++ if (lock && flock(pp->fd, LOCK_SH | LOCK_NB) && + errno == EWOULDBLOCK) + goto fail; + else if (!lock) diff --git a/SOURCES/0169-UPBZ-1353357-json-output.patch b/SOURCES/0169-UPBZ-1353357-json-output.patch new file mode 100644 index 0000000..14fa840 --- /dev/null +++ b/SOURCES/0169-UPBZ-1353357-json-output.patch @@ -0,0 +1,549 @@ +--- + libmultipath/print.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++ + libmultipath/print.h | 61 ++++++++++++ + multipathd/cli.c | 3 + multipathd/cli.h | 2 + multipathd/cli_handlers.c | 93 +++++++++++++++++++ + multipathd/cli_handlers.h | 2 + multipathd/main.c | 2 + multipathd/multipathd.8 | 9 + + 8 files changed, 393 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -269,6 +269,61 @@ snprint_multipath_vpr (char * buff, size + pp->vendor_id, pp->product_id); + } + ++ ++static int ++snprint_multipath_vend (char * buff, size_t len, struct multipath * mpp) ++{ ++ struct pathgroup * pgp; ++ struct path * pp; ++ int i, j; ++ ++ vector_foreach_slot(mpp->pg, pgp, i) { ++ if (!pgp) ++ continue; ++ vector_foreach_slot(pgp->paths, pp, j) { ++ if (strlen(pp->vendor_id)) ++ return snprintf(buff, len, "%s", pp->vendor_id); ++ } ++ } ++ return snprintf(buff, len, "##"); ++} ++ ++static int ++snprint_multipath_prod (char * buff, size_t len, struct multipath * mpp) ++{ ++ struct pathgroup * pgp; ++ struct path * pp; ++ int i, j; ++ ++ vector_foreach_slot(mpp->pg, pgp, i) { ++ if (!pgp) ++ continue; ++ vector_foreach_slot(pgp->paths, pp, j) { ++ if (strlen(pp->product_id)) ++ return snprintf(buff, len, "%s", pp->product_id); ++ } ++ } ++ return snprintf(buff, len, "##"); ++} ++ ++static int ++snprint_multipath_rev (char * buff, size_t len, struct multipath * mpp) ++{ ++ struct pathgroup * pgp; ++ struct path * pp; ++ int i, j; ++ ++ vector_foreach_slot(mpp->pg, pgp, i) { ++ if (!pgp) ++ continue; ++ vector_foreach_slot(pgp->paths, pp, j) { ++ if (strlen(pp->rev)) ++ return snprintf(buff, len, "%s", pp->rev); ++ } ++ } ++ return snprintf(buff, len, "##"); ++} ++ + static int + snprint_action (char * buff, size_t len, struct multipath * mpp) + { +@@ -561,6 +616,9 @@ struct multipath_data mpd[] = { + {'3', "total_q_time", 0, snprint_total_q_time}, + {'4', "q_timeouts", 0, snprint_q_timeouts}, + {'s', "vend/prod/rev", 0, snprint_multipath_vpr}, ++ {'v', "vend", 0, snprint_multipath_vend}, ++ {'p', "prod", 0, snprint_multipath_prod}, ++ {'e', "rev", 0, snprint_multipath_rev}, + {0, NULL, 0 , NULL} + }; + +@@ -983,6 +1041,170 @@ snprint_multipath_topology (char * buff, + return fwd; + } + ++static int ++snprint_json (char * buff, int len, int indent, char *json_str) ++{ ++ int fwd = 0, i; ++ ++ for (i = 0; i < indent; i++) { ++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_INDENT); ++ if (fwd > len) ++ return fwd; ++ } ++ ++ fwd += snprintf(buff + fwd, len - fwd, "%s", json_str); ++ return fwd; ++} ++ ++static int ++snprint_json_header (char * buff, int len) ++{ ++ int fwd = 0; ++ ++ fwd += snprint_json(buff, len, 0, PRINT_JSON_START_ELEM); ++ if (fwd > len) ++ return fwd; ++ ++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_START_VERSION, ++ PRINT_JSON_MAJOR_VERSION, PRINT_JSON_MINOR_VERSION); ++ return fwd; ++} ++ ++static int ++snprint_json_elem_footer (char * buff, int len, int indent, int last) ++{ ++ int fwd = 0, i; ++ ++ for (i = 0; i < indent; i++) { ++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_INDENT); ++ if (fwd > len) ++ return fwd; ++ } ++ ++ if (last == 1) ++ fwd += snprintf(buff + fwd, len - fwd, "%s", PRINT_JSON_END_LAST_ELEM); ++ else ++ fwd += snprintf(buff + fwd, len - fwd, "%s", PRINT_JSON_END_ELEM); ++ return fwd; ++} ++ ++static int ++snprint_multipath_fields_json (char * buff, int len, ++ struct multipath * mpp, int last) ++{ ++ int i, j, fwd = 0; ++ struct path *pp; ++ struct pathgroup *pgp; ++ ++ fwd += snprint_multipath(buff, len, PRINT_JSON_MAP, mpp, 0); ++ if (fwd > len) ++ return fwd; ++ ++ fwd += snprint_json(buff + fwd, len - fwd, 2, PRINT_JSON_START_GROUPS); ++ if (fwd > len) ++ return fwd; ++ ++ vector_foreach_slot (mpp->pg, pgp, i) { ++ ++ pgp->selector = mpp->selector; ++ fwd += snprint_pathgroup(buff + fwd, len - fwd, PRINT_JSON_GROUP, pgp); ++ if (fwd > len) ++ return fwd; ++ ++ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_GROUP_NUM, i + 1); ++ if (fwd > len) ++ return fwd; ++ ++ fwd += snprint_json(buff + fwd, len - fwd, 3, PRINT_JSON_START_PATHS); ++ if (fwd > len) ++ return fwd; ++ ++ vector_foreach_slot (pgp->paths, pp, j) { ++ fwd += snprint_path(buff + fwd, len - fwd, PRINT_JSON_PATH, pp, 0); ++ if (fwd > len) ++ return fwd; ++ ++ fwd += snprint_json_elem_footer(buff + fwd, ++ len - fwd, 3, j + 1 == VECTOR_SIZE(pgp->paths)); ++ if (fwd > len) ++ return fwd; ++ } ++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY); ++ if (fwd > len) ++ return fwd; ++ ++ fwd += snprint_json_elem_footer(buff + fwd, ++ len - fwd, 2, i + 1 == VECTOR_SIZE(mpp->pg)); ++ if (fwd > len) ++ return fwd; ++ } ++ ++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY); ++ if (fwd > len) ++ return fwd; ++ ++ fwd += snprint_json_elem_footer(buff + fwd, len - fwd, 1, last); ++ return fwd; ++} ++ ++int ++snprint_multipath_map_json (char * buff, int len, ++ struct multipath * mpp, int last){ ++ int fwd = 0; ++ ++ fwd += snprint_json_header(buff, len); ++ if (fwd > len) ++ return len; ++ ++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_START_MAP); ++ if (fwd > len) ++ return len; ++ ++ fwd += snprint_multipath_fields_json(buff + fwd, len - fwd, mpp, 1); ++ if (fwd > len) ++ return len; ++ ++ fwd += snprint_json(buff + fwd, len - fwd, 0, "\n"); ++ if (fwd > len) ++ return len; ++ ++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_LAST); ++ if (fwd > len) ++ return len; ++ return fwd; ++} ++ ++int ++snprint_multipath_topology_json (char * buff, int len, struct vectors * vecs) ++{ ++ int i, fwd = 0; ++ struct multipath * mpp; ++ ++ fwd += snprint_json_header(buff, len); ++ if (fwd > len) ++ return len; ++ ++ fwd += snprint_json(buff + fwd, len - fwd, 1, PRINT_JSON_START_MAPS); ++ if (fwd > len) ++ return len; ++ ++ vector_foreach_slot(vecs->mpvec, mpp, i) { ++ fwd += snprint_multipath_fields_json(buff + fwd, len - fwd, ++ mpp, i + 1 == VECTOR_SIZE(vecs->mpvec)); ++ if (fwd > len) ++ return len; ++ } ++ ++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY); ++ if (fwd > len) ++ return len; ++ ++ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_LAST); ++ if (fwd > len) ++ return len; ++ return fwd; ++} ++ + static int + snprint_hwentry (char * buff, int len, struct hwentry * hwe) + { +Index: multipath-tools-130222/libmultipath/print.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.h ++++ multipath-tools-130222/libmultipath/print.h +@@ -7,6 +7,63 @@ + #define PRINT_MAP_PROPS "size=%S features='%f' hwhandler='%h' wp=%r" + #define PRINT_PG_INDENT "policy='%s' prio=%p status=%t" + ++#define PRINT_JSON_MULTIPLIER 5 ++#define PRINT_JSON_MAJOR_VERSION 0 ++#define PRINT_JSON_MINOR_VERSION 1 ++#define PRINT_JSON_START_VERSION " \"major_version\": %d,\n" \ ++ " \"minor_version\": %d,\n" ++#define PRINT_JSON_START_ELEM "{\n" ++#define PRINT_JSON_START_MAP " \"map\":" ++#define PRINT_JSON_START_MAPS "\"maps\": [" ++#define PRINT_JSON_START_PATHS "\"paths\": [" ++#define PRINT_JSON_START_GROUPS "\"path_groups\": [" ++#define PRINT_JSON_END_ELEM "}," ++#define PRINT_JSON_END_LAST_ELEM "}" ++#define PRINT_JSON_END_LAST "}\n" ++#define PRINT_JSON_END_ARRAY "]\n" ++#define PRINT_JSON_INDENT " " ++#define PRINT_JSON_MAP "{\n" \ ++ " \"name\" : \"%n\",\n" \ ++ " \"uuid\" : \"%w\",\n" \ ++ " \"sysfs\" : \"%d\",\n" \ ++ " \"failback\" : \"%F\",\n" \ ++ " \"queueing\" : \"%Q\",\n" \ ++ " \"paths\" : %N,\n" \ ++ " \"write_prot\" : \"%r\",\n" \ ++ " \"dm_st\" : \"%t\",\n" \ ++ " \"features\" : \"%f\",\n" \ ++ " \"hwhandler\" : \"%h\",\n" \ ++ " \"action\" : \"%A\",\n" \ ++ " \"path_faults\" : %0,\n" \ ++ " \"vend\" : \"%v\",\n" \ ++ " \"prod\" : \"%p\",\n" \ ++ " \"rev\" : \"%e\",\n" \ ++ " \"switch_grp\" : %1,\n" \ ++ " \"map_loads\" : %2,\n" \ ++ " \"total_q_time\" : %3,\n" \ ++ " \"q_timeouts\" : %4," ++ ++#define PRINT_JSON_GROUP "{\n" \ ++ " \"selector\" : \"%s\",\n" \ ++ " \"pri\" : %p,\n" \ ++ " \"dm_st\" : \"%t\"," ++ ++#define PRINT_JSON_GROUP_NUM " \"group\" : %d,\n" ++ ++#define PRINT_JSON_PATH "{\n" \ ++ " \"dev\" : \"%d\",\n"\ ++ " \"dev_t\" : \"%D\",\n" \ ++ " \"dm_st\" : \"%t\",\n" \ ++ " \"dev_st\" : \"%o\",\n" \ ++ " \"chk_st\" : \"%T\",\n" \ ++ " \"checker\" : \"%c\",\n" \ ++ " \"pri\" : %p,\n" \ ++ " \"host_wwnn\" : \"%N\",\n" \ ++ " \"target_wwnn\" : \"%n\",\n" \ ++ " \"host_wwpn\" : \"%R\",\n" \ ++ " \"target_wwpn\" : \"%r\",\n" \ ++ " \"host_adapter\" : \"%a\"" ++ + #define MAX_LINE_LEN 80 + #define MAX_LINES 64 + #define MAX_FIELD_LEN 64 +@@ -41,6 +98,10 @@ int snprint_path (char *, int, char *, s + int snprint_multipath (char *, int, char *, struct multipath *, int); + int snprint_multipath_topology (char *, int, struct multipath * mpp, + int verbosity); ++int snprint_multipath_topology_json (char * buff, int len, ++ struct vectors * vecs); ++int snprint_multipath_map_json (char * buff, int len, ++ struct multipath * mpp, int last); + int snprint_defaults (char *, int); + int snprint_blacklist (char *, int); + int snprint_blacklist_except (char *, int); +Index: multipath-tools-130222/multipathd/cli.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.c ++++ multipath-tools-130222/multipathd/cli.c +@@ -189,6 +189,7 @@ load_keys (void) + r += add_key(keys, "setprstatus", SETPRSTATUS, 0); + r += add_key(keys, "unsetprstatus", UNSETPRSTATUS, 0); + r += add_key(keys, "format", FMT, 1); ++ r += add_key(keys, "json", JSON, 0); + + if (r) { + free_keys(keys); +@@ -473,8 +474,10 @@ cli_init (void) { + add_handler(LIST+MAPS+FMT, NULL); + add_handler(LIST+MAPS+RAW+FMT, NULL); + add_handler(LIST+MAPS+TOPOLOGY, NULL); ++ add_handler(LIST+MAPS+JSON, NULL); + add_handler(LIST+TOPOLOGY, NULL); + add_handler(LIST+MAP+TOPOLOGY, NULL); ++ add_handler(LIST+MAP+JSON, NULL); + add_handler(LIST+CONFIG, NULL); + add_handler(LIST+BLACKLIST, NULL); + add_handler(LIST+DEVICES, NULL); +Index: multipath-tools-130222/multipathd/cli.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.h ++++ multipath-tools-130222/multipathd/cli.h +@@ -36,6 +36,7 @@ enum { + __SETPRSTATUS, + __UNSETPRSTATUS, + __FMT, ++ __JSON, + }; + + #define LIST (1 << __LIST) +@@ -74,6 +75,7 @@ enum { + #define SETPRSTATUS (1ULL << __SETPRSTATUS) + #define UNSETPRSTATUS (1ULL << __UNSETPRSTATUS) + #define FMT (1ULL << __FMT) ++#define JSON (1ULL << __JSON) + + #define INITIAL_REPLY_LEN 1200 + +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -127,6 +127,70 @@ show_maps_topology (char ** r, int * len + } + + int ++show_maps_json (char ** r, int * len, struct vectors * vecs) ++{ ++ int i; ++ struct multipath * mpp; ++ char * c; ++ char * reply; ++ unsigned int maxlen = INITIAL_REPLY_LEN * ++ PRINT_JSON_MULTIPLIER * VECTOR_SIZE(vecs->mpvec); ++ int again = 1; ++ ++ vector_foreach_slot(vecs->mpvec, mpp, i) { ++ if (update_multipath(vecs, mpp->alias, 0)) { ++ return 1; ++ } ++ } ++ ++ reply = MALLOC(maxlen); ++ ++ while (again) { ++ if (!reply) ++ return 1; ++ ++ c = reply; ++ ++ c += snprint_multipath_topology_json(c, maxlen, vecs); ++ again = ((c - reply) == maxlen); ++ ++ REALLOC_REPLY(reply, again, maxlen); ++ } ++ *r = reply; ++ *len = (int)(c - reply); ++ return 0; ++} ++ ++int ++show_map_json (char ** r, int * len, struct multipath * mpp, ++ struct vectors * vecs) ++{ ++ char * c; ++ char * reply; ++ unsigned int maxlen = INITIAL_REPLY_LEN; ++ int again = 1; ++ ++ if (update_multipath(vecs, mpp->alias, 0)) ++ return 1; ++ reply = MALLOC(maxlen); ++ ++ while (again) { ++ if (!reply) ++ return 1; ++ ++ c = reply; ++ ++ c += snprint_multipath_map_json(c, maxlen, mpp, 1); ++ again = ((c - reply) == maxlen); ++ ++ REALLOC_REPLY(reply, again, maxlen); ++ } ++ *r = reply; ++ *len = (int)(c - reply); ++ return 0; ++} ++ ++int + show_config (char ** r, int * len) + { + char * c; +@@ -239,6 +303,35 @@ cli_list_maps_topology (void * v, char * + } + + int ++cli_list_map_json (void * v, char ** reply, int * len, void * data) ++{ ++ struct multipath * mpp; ++ struct vectors * vecs = (struct vectors *)data; ++ char * param = get_keyparam(v, MAP); ++ ++ param = convert_dev(param, 0); ++ get_path_layout(vecs->pathvec, 0); ++ mpp = find_mp_by_str(vecs->mpvec, param); ++ ++ if (!mpp) ++ return 1; ++ ++ condlog(3, "list multipath json %s (operator)", param); ++ ++ return show_map_json(reply, len, mpp, vecs); ++} ++ ++int ++cli_list_maps_json (void * v, char ** reply, int * len, void * data) ++{ ++ struct vectors * vecs = (struct vectors *)data; ++ ++ condlog(3, "list multipaths json (operator)"); ++ ++ return show_maps_json(reply, len, vecs); ++} ++ ++int + cli_list_wildcards (void * v, char ** reply, int * len, void * data) + { + char * c; +Index: multipath-tools-130222/multipathd/cli_handlers.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.h ++++ multipath-tools-130222/multipathd/cli_handlers.h +@@ -10,6 +10,8 @@ int cli_list_maps_status (void * v, char + int cli_list_maps_stats (void * v, char ** reply, int * len, void * data); + int cli_list_map_topology (void * v, char ** reply, int * len, void * data); + int cli_list_maps_topology (void * v, char ** reply, int * len, void * data); ++int cli_list_map_json (void * v, char ** reply, int * len, void * data); ++int cli_list_maps_json (void * v, char ** reply, int * len, void * data); + int cli_list_config (void * v, char ** reply, int * len, void * data); + int cli_list_blacklist (void * v, char ** reply, int * len, void * data); + int cli_list_devices (void * v, char ** reply, int * len, void * data); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -981,7 +981,9 @@ uxlsnrloop (void * ap) + set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw); + set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology); + set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology); ++ set_handler_callback(LIST+MAPS+JSON, cli_list_maps_json); + set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology); ++ set_handler_callback(LIST+MAP+JSON, cli_list_map_json); + set_handler_callback(LIST+CONFIG, cli_list_config); + set_handler_callback(LIST+BLACKLIST, cli_list_blacklist); + set_handler_callback(LIST+DEVICES, cli_list_devices); +Index: multipath-tools-130222/multipathd/multipathd.8 +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.8 ++++ multipath-tools-130222/multipathd/multipathd.8 +@@ -53,11 +53,15 @@ using a format string with multipath for + Show the status of all multipath devices that the multipathd is monitoring. + .TP + .B list|show maps|multipaths stats +-Show some statistics of all multipath devices that the multipathd is monitoring. ++Show some statistics of all multipath devices that multipathd is monitoring. + .TP + .B list|show maps|multipaths topology + Show the current multipath topology. Same as "multipath \-ll". + .TP ++.B list|show maps|multipaths json ++Show the multipath devices that multipathd is monitoring, using JSON ++formatted output. ++.TP + .B list|show topology + Show the current multipath topology. Same as "multipath \-ll". + .TP +@@ -65,6 +69,9 @@ Show the current multipath topology. Sam + Show topology of a single multipath device specified by $map, e.g. 36005076303ffc56200000000000010aa. + This map could be obtained from "list maps". + .TP ++.B list|show map|multipath $map json ++Show a single multipath device specified by $map, using JSON formatted output. ++.TP + .B list|show wildcards + Show the format wildcards used in interactive commands taking $format + .TP diff --git a/SOURCES/0170-UPBZ-1352925-fix-typo.patch b/SOURCES/0170-UPBZ-1352925-fix-typo.patch new file mode 100644 index 0000000..2521c3d --- /dev/null +++ b/SOURCES/0170-UPBZ-1352925-fix-typo.patch @@ -0,0 +1,26 @@ +--- + multipath/main.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -286,7 +286,7 @@ configure (void) + if (failed == 2 && conf->cmd == CMD_VALID_PATH) + printf("%s is not a valid multipath device path\n", conf->dev); + else +- condlog(3, "scope is nul"); ++ condlog(3, "scope is null"); + goto out; + } + if (conf->cmd == CMD_REMOVE_WWID) { +@@ -358,7 +358,7 @@ configure (void) + + + if (conf->cmd == CMD_VALID_PATH) { +- /* This only happens if find_multipaths is and ++ /* This only happens if find_multipaths and + * ignore_wwids is set. + * If there is currently a multipath device matching + * the refwwid, or there is more than one path matching diff --git a/SOURCES/0171-UPBZ-1356651-allow-zero-size.patch b/SOURCES/0171-UPBZ-1356651-allow-zero-size.patch new file mode 100644 index 0000000..0fe05b5 --- /dev/null +++ b/SOURCES/0171-UPBZ-1356651-allow-zero-size.patch @@ -0,0 +1,79 @@ +--- + libmultipath/discovery.c | 5 +++++ + libmultipath/structs_vec.c | 2 +- + multipathd/main.c | 26 +++++--------------------- + 3 files changed, 11 insertions(+), 22 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -1188,6 +1188,11 @@ pathinfo (struct path *pp, vector hwtabl + if (pp->state == PATH_UNCHECKED || + pp->state == PATH_WILD) + goto blank; ++ if (pp->state == PATH_UP && !pp->size) { ++ condlog(3, "%s: device size is 0, " ++ "path unuseable", pp->dev); ++ pp->state = PATH_GHOST; ++ } + } else { + condlog(3, "%s: path inaccessible", pp->dev); + pp->chkrstate = pp->state = path_state; +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -551,7 +551,7 @@ int update_multipath (struct vectors *ve + + if (pp->state != PATH_DOWN) { + int oldstate = pp->state; +- condlog(2, "%s: mark as failed", pp->dev_t); ++ condlog(2, "%s: mark as failed", pp->dev); + mpp->stat_path_failures++; + pp->state = PATH_DOWN; + if (oldstate == PATH_UP || +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -538,15 +538,10 @@ ev_add_path (struct path * pp, struct ve + pp->mpp = mpp; + rescan: + if (mpp) { +- if ((!pp->size) || (mpp->size != pp->size)) { +- if (!pp->size) +- condlog(0, "%s: failed to add new path %s, " +- "device size is 0", +- mpp->alias, pp->dev); +- else +- condlog(0, "%s: failed to add new path %s, " +- "device size mismatch", +- mpp->alias, pp->dev); ++ if (pp->size && mpp->size != pp->size) { ++ condlog(0, "%s: failed to add new path %s, " ++ "device size mismatch", ++ mpp->alias, pp->dev); + int i = find_slot(vecs->pathvec, (void *)pp); + if (i != -1) + vector_del_slot(vecs->pathvec, i); +@@ -563,18 +558,7 @@ rescan: + verify_paths(mpp, vecs, NULL); + mpp->flush_on_last_del = FLUSH_UNDEF; + mpp->action = ACT_RELOAD; +- } +- else { +- if (!pp->size) { +- condlog(0, "%s: failed to create new map," +- " device size is 0 ", pp->dev); +- int i = find_slot(vecs->pathvec, (void *)pp); +- if (i != -1) +- vector_del_slot(vecs->pathvec, i); +- free_path(pp); +- return 1; +- } +- ++ } else { + if (!should_multipath(pp, vecs->pathvec)) { + orphan_path(pp); + return 0; diff --git a/SOURCES/0172-RHBZ-1350931-no-active-add.patch b/SOURCES/0172-RHBZ-1350931-no-active-add.patch new file mode 100644 index 0000000..4e79e32 --- /dev/null +++ b/SOURCES/0172-RHBZ-1350931-no-active-add.patch @@ -0,0 +1,37 @@ +--- + multipathd/main.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -530,9 +530,15 @@ ev_add_path (struct path * pp, struct ve + } + mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); + if (mpp && mpp->wait_for_udev) { +- mpp->wait_for_udev = 2; +- orphan_path(pp); +- return 0; ++ if (pathcount(mpp, PATH_UP) == 0 && ++ (pathcount(mpp, PATH_GHOST) == 0 || ++ pp->tpgs == TPGS_IMPLICIT)) ++ mpp->force_udev_reload = 1; ++ else { ++ mpp->wait_for_udev = 2; ++ orphan_path(pp); ++ return 0; ++ } + } + + pp->mpp = mpp; +@@ -551,7 +557,8 @@ rescan: + + condlog(4,"%s: adopting all paths for path %s", + mpp->alias, pp->dev); +- mpp->force_udev_reload = !pathcount(mpp, PATH_WILD); ++ if (pathcount(mpp, PATH_WILD) == 0) ++ mpp->force_udev_reload = 1; + if (adopt_paths(vecs->pathvec, mpp, 1)) + goto fail; /* leave path added to pathvec */ + diff --git a/SOURCES/0173-RH-update-man-page.patch b/SOURCES/0173-RH-update-man-page.patch new file mode 100644 index 0000000..80c6dbf --- /dev/null +++ b/SOURCES/0173-RH-update-man-page.patch @@ -0,0 +1,99 @@ +--- + multipath/multipath.conf.5 | 56 ++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 51 insertions(+), 5 deletions(-) + +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -240,18 +240,21 @@ Specify any device-mapper features to be + .I num list + where + .I num +-is the number of features in ++is the number, between 0 and 6, of features in + .I list. +-Possible values for the feature list are ++Possible values for the feature list are: + .RS + .TP 12 +-.B queue_if_no_path ++.I queue_if_no_path + Queue IO if no path is active; identical to the + .I no_path_retry + keyword. + .TP +-.B no_partitions +-Disable automatic partitions generation via kpartx. ++.I pg_init_retries ++Number of times to retry pg_init, it must be between 1 and 50. ++.TP ++.I pg_init_delay_msecs ++Number of msecs before pg_init retry, it must be between 0 and 60000. + .RE + .TP + .B path_checker +@@ -511,6 +514,45 @@ If set to + .I yes + , kpartx will not automatically create partitions on the device. The default is + .I no ++.TP ++.B ignore_new_boot_devs ++If set to ++.I yes ++, multipath will never attempt to create a multipath device whose wwid is not ++listed in /etc/multipath/wwids, while running in the initramfs. This keeps ++multipath from adding new devices during the initramfs portion of bootup. The ++default is ++.I no ++.TP ++.B retrigger_tries ++This sets how many times multipathd will reissue change uevents on block ++devices that are not blacklisted, but have no wwid set by udev. Multipath ++assumes that any devices that should not report a wwid are blacklisted. This ++means that if a non-blacklisted device has no wwid, it is likely that udev ++timed out while processing it. Multipathd will wait for a while, and then ++reissue a change uevent to give udev another chance to set the wwid. The ++default is ++.I 3 ++.TP ++.B retrigger_delay ++This sets how long multipathd should wait, after receiving a uevent for a ++non-blacklisted device without a wwid set by udev, before reissuing a ++change uevent. The goal of this delay is to give udev a chance to finish ++processing its current batch of uevents before sending more, to hopefully ++avoid it timing out. The default is ++.I 10 ++.TP ++.B new_bindings_in_boot ++If set to ++.I yes ++, multipath will allow new user_friendly_names bindings to be created while ++running in the initramfs. Otherwise, multipath will not create ++user_friendly_names bindings while running in the initramfs. Instead, it will ++use the WWID for the name of a device that was configured to use ++user_friendly_names. When multipathd is restarted later in boot on the ++regular filesystem, the device will be renamed to a user_friendly_name. The ++default is ++.I no + . + .SH "blacklist section" + The +@@ -603,6 +645,8 @@ section: + .TP + .B flush_on_last_del + .TP ++.B user_friendly_names ++.TP + .B no_path_retry + .TP + .B rr_min_io +@@ -697,6 +741,8 @@ section: + .TP + .B no_path_retry + .TP ++.B user_friendly_names ++.TP + .B rr_min_io + .TP + .B rr_min_io_rq diff --git a/SOURCES/0174-RHBZ-1362396-modprobe.patch b/SOURCES/0174-RHBZ-1362396-modprobe.patch new file mode 100644 index 0000000..509510c --- /dev/null +++ b/SOURCES/0174-RHBZ-1362396-modprobe.patch @@ -0,0 +1,16 @@ +--- + multipathd/multipathd.init.redhat | 1 + + 1 file changed, 1 insertion(+) + +Index: multipath-tools-130222/multipathd/multipathd.init.redhat +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.init.redhat ++++ multipath-tools-130222/multipathd/multipathd.init.redhat +@@ -67,6 +67,7 @@ popd > /dev/null + start() { + test -x $DAEMON || exit 5 + echo -n $"Starting $prog daemon: " ++ modprobe dm-multipath >/dev/null 2>&1 + daemon $DAEMON + RETVAL=$? + [ $RETVAL -eq 0 ] && touch $lockdir/$prog diff --git a/SOURCES/0175-RHBZ-1357382-ordering.patch b/SOURCES/0175-RHBZ-1357382-ordering.patch new file mode 100644 index 0000000..c778596 --- /dev/null +++ b/SOURCES/0175-RHBZ-1357382-ordering.patch @@ -0,0 +1,17 @@ +--- + multipathd/multipathd.service | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipathd/multipathd.service +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.service ++++ multipath-tools-130222/multipathd/multipathd.service +@@ -2,7 +2,7 @@ + Description=Device-Mapper Multipath Device Controller + Wants=blk-availability.service + Before=iscsi.service iscsid.service lvm2-activation-early.service +-After=syslog.target ++After=syslog.target systemd-udev-trigger.service + ConditionPathExists=/etc/multipath.conf + ConditionKernelCommandLine=!nompath + DefaultDependencies=no diff --git a/SOURCES/0176-RHBZ-1363830-fix-rename.patch b/SOURCES/0176-RHBZ-1363830-fix-rename.patch new file mode 100644 index 0000000..428b2f1 --- /dev/null +++ b/SOURCES/0176-RHBZ-1363830-fix-rename.patch @@ -0,0 +1,17 @@ +--- + libmultipath/devmapper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -1387,7 +1387,7 @@ dm_rename (const char * old, char * new, + { + int r = 0; + struct dm_task *dmt; +- uint32_t cookie; ++ uint32_t cookie = 0; + uint16_t udev_flags = ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | ((skip_kpartx == SKIP_KPARTX_ON)? MPATH_UDEV_NO_KPARTX_FLAG : 0); + + if (dm_rename_partmaps(old, new)) diff --git a/SOURCES/0177-libmultipath-correctly-initialize-pp-sg_id.patch b/SOURCES/0177-libmultipath-correctly-initialize-pp-sg_id.patch new file mode 100644 index 0000000..1c927be --- /dev/null +++ b/SOURCES/0177-libmultipath-correctly-initialize-pp-sg_id.patch @@ -0,0 +1,38 @@ +From e2b87038125c79089e0bd4c6fd905667c5108740 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Tue, 9 Aug 2016 13:36:04 -0500 +Subject: [PATCH 01/11] libmultipath: correctly initialize pp->sg_id + +For BZ 1348372 from upstream: + +commit b4d9ca8dc8bbfbd3782bf4cf2cb1a440685ccd07 +Author: Hannes Reinecke +Date: Wed Nov 11 13:38:57 2015 +0100 + + libmultipath: correctly initialize pp->sg_id + + The default SCSI protocol is 'SCSI_PROTOCOL_UNSPEC'; + '0' is SCSI_PROTOCOL_FCP. + + Signed-off-by: Hannes Reinecke + +Signed-off-by: Mike Christie +--- + libmultipath/structs.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libmultipath/structs.c b/libmultipath/structs.c +index 30d247d..26a6a3b 100644 +--- a/libmultipath/structs.c ++++ b/libmultipath/structs.c +@@ -94,6 +94,7 @@ alloc_path (void) + pp->sg_id.channel = -1; + pp->sg_id.scsi_id = -1; + pp->sg_id.lun = -1; ++ pp->sg_id.proto_id = SCSI_PROTOCOL_UNSPEC; + pp->fd = -1; + pp->priority = PRIO_UNDEF; + } +-- +1.8.3.1 + diff --git a/SOURCES/0178-libmultipath-add-rbd-discovery.patch b/SOURCES/0178-libmultipath-add-rbd-discovery.patch new file mode 100644 index 0000000..6930e46 --- /dev/null +++ b/SOURCES/0178-libmultipath-add-rbd-discovery.patch @@ -0,0 +1,219 @@ +From 2fc494b81157059e0be66022f6a2110f1ce179c3 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Tue, 9 Aug 2016 13:44:10 -0500 +Subject: [PATCH 02/11] libmultipath: add rbd discovery + +For BZ 1348372 from upstream commit: + +Commit 152f3f803ee922075e8b25027eb9dc5699f1aefa +Author: Mike Christie +Date: Mon Aug 8 07:01:47 2016 -0500 + + libmultipath: add rbd discovery + + rbd is a block device interface for Ceph. It does not support + any SCSI commands, so this patch adds bus detection and virtual + vendor/product pathinfo. + +-------- + +Porting notes: + +get_uid() chunk does not match upstream due to rhel not having +the get uid callout code and sysfs uid detection code. + +Signed-off-by: Mike Christie +--- + libmultipath/checkers.h | 1 + + libmultipath/discovery.c | 116 ++++++++++++++++++++++++++++++++++++++++------- + libmultipath/structs.h | 1 + + 3 files changed, 101 insertions(+), 17 deletions(-) + +diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h +index f6fe326..735bb25 100644 +--- a/libmultipath/checkers.h ++++ b/libmultipath/checkers.h +@@ -75,6 +75,7 @@ enum path_check_state { + #define EMC_CLARIION "emc_clariion" + #define READSECTOR0 "readsector0" + #define CCISS_TUR "cciss_tur" ++#define RBD "rbd" + + #define DEFAULT_CHECKER DIRECTIO + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 7a8282b..1b9f390 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -781,6 +781,21 @@ scsi_sysfs_pathinfo (struct path * pp) + } + + static int ++rbd_sysfs_pathinfo (struct path * pp) ++{ ++ sprintf(pp->vendor_id, "Ceph"); ++ sprintf(pp->product_id, "RBD"); ++ ++ condlog(3, "%s: vendor = %s product = %s", pp->dev, pp->vendor_id, ++ pp->product_id); ++ /* ++ * set the hwe configlet pointer ++ */ ++ pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, NULL); ++ return 0; ++} ++ ++static int + ccw_sysfs_pathinfo (struct path * pp) + { + struct udev_device *parent; +@@ -974,6 +989,8 @@ sysfs_pathinfo(struct path * pp) + pp->bus = SYSFS_BUS_CCW; + if (!strncmp(pp->dev,"sd", 2)) + pp->bus = SYSFS_BUS_SCSI; ++ if (!strncmp(pp->dev,"rbd", 3)) ++ pp->bus = SYSFS_BUS_RBD; + + if (pp->bus == SYSFS_BUS_UNDEF) + return 0; +@@ -986,6 +1003,9 @@ sysfs_pathinfo(struct path * pp) + } else if (pp->bus == SYSFS_BUS_CCISS) { + if (cciss_sysfs_pathinfo(pp)) + return 1; ++ } else if (pp->bus == SYSFS_BUS_RBD) { ++ if (rbd_sysfs_pathinfo(pp)) ++ return 1; + } + return 0; + } +@@ -1087,10 +1107,60 @@ get_prio (struct path * pp) + } + + static int ++get_rbd_uid(struct path * pp) ++{ ++ struct udev_device *rbd_bus_dev; ++ int ret, rbd_bus_id; ++ const char *pool, *image, *snap; ++ char sysfs_path[PATH_SIZE]; ++ uint64_t snap_id, max_snap_id = -3; ++ ++ ret = sscanf(pp->dev, "rbd%d", &rbd_bus_id); ++ if (ret != 1) ++ return -EINVAL; ++ ++ snprintf(sysfs_path, sizeof(sysfs_path), "/sys/bus/rbd/devices/%d", ++ rbd_bus_id); ++ rbd_bus_dev = udev_device_new_from_syspath(conf->udev, sysfs_path); ++ if (!rbd_bus_dev) ++ return -ENODEV; ++ ++ ret = -EINVAL; ++ pool = udev_device_get_sysattr_value(rbd_bus_dev, "pool_id"); ++ if (!pool) ++ goto free_dev; ++ ++ image = udev_device_get_sysattr_value(rbd_bus_dev, "image_id"); ++ if (!image) ++ goto free_dev; ++ ++ snap = udev_device_get_sysattr_value(rbd_bus_dev, "snap_id"); ++ if (!snap) ++ goto free_dev; ++ snap_id = strtoull(snap, NULL, 19); ++ if (snap_id >= max_snap_id) ++ ret = snprintf(pp->wwid, WWID_SIZE, "%s-%s", pool, image); ++ else ++ ret = snprintf(pp->wwid, WWID_SIZE, "%s-%s-%s", pool, ++ image, snap); ++ if (ret < WWID_SIZE) { ++ ret = 0; ++ } else { ++ condlog(0, "%s: wwid overflow", pp->dev); ++ ret = -EOVERFLOW; ++ } ++ ++free_dev: ++ udev_device_unref(rbd_bus_dev); ++ return ret; ++} ++ ++static int + get_uid (struct path * pp) + { + char *c; + const char *value; ++ int ret; + + if (!pp->uid_attribute) + select_getuid(pp); +@@ -1101,25 +1171,37 @@ 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->cmd == CMD_VALID_PATH) +- value = getenv(pp->uid_attribute); +- if (value && strlen(value)) { +- size_t len = WWID_SIZE; +- +- if (strlen(value) + 1 > WWID_SIZE) { +- condlog(0, "%s: wwid overflow", pp->dev); +- } else { +- len = strlen(value); ++ if (pp->bus == SYSFS_BUS_RBD) { ++ ret = get_rbd_uid(pp); ++ if (ret) { ++ condlog(1, "%s: failed to get sysfs uid: %s", ++ pp->dev, strerror(-ret)); ++ pp->missing_udev_info = INFO_MISSING; ++ pp->tick = conf->retrigger_delay; + } +- strncpy(pp->wwid, value, len); +- pp->missing_udev_info = INFO_OK; +- pp->tick = 0; + } else { +- condlog(3, "%s: no %s attribute", pp->dev, +- pp->uid_attribute); +- pp->missing_udev_info = INFO_MISSING; +- pp->tick = conf->retrigger_delay; ++ value = udev_device_get_property_value(pp->udev, ++ pp->uid_attribute); ++ if ((!value || strlen(value) == 0) && ++ conf->cmd == CMD_VALID_PATH) ++ value = getenv(pp->uid_attribute); ++ if (value && strlen(value)) { ++ size_t len = WWID_SIZE; ++ ++ if (strlen(value) + 1 > WWID_SIZE) { ++ condlog(0, "%s: wwid overflow", pp->dev); ++ } else { ++ len = strlen(value); ++ } ++ strncpy(pp->wwid, value, len); ++ pp->missing_udev_info = INFO_OK; ++ pp->tick = 0; ++ } else { ++ condlog(3, "%s: no %s attribute", pp->dev, ++ pp->uid_attribute); ++ pp->missing_udev_info = INFO_MISSING; ++ pp->tick = conf->retrigger_delay; ++ } + } + + /* Strip any trailing blanks */ +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index b5b4567..e566462 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -52,6 +52,7 @@ enum sysfs_buses { + SYSFS_BUS_IDE, + SYSFS_BUS_CCW, + SYSFS_BUS_CCISS, ++ SYSFS_BUS_RBD, + }; + + enum pathstates { +-- +1.8.3.1 + diff --git a/SOURCES/0179-multipath-tools-add-checker-callout-to-repair-path.patch b/SOURCES/0179-multipath-tools-add-checker-callout-to-repair-path.patch new file mode 100644 index 0000000..8b48f7d --- /dev/null +++ b/SOURCES/0179-multipath-tools-add-checker-callout-to-repair-path.patch @@ -0,0 +1,250 @@ +From 1073621a7a63ca4e9a00baedd8edc51e5381eb95 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Tue, 9 Aug 2016 13:46:11 -0500 +Subject: [PATCH 03/11] multipath-tools: add checker callout to repair path + +For BZ 1348372 from upstream commit: + +commit 015f87b16a7797a17afd514aec46e65c2a1a2f73 +Author: Mike Christie +Date: Mon Aug 8 07:01:48 2016 -0500 + + multipath-tools: add checker callout to repair path + + This patch adds a callback which can be used to repair a path + if check() has determined it is in the PATH_DOWN state. + + The next patch that adds rbd checker support which will use this to + handle the case where a rbd device is blacklisted. + +-------- + +Porting notes: +checkerloop difference due to different path tracking. + +Signed-off-by: Mike Christie +--- + libmultipath/checkers.c | 23 +++++++++++++++++++++++ + libmultipath/checkers.h | 4 ++++ + libmultipath/checkers/cciss_tur.c | 5 +++++ + libmultipath/checkers/directio.c | 5 +++++ + libmultipath/checkers/emc_clariion.c | 5 +++++ + libmultipath/checkers/hp_sw.c | 5 +++++ + libmultipath/checkers/rdac.c | 5 +++++ + libmultipath/checkers/readsector0.c | 5 +++++ + libmultipath/checkers/tur.c | 5 +++++ + multipathd/main.c | 9 +++++++++ + 10 files changed, 71 insertions(+) + +diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c +index 7f9db2d..fa7d8b7 100644 +--- a/libmultipath/checkers.c ++++ b/libmultipath/checkers.c +@@ -137,6 +137,14 @@ struct checker * add_checker (char * name) + if (!c->free) + goto out; + ++ c->repair = (void (*)(struct checker *)) dlsym(c->handle, ++ "libcheck_repair"); ++ errstr = dlerror(); ++ if (errstr != NULL) ++ condlog(0, "A dynamic linking error occurred: (%s)", errstr); ++ if (!c->repair) ++ goto out; ++ + c->fd = 0; + c->sync = 1; + list_add(&c->node, &checkers); +@@ -202,6 +210,20 @@ void checker_put (struct checker * dst) + free_checker(src); + } + ++void checker_repair (struct checker * c) ++{ ++ if (!c) ++ return; ++ ++ c->message[0] = '\0'; ++ if (c->disable) { ++ MSG(c, "checker disabled"); ++ return; ++ } ++ ++ c->repair(c); ++} ++ + int checker_check (struct checker * c) + { + int r; +@@ -266,6 +288,7 @@ void checker_get (struct checker * dst, char * name) + dst->sync = src->sync; + strncpy(dst->name, src->name, CHECKER_NAME_LEN); + strncpy(dst->message, src->message, CHECKER_MSG_LEN); ++ dst->repair = src->repair; + dst->check = src->check; + dst->init = src->init; + dst->free = src->free; +diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h +index 735bb25..ad3b9e4 100644 +--- a/libmultipath/checkers.h ++++ b/libmultipath/checkers.h +@@ -106,6 +106,9 @@ struct checker { + multipath-wide. Use MALLOC if + you want to stuff data in. */ + int (*check)(struct checker *); ++ void (*repair)(struct checker *); /* called if check returns ++ PATH_DOWN to bring path into ++ usable state */ + int (*init)(struct checker *); /* to allocate the context */ + void (*free)(struct checker *); /* to free the context */ + }; +@@ -125,6 +128,7 @@ void checker_set_async (struct checker *); + void checker_set_fd (struct checker *, int); + void checker_enable (struct checker *); + void checker_disable (struct checker *); ++void checker_repair (struct checker *); + int checker_check (struct checker *); + int checker_selected (struct checker *); + char * checker_name (struct checker *); +diff --git a/libmultipath/checkers/cciss_tur.c b/libmultipath/checkers/cciss_tur.c +index 4c26901..7e4eb81 100644 +--- a/libmultipath/checkers/cciss_tur.c ++++ b/libmultipath/checkers/cciss_tur.c +@@ -63,6 +63,11 @@ void libcheck_free (struct checker * c) + return; + } + ++void libcheck_repair (struct checker * c) ++{ ++ return; ++} ++ + extern int + libcheck_check (struct checker * c) + { +diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c +index 46fe6a7..1a997ed 100644 +--- a/libmultipath/checkers/directio.c ++++ b/libmultipath/checkers/directio.c +@@ -116,6 +116,11 @@ void libcheck_free (struct checker * c) + free(ct); + } + ++void libcheck_repair (struct checker * c) ++{ ++ return; ++} ++ + static int + check_state(int fd, struct directio_context *ct, int sync, int timeout_secs) + { +diff --git a/libmultipath/checkers/emc_clariion.c b/libmultipath/checkers/emc_clariion.c +index b42d267..43b5025 100644 +--- a/libmultipath/checkers/emc_clariion.c ++++ b/libmultipath/checkers/emc_clariion.c +@@ -90,6 +90,11 @@ void libcheck_free (struct checker * c) + free(c->context); + } + ++void libcheck_repair (struct checker * c) ++{ ++ return; ++} ++ + int libcheck_check (struct checker * c) + { + unsigned char sense_buffer[128] = { 0, }; +diff --git a/libmultipath/checkers/hp_sw.c b/libmultipath/checkers/hp_sw.c +index b50ac0c..857ac5e 100644 +--- a/libmultipath/checkers/hp_sw.c ++++ b/libmultipath/checkers/hp_sw.c +@@ -44,6 +44,11 @@ void libcheck_free (struct checker * c) + return; + } + ++void libcheck_repair (struct checker * c) ++{ ++ return; ++} ++ + static int + do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op, + void *resp, int mx_resp_len, int noisy, unsigned int timeout) +diff --git a/libmultipath/checkers/rdac.c b/libmultipath/checkers/rdac.c +index f0e0af3..5469e61 100644 +--- a/libmultipath/checkers/rdac.c ++++ b/libmultipath/checkers/rdac.c +@@ -139,6 +139,11 @@ void libcheck_free (struct checker * c) + return; + } + ++void libcheck_repair (struct checker * c) ++{ ++ return; ++} ++ + static int + do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len, + unsigned int timeout) +diff --git a/libmultipath/checkers/readsector0.c b/libmultipath/checkers/readsector0.c +index 0550fb6..b3ed1f3 100644 +--- a/libmultipath/checkers/readsector0.c ++++ b/libmultipath/checkers/readsector0.c +@@ -23,6 +23,11 @@ void libcheck_free (struct checker * c) + return; + } + ++void libcheck_repair (struct checker * c) ++{ ++ return; ++} ++ + int libcheck_check (struct checker * c) + { + unsigned char buf[4096]; +diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c +index 1e5b039..91f1458 100644 +--- a/libmultipath/checkers/tur.c ++++ b/libmultipath/checkers/tur.c +@@ -187,6 +187,11 @@ void libcheck_free (struct checker * c) + return; + } + ++void libcheck_repair (struct checker * c) ++{ ++ return; ++} ++ + #define TUR_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args); + + int +diff --git a/multipathd/main.c b/multipathd/main.c +index 8808c88..d26fd22 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1455,6 +1455,14 @@ check_path (struct vectors * vecs, struct path * pp) + } + } + ++void repair_path(struct vectors * vecs, struct path * pp) ++{ ++ if (pp->state != PATH_DOWN) ++ return; ++ ++ checker_repair(&pp->checker); ++} ++ + static void * + checkerloop (void *ap) + { +@@ -1483,6 +1491,7 @@ checkerloop (void *ap) + if (vecs->pathvec) { + vector_foreach_slot (vecs->pathvec, pp, i) { + check_path(vecs, pp); ++ repair_path(vecs, pp); + } + } + if (vecs->mpvec) { +-- +1.8.3.1 + diff --git a/SOURCES/0180-multipath-tools-Add-rbd-checker.patch b/SOURCES/0180-multipath-tools-Add-rbd-checker.patch new file mode 100644 index 0000000..cf8a752 --- /dev/null +++ b/SOURCES/0180-multipath-tools-Add-rbd-checker.patch @@ -0,0 +1,746 @@ +From e28c340ed961409700d46a1cb9a820a8b7a4d016 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Thu, 11 Aug 2016 02:12:12 -0500 +Subject: [PATCH 04/11] multipath-tools: Add rbd checker. + +For BZ 1348372 from upstream commit: + +commit d1cad5649b6fcf9027d43ca0405c900080133e32 +Author: Mike Christie +Date: Mon Aug 8 07:01:49 2016 -0500 + + multipath-tools: Add rbd checker. + + This checker currently only handles the case where a path is failed + due to it being blacklisted by the ceph cluster. The specific use + case for me is when LIO exports rbd images through multiple LIO + instances. + + The problem it handles is when rbd instance1 has the exclusive lock, + but becomes unreachable another host in the cluster will take over + and blacklist the instance1. This prevents it from sending stale IO + and corrupting data. + + Later, when the host is reachable, we will want to failback to it. + To this, the checker will detect we were blacklisted, unmap the old + image which will make sure old IO is failed, and then remap the +image + and unblacklist the host. multipathd will then handle this like a + path being removed and re-added. + +-------- + +Porting notes: +Added rbd to multipath.conf.annotated. + +Signed-off-by: Mike Christie +--- + libmultipath/checkers/Makefile | 7 + libmultipath/checkers/rbd.c | 639 +++++++++++++++++++++++++++++++++++++++++ + multipath.conf.annotated | 4 + multipath/multipath.conf.5 | 3 + 4 files changed, 651 insertions(+), 2 deletions(-) + create mode 100644 libmultipath/checkers/rbd.c + +Index: multipath-tools-130222/libmultipath/checkers/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/Makefile ++++ multipath-tools-130222/libmultipath/checkers/Makefile +@@ -14,10 +14,17 @@ LIBS= \ + libcheckhp_sw.so \ + libcheckrdac.so + ++ifeq ($(shell test -r /usr/include/rados/librados.h && echo 1),1) ++LIBS += libcheckrbd.so ++endif ++ + CFLAGS += -fPIC -I.. + + all: $(LIBS) + ++libcheckrbd.so: rbd.o ++ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -lrados -ludev ++ + libcheckdirectio.so: libsg.o directio.o + $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -laio + +Index: multipath-tools-130222/libmultipath/checkers/rbd.c +=================================================================== +--- /dev/null ++++ multipath-tools-130222/libmultipath/checkers/rbd.c +@@ -0,0 +1,639 @@ ++/* ++ * Copyright (c) 2016 Red Hat ++ * Copyright (c) 2004 Christophe Varoqui ++ * ++ * Code based off of tur.c and ceph's krbd.cc ++ */ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rados/librados.h" ++ ++#include "structs.h" ++#include "checkers.h" ++ ++#include "../libmultipath/debug.h" ++#include "../libmultipath/uevent.h" ++ ++struct rbd_checker_context; ++typedef int (thread_fn)(struct rbd_checker_context *ct, char *msg); ++ ++#define RBD_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args); ++ ++struct rbd_checker_context { ++ int rbd_bus_id; ++ char *client_addr; ++ char *config_info; ++ char *snap; ++ char *pool; ++ char *image; ++ char *username; ++ int remapped; ++ int blacklisted; ++ ++ rados_t cluster; ++ ++ int state; ++ int running; ++ time_t time; ++ thread_fn *fn; ++ pthread_t thread; ++ pthread_mutex_t lock; ++ pthread_cond_t active; ++ pthread_spinlock_t hldr_lock; ++ int holders; ++ char message[CHECKER_MSG_LEN]; ++}; ++ ++int libcheck_init(struct checker * c) ++{ ++ struct rbd_checker_context *ct; ++ struct udev_device *block_dev; ++ struct udev_device *bus_dev; ++ struct udev *udev; ++ struct stat sb; ++ const char *block_name, *addr, *config_info; ++ const char *image, *pool, *snap, *username; ++ char sysfs_path[PATH_SIZE]; ++ int ret; ++ ++ ct = malloc(sizeof(struct rbd_checker_context)); ++ if (!ct) ++ return 1; ++ memset(ct, 0, sizeof(struct rbd_checker_context)); ++ ct->holders = 1; ++ pthread_cond_init(&ct->active, NULL); ++ pthread_mutex_init(&ct->lock, NULL); ++ pthread_spin_init(&ct->hldr_lock, PTHREAD_PROCESS_PRIVATE); ++ c->context = ct; ++ ++ /* ++ * The rbd block layer sysfs device is not linked to the rbd bus ++ * device that we interact with, so figure that out now. ++ */ ++ if (fstat(c->fd, &sb) != 0) ++ goto free_ct; ++ ++ udev = udev_new(); ++ if (!udev) ++ goto free_ct; ++ ++ block_dev = udev_device_new_from_devnum(udev, 'b', sb.st_rdev); ++ if (!block_dev) ++ goto free_udev; ++ ++ block_name = udev_device_get_sysname(block_dev); ++ ret = sscanf(block_name, "rbd%d", &ct->rbd_bus_id); ++ ++ udev_device_unref(block_dev); ++ if (ret != 1) ++ goto free_udev; ++ ++ snprintf(sysfs_path, sizeof(sysfs_path), "/sys/bus/rbd/devices/%d", ++ ct->rbd_bus_id); ++ bus_dev = udev_device_new_from_syspath(udev, sysfs_path); ++ if (!bus_dev) ++ goto free_udev; ++ ++ addr = udev_device_get_sysattr_value(bus_dev, "client_addr"); ++ if (!addr) { ++ condlog(0, "Could not find client_addr in rbd sysfs. Try " ++ "updating kernel"); ++ goto free_dev; ++ } ++ ++ ct->client_addr = strdup(addr); ++ if (!ct->client_addr) ++ goto free_dev; ++ ++ config_info = udev_device_get_sysattr_value(bus_dev, "config_info"); ++ if (!config_info) ++ goto free_addr; ++ ++ ct->config_info = strdup(config_info); ++ if (!ct->config_info) ++ goto free_addr; ++ ++ username = strstr(config_info, "name="); ++ if (username) { ++ char *end; ++ int len; ++ ++ username += 5; ++ end = strchr(username, ','); ++ if (!end) ++ goto free_info; ++ len = end - username; ++ ++ ct->username = malloc(len + 1); ++ if (!ct->username) ++ goto free_info; ++ strncpy(ct->username, username, len); ++ ct->username[len] = '\0'; ++ } ++ ++ image = udev_device_get_sysattr_value(bus_dev, "name"); ++ if (!image) ++ goto free_username; ++ ++ ct->image = strdup(image); ++ if (!ct->image) ++ goto free_info; ++ ++ pool = udev_device_get_sysattr_value(bus_dev, "pool"); ++ if (!pool) ++ goto free_image; ++ ++ ct->pool = strdup(pool); ++ if (!ct->pool) ++ goto free_image; ++ ++ snap = udev_device_get_sysattr_value(bus_dev, "current_snap"); ++ if (!snap) ++ goto free_pool; ++ ++ if (strcmp("-", snap)) { ++ ct->snap = strdup(snap); ++ if (!ct->snap) ++ goto free_pool; ++ } ++ ++ if (rados_create(&ct->cluster, NULL) < 0) { ++ condlog(0, "Could not create rados cluster"); ++ goto free_snap; ++ } ++ ++ if (rados_conf_read_file(ct->cluster, NULL) < 0) { ++ condlog(0, "Could not read rados conf"); ++ goto shutdown_rados; ++ } ++ ++ ret = rados_connect(ct->cluster); ++ if (ret < 0) { ++ condlog(0, "Could not connect to rados cluster"); ++ goto shutdown_rados; ++ } ++ ++ udev_device_unref(bus_dev); ++ udev_unref(udev); ++ ++ condlog(3, "rbd%d checker init %s %s/%s@%s %s", ct->rbd_bus_id, ++ ct->client_addr, ct->pool, ct->image, ct->snap ? ct->snap : "-", ++ ct->username ? ct->username : "none"); ++ return 0; ++ ++shutdown_rados: ++ rados_shutdown(ct->cluster); ++free_snap: ++ if (ct->snap) ++ free(ct->snap); ++free_pool: ++ free(ct->pool); ++free_image: ++ free(ct->image); ++free_username: ++ if (ct->username) ++ free(ct->username); ++free_info: ++ free(ct->config_info); ++free_addr: ++ free(ct->client_addr); ++free_dev: ++ udev_device_unref(bus_dev); ++free_udev: ++ udev_unref(udev); ++free_ct: ++ free(ct); ++ return 1; ++} ++ ++void cleanup_context(struct rbd_checker_context *ct) ++{ ++ pthread_mutex_destroy(&ct->lock); ++ pthread_cond_destroy(&ct->active); ++ pthread_spin_destroy(&ct->hldr_lock); ++ ++ rados_shutdown(ct->cluster); ++ ++ if (ct->username) ++ free(ct->username); ++ if (ct->snap) ++ free(ct->snap); ++ free(ct->pool); ++ free(ct->image); ++ free(ct->config_info); ++ free(ct->client_addr); ++ free(ct); ++} ++ ++void libcheck_free(struct checker * c) ++{ ++ if (c->context) { ++ struct rbd_checker_context *ct = c->context; ++ int holders; ++ pthread_t thread; ++ ++ pthread_spin_lock(&ct->hldr_lock); ++ ct->holders--; ++ holders = ct->holders; ++ thread = ct->thread; ++ pthread_spin_unlock(&ct->hldr_lock); ++ if (holders) ++ pthread_cancel(thread); ++ else ++ cleanup_context(ct); ++ c->context = NULL; ++ } ++} ++ ++static int rbd_is_blacklisted(struct rbd_checker_context *ct, char *msg) ++{ ++ char *addr_tok, *start, *save; ++ char *cmd[2]; ++ char *blklist, *stat; ++ size_t blklist_len, stat_len; ++ int ret; ++ char *end; ++ ++ cmd[0] = "{\"prefix\": \"osd blacklist ls\"}"; ++ cmd[1] = NULL; ++ ++ ret = rados_mon_command(ct->cluster, (const char **)cmd, 1, "", 0, ++ &blklist, &blklist_len, &stat, &stat_len); ++ if (ret < 0) { ++ RBD_MSG(msg, "rbd checker failed: mon command failed %d", ++ ret); ++ return ret; ++ } ++ ++ if (!blklist || !blklist_len) ++ goto free_bufs; ++ ++ /* ++ * parse list of addrs with the format ++ * ipv4:port/nonce date time\n ++ * or ++ * [ipv6]:port/nonce date time\n ++ */ ++ ret = 0; ++ for (start = blklist; ; start = NULL) { ++ addr_tok = strtok_r(start, "\n", &save); ++ if (!addr_tok || !strlen(addr_tok)) ++ break; ++ ++ end = strchr(addr_tok, ' '); ++ if (!end) { ++ RBD_MSG(msg, "rbd%d checker failed: invalid blacklist %s", ++ ct->rbd_bus_id, addr_tok); ++ break; ++ } ++ *end = '\0'; ++ ++ if (!strcmp(addr_tok, ct->client_addr)) { ++ ct->blacklisted = 1; ++ RBD_MSG(msg, "rbd%d checker: %s is blacklisted", ++ ct->rbd_bus_id, ct->client_addr); ++ ret = 1; ++ break; ++ } ++ } ++ ++free_bufs: ++ rados_buffer_free(blklist); ++ rados_buffer_free(stat); ++ return ret; ++} ++ ++int rbd_check(struct rbd_checker_context *ct, char *msg) ++{ ++ if (ct->blacklisted || rbd_is_blacklisted(ct, msg) == 1) ++ return PATH_DOWN; ++ ++ RBD_MSG(msg, "rbd checker reports path is up"); ++ /* ++ * Path may have issues, but the ceph cluster is at least ++ * accepting IO, so we can attempt to do IO. ++ * ++ * TODO: in future versions, we can run other tests to ++ * verify OSDs and networks. ++ */ ++ return PATH_UP; ++} ++ ++int safe_write(int fd, const void *buf, size_t count) ++{ ++ while (count > 0) { ++ ssize_t r = write(fd, buf, count); ++ if (r < 0) { ++ if (errno == EINTR) ++ continue; ++ return -errno; ++ } ++ count -= r; ++ buf = (char *)buf + r; ++ } ++ return 0; ++} ++ ++static int sysfs_write_rbd_bus(const char *which, const char *buf, ++ size_t buf_len) ++{ ++ char sysfs_path[PATH_SIZE]; ++ int fd; ++ int r; ++ ++ /* we require newer kernels so single_major should alwayws be there */ ++ snprintf(sysfs_path, sizeof(sysfs_path), ++ "/sys/bus/rbd/%s_single_major", which); ++ fd = open(sysfs_path, O_WRONLY); ++ if (fd < 0) ++ return -errno; ++ ++ r = safe_write(fd, buf, buf_len); ++ close(fd); ++ return r; ++} ++ ++static int rbd_remap(struct rbd_checker_context *ct) ++{ ++ char *argv[11]; ++ pid_t pid; ++ int ret = 0, i = 0; ++ int status; ++ ++ pid = fork(); ++ switch (pid) { ++ case 0: ++ argv[i++] = "rbd"; ++ argv[i++] = "map"; ++ argv[i++] = "-o noshare"; ++ if (ct->username) { ++ argv[i++] = "--id"; ++ argv[i++] = ct->username; ++ } ++ argv[i++] = "--pool"; ++ argv[i++] = ct->pool; ++ if (ct->snap) { ++ argv[i++] = "--snap"; ++ argv[i++] = ct->snap; ++ } ++ argv[i++] = ct->image; ++ argv[i] = NULL; ++ ++ ret = execvp(argv[0], argv); ++ condlog(0, "Error executing rbd: %s", strerror(errno)); ++ exit(-1); ++ case -1: ++ condlog(0, "fork failed: %s", strerror(errno)); ++ return -1; ++ default: ++ ret = -1; ++ wait(&status); ++ if (WIFEXITED(status)) { ++ status = WEXITSTATUS(status); ++ if (status == 0) ++ ret = 0; ++ else ++ condlog(0, "rbd failed with %d", status); ++ } ++ } ++ ++ return ret; ++} ++ ++static int sysfs_write_rbd_remove(const char *buf, int buf_len) ++{ ++ return sysfs_write_rbd_bus("remove", buf, buf_len); ++} ++ ++static int rbd_rm_blacklist(struct rbd_checker_context *ct) ++{ ++ char *cmd[2]; ++ char *stat, *cmd_str; ++ size_t stat_len; ++ int ret; ++ ++ ret = asprintf(&cmd_str, "{\"prefix\": \"osd blacklist\", \"blacklistop\": \"rm\", \"addr\": \"%s\"}", ++ ct->client_addr); ++ if (ret == -1) ++ return -ENOMEM; ++ ++ cmd[0] = cmd_str; ++ cmd[1] = NULL; ++ ++ ret = rados_mon_command(ct->cluster, (const char **)cmd, 1, "", 0, ++ NULL, 0, &stat, &stat_len); ++ if (ret < 0) { ++ condlog(1, "rbd%d repair failed to remove blacklist for %s %d", ++ ct->rbd_bus_id, ct->client_addr, ret); ++ goto free_cmd; ++ } ++ ++ condlog(1, "rbd%d repair rm blacklist for %s", ++ ct->rbd_bus_id, ct->client_addr); ++ free(stat); ++free_cmd: ++ free(cmd_str); ++ return ret; ++} ++ ++static int rbd_repair(struct rbd_checker_context *ct, char *msg) ++{ ++ char del[17]; ++ int ret; ++ ++ if (!ct->blacklisted) ++ return PATH_UP; ++ ++ if (!ct->remapped) { ++ ret = rbd_remap(ct); ++ if (ret) { ++ RBD_MSG(msg, "rbd%d repair failed to remap. Err %d", ++ ct->rbd_bus_id, ret); ++ return PATH_DOWN; ++ } ++ } ++ ct->remapped = 1; ++ ++ snprintf(del, sizeof(del), "%d force", ct->rbd_bus_id); ++ ret = sysfs_write_rbd_remove(del, strlen(del) + 1); ++ if (ret) { ++ RBD_MSG(msg, "rbd%d repair failed to clean up. Err %d", ++ ct->rbd_bus_id, ret); ++ return PATH_DOWN; ++ } ++ ++ ret = rbd_rm_blacklist(ct); ++ if (ret) { ++ RBD_MSG(msg, "rbd%d repair could not remove blacklist entry. Err %d", ++ ct->rbd_bus_id, ret); ++ return PATH_DOWN; ++ } ++ ++ ct->remapped = 0; ++ ct->blacklisted = 0; ++ ++ RBD_MSG(msg, "rbd%d has been repaired", ct->rbd_bus_id); ++ return PATH_UP; ++} ++ ++#define rbd_thread_cleanup_push(ct) pthread_cleanup_push(cleanup_func, ct) ++#define rbd_thread_cleanup_pop(ct) pthread_cleanup_pop(1) ++ ++void cleanup_func(void *data) ++{ ++ int holders; ++ struct rbd_checker_context *ct = data; ++ pthread_spin_lock(&ct->hldr_lock); ++ ct->holders--; ++ holders = ct->holders; ++ ct->thread = 0; ++ pthread_spin_unlock(&ct->hldr_lock); ++ if (!holders) ++ cleanup_context(ct); ++} ++ ++void *rbd_thread(void *ctx) ++{ ++ struct rbd_checker_context *ct = ctx; ++ int state; ++ ++ condlog(3, "rbd%d thread starting up", ct->rbd_bus_id); ++ ++ ct->message[0] = '\0'; ++ /* This thread can be canceled, so setup clean up */ ++ rbd_thread_cleanup_push(ct) ++ ++ /* checker start up */ ++ pthread_mutex_lock(&ct->lock); ++ ct->state = PATH_PENDING; ++ pthread_mutex_unlock(&ct->lock); ++ ++ state = ct->fn(ct, ct->message); ++ ++ /* checker done */ ++ pthread_mutex_lock(&ct->lock); ++ ct->state = state; ++ pthread_mutex_unlock(&ct->lock); ++ pthread_cond_signal(&ct->active); ++ ++ condlog(3, "rbd%d thead finished, state %s", ct->rbd_bus_id, ++ checker_state_name(state)); ++ rbd_thread_cleanup_pop(ct); ++ return ((void *)0); ++} ++ ++static void rbd_timeout(struct timespec *tsp) ++{ ++ struct timeval now; ++ ++ gettimeofday(&now, NULL); ++ tsp->tv_sec = now.tv_sec; ++ tsp->tv_nsec = now.tv_usec * 1000; ++ tsp->tv_nsec += 1000000; /* 1 millisecond */ ++} ++ ++static int rbd_exec_fn(struct checker *c, thread_fn *fn) ++{ ++ struct rbd_checker_context *ct = c->context; ++ struct timespec tsp; ++ pthread_attr_t attr; ++ int rbd_status, r; ++ ++ if (c->sync) ++ return rbd_check(ct, c->message); ++ /* ++ * Async mode ++ */ ++ r = pthread_mutex_lock(&ct->lock); ++ if (r != 0) { ++ condlog(2, "rbd%d mutex lock failed with %d", ct->rbd_bus_id, ++ r); ++ MSG(c, "rbd%d thread failed to initialize", ct->rbd_bus_id); ++ return PATH_WILD; ++ } ++ ++ if (ct->running) { ++ /* Check if checker is still running */ ++ if (ct->thread) { ++ condlog(3, "rbd%d thread not finished", ct->rbd_bus_id); ++ rbd_status = PATH_PENDING; ++ } else { ++ /* checker done */ ++ ct->running = 0; ++ rbd_status = ct->state; ++ strncpy(c->message, ct->message, CHECKER_MSG_LEN); ++ c->message[CHECKER_MSG_LEN - 1] = '\0'; ++ } ++ pthread_mutex_unlock(&ct->lock); ++ } else { ++ /* Start new checker */ ++ ct->state = PATH_UNCHECKED; ++ ct->fn = fn; ++ pthread_spin_lock(&ct->hldr_lock); ++ ct->holders++; ++ pthread_spin_unlock(&ct->hldr_lock); ++ setup_thread_attr(&attr, 32 * 1024, 1); ++ r = pthread_create(&ct->thread, &attr, rbd_thread, ct); ++ if (r) { ++ pthread_mutex_unlock(&ct->lock); ++ ct->thread = 0; ++ ct->holders--; ++ condlog(3, "rbd%d failed to start rbd thread, using sync mode", ++ ct->rbd_bus_id); ++ return fn(ct, c->message); ++ } ++ pthread_attr_destroy(&attr); ++ rbd_timeout(&tsp); ++ r = pthread_cond_timedwait(&ct->active, &ct->lock, &tsp); ++ rbd_status = ct->state; ++ strncpy(c->message, ct->message,CHECKER_MSG_LEN); ++ c->message[CHECKER_MSG_LEN -1] = '\0'; ++ pthread_mutex_unlock(&ct->lock); ++ ++ if (ct->thread && ++ (rbd_status == PATH_PENDING || rbd_status == PATH_UNCHECKED)) { ++ condlog(3, "rbd%d thread still running", ++ ct->rbd_bus_id); ++ ct->running = 1; ++ rbd_status = PATH_PENDING; ++ } ++ } ++ ++ return rbd_status; ++} ++ ++void libcheck_repair(struct checker * c) ++{ ++ struct rbd_checker_context *ct = c->context; ++ ++ if (!ct || !ct->blacklisted) ++ return; ++ rbd_exec_fn(c, rbd_repair); ++} ++ ++int libcheck_check(struct checker * c) ++{ ++ struct rbd_checker_context *ct = c->context; ++ ++ if (!ct) ++ return PATH_UNCHECKED; ++ ++ if (ct->blacklisted) ++ return PATH_DOWN; ++ ++ return rbd_exec_fn(c, rbd_check); ++} +Index: multipath-tools-130222/multipath.conf.annotated +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.annotated ++++ multipath-tools-130222/multipath.conf.annotated +@@ -97,7 +97,7 @@ + # # scope : multipath & multipathd + # # desc : the default method used to determine the paths' state + # # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac| +-# cciss_tur|hp_tur ++# cciss_tur|hp_tur|rbd + # # default : directio + # # + # path_checker directio +@@ -493,7 +493,7 @@ + # # scope : multipathd & multipathd + # # desc : path checking algorithm to use to check path state + # # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac| +-# # cciss_tur|hp_tur ++# # cciss_tur|hp_tur|rbd + # # + # path_checker directio + # +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -284,6 +284,9 @@ Check the path state for LSI/Engenio/Net + .B directio + Read the first sector with direct I/O. + .TP ++.B rbd ++Check if the path is in the Ceph blacklist. ++.TP + Default value is \fIdirectio\fR. + .RE + .TP diff --git a/SOURCES/0181-multipath-tools-Add-rbd-to-the-hwtable.patch b/SOURCES/0181-multipath-tools-Add-rbd-to-the-hwtable.patch new file mode 100644 index 0000000..fd9d6ff --- /dev/null +++ b/SOURCES/0181-multipath-tools-Add-rbd-to-the-hwtable.patch @@ -0,0 +1,51 @@ +From b25186a60347e2a0f2e53a10c05d9ad52a88c890 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Tue, 9 Aug 2016 13:53:21 -0500 +Subject: [PATCH 05/11] multipath-tools: Add rbd to the hwtable + +For BZ 1348372 from upstream commit: + +commit 61fe9e521965ff70db6a65370b394d769077d54c +Author: Mike Christie +Date: Mon Aug 8 07:01:50 2016 -0500 + + multipath-tools: Add rbd to the hwtable + + Add rbd to hwtable. These defaults are for the HA type of setup + supported by the checker. We do no support features like multibus + at the dm-multipath level yet + +Signed-off-by: Mike Christie +--- + libmultipath/hwtable.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c +index 61d1033..d278c04 100644 +--- a/libmultipath/hwtable.c ++++ b/libmultipath/hwtable.c +@@ -1206,6 +1206,21 @@ static struct hwentry default_hw[] = { + .pgfailback = -FAILBACK_IMMEDIATE, + .checker_name = TUR, + }, ++ { ++ /* ++ * Red Hat ++ * ++ * Maintainer: Mike Christie ++ * Mail: mchristi@redhat.com ++ */ ++ .vendor = "Ceph", ++ .product = "RBD", ++ .pgpolicy = FAILOVER, ++ .no_path_retry = NO_PATH_RETRY_FAIL, ++ .checker_name = RBD, ++ .deferred_remove = DEFERRED_REMOVE_ON, ++ }, ++ + /* + * EOL + */ +-- +1.8.3.1 + diff --git a/SOURCES/0182-multipath-tools-check-for-initialized-checker-before.patch b/SOURCES/0182-multipath-tools-check-for-initialized-checker-before.patch new file mode 100644 index 0000000..26b8f28 --- /dev/null +++ b/SOURCES/0182-multipath-tools-check-for-initialized-checker-before.patch @@ -0,0 +1,49 @@ +From 7592f62383e6143a54d89885e505834c4977c4a6 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Tue, 16 Aug 2016 11:44:27 -0500 +Subject: [PATCH 06/11] multipath-tools: check for initialized checker before + +For bz from upstream commit: + +commit b5773d46a4550c3c222bb415197e0bc5f09c1169 +Author: Mike Christie +Date: Mon Aug 15 12:13:45 2016 -0500 + + multipath-tools: check for initialized checker before + + This fixes a regression added with: + 015f87b16a7797a17afd514aec46e65c2a1a2f73 + + We can hit a race where when pathinfo is setting up a path, the path + could have gone down already. In the DI_CHECKER chunk we then do not +run + get_state and attach a checker. Later when check_path is run + path_offline could still return PATH_DOWN or PATH_REMOVED and + get_state is again not run so we do not get to attach a checker. I + was then running repair_path since the state was PATH_DOWN, and we +then + hit a segfault. + + This has us test if a checker is selected before running repair. + +Signed-off-by: Mike Christie +--- + libmultipath/checkers.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c +index fa7d8b7..6cd8d34 100644 +--- a/libmultipath/checkers.c ++++ b/libmultipath/checkers.c +@@ -212,7 +212,7 @@ void checker_put (struct checker * dst) + + void checker_repair (struct checker * c) + { +- if (!c) ++ if (!c || !checker_selected(c)) + return; + + c->message[0] = '\0'; +-- +1.8.3.1 + diff --git a/SOURCES/0183-multipathd-Don-t-call-repair-on-blacklisted-path.patch b/SOURCES/0183-multipathd-Don-t-call-repair-on-blacklisted-path.patch new file mode 100644 index 0000000..93323c1 --- /dev/null +++ b/SOURCES/0183-multipathd-Don-t-call-repair-on-blacklisted-path.patch @@ -0,0 +1,91 @@ +From 2926316c8492a1d18c7bbdac0fac75c38ce16152 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Tue, 16 Aug 2016 11:47:16 -0500 +Subject: [PATCH 07/11] multipathd: Don't call repair on blacklisted path + +For BZ 1348372 from upstream commit: + +Author: Mike Christie +Date: Mon Aug 15 12:13:46 2016 -0500 + + multipathd: Don't call repair on blacklisted paths + + This fixes a regression added in + 015f87b16a7797a17afd514aec46e65c2a1a2f73 + + If a path is blacklisted the checkerloop will free the path so + don't call repair on it. + + This moves the repair call down into check_path, because I think + we also do not need to call it for other cases where we cannot get + the uuid info or being orphaned. + +Signed-off-by: Mike Christie +--- + multipathd/main.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index d26fd22..4638c8b 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1238,6 +1238,16 @@ int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh) + return 0; + } + ++void repair_path(struct path * pp) ++{ ++ if (pp->state != PATH_DOWN) ++ return; ++ ++ checker_repair(&pp->checker); ++ if (strlen(checker_message(&pp->checker))) ++ LOG_MSG(1, checker_message(&pp->checker)); ++} ++ + void + check_path (struct vectors * vecs, struct path * pp) + { +@@ -1352,6 +1362,7 @@ check_path (struct vectors * vecs, struct path * pp) + pp->mpp->failback_tick = 0; + + pp->mpp->stat_path_failures++; ++ repair_path(pp); + return; + } + +@@ -1431,7 +1442,7 @@ check_path (struct vectors * vecs, struct path * pp) + } + + pp->state = newstate; +- ++ repair_path(pp); + + if (pp->mpp->wait_for_udev) + return; +@@ -1455,14 +1466,6 @@ check_path (struct vectors * vecs, struct path * pp) + } + } + +-void repair_path(struct vectors * vecs, struct path * pp) +-{ +- if (pp->state != PATH_DOWN) +- return; +- +- checker_repair(&pp->checker); +-} +- + static void * + checkerloop (void *ap) + { +@@ -1491,7 +1494,6 @@ checkerloop (void *ap) + if (vecs->pathvec) { + vector_foreach_slot (vecs->pathvec, pp, i) { + check_path(vecs, pp); +- repair_path(vecs, pp); + } + } + if (vecs->mpvec) { +-- +1.8.3.1 + diff --git a/SOURCES/0184-rbd-fix-sync-repair-support.patch b/SOURCES/0184-rbd-fix-sync-repair-support.patch new file mode 100644 index 0000000..6ae6303 --- /dev/null +++ b/SOURCES/0184-rbd-fix-sync-repair-support.patch @@ -0,0 +1,29 @@ +From d1bda720153b4978121fbae40f82d2f4b9aff997 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Thu, 25 Aug 2016 01:34:11 -0500 +Subject: [PATCH 08/11] rbd: fix sync repair support + +If sync was set we were calling check instead +of function passed in. + +Signed-off-by: Mike Christie +--- + libmultipath/checkers/rbd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/checkers/rbd.c b/libmultipath/checkers/rbd.c +index 6f1b53a..76f4005 100644 +--- a/libmultipath/checkers/rbd.c ++++ b/libmultipath/checkers/rbd.c +@@ -554,7 +554,7 @@ static int rbd_exec_fn(struct checker *c, thread_fn *fn) + int rbd_status, r; + + if (c->sync) +- return rbd_check(ct, c->message); ++ return fn(ct, c->message); + /* + * Async mode + */ +-- +1.8.3.1 + diff --git a/SOURCES/0185-rbd-check-for-nonshared-clients.patch b/SOURCES/0185-rbd-check-for-nonshared-clients.patch new file mode 100644 index 0000000..c209d73 --- /dev/null +++ b/SOURCES/0185-rbd-check-for-nonshared-clients.patch @@ -0,0 +1,32 @@ +From c9a788f437f2729f943cd03c43e84b65d74eb015 Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Wed, 31 Aug 2016 15:22:09 -0500 +Subject: [PATCH 09/11] rbd: check for nonshared clients + +The rbd checker only supports nonshared clients so add a check +during init time. + +Signed-off-by: Mike Christie +--- + libmultipath/checkers/rbd.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/libmultipath/checkers/rbd.c b/libmultipath/checkers/rbd.c +index 76f4005..a6f3405 100644 +--- a/libmultipath/checkers/rbd.c ++++ b/libmultipath/checkers/rbd.c +@@ -123,6 +123,11 @@ int libcheck_init(struct checker * c) + if (!config_info) + goto free_addr; + ++ if (!strstr(config_info, "noshare")) { ++ condlog(3, "Only nonshared clients supported."); ++ goto free_addr; ++ } ++ + ct->config_info = strdup(config_info); + if (!ct->config_info) + goto free_addr; +-- +1.8.3.1 + diff --git a/SOURCES/0186-rbd-check-for-exclusive-lock-enabled.patch b/SOURCES/0186-rbd-check-for-exclusive-lock-enabled.patch new file mode 100644 index 0000000..290850b --- /dev/null +++ b/SOURCES/0186-rbd-check-for-exclusive-lock-enabled.patch @@ -0,0 +1,56 @@ +From 513d210cdbccfdaadb0cf7f09ba97d563aac52bb Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Wed, 31 Aug 2016 15:40:16 -0500 +Subject: [PATCH 10/11] rbd: check for exclusive lock enabled + +Only attach the checker if the rbd image has the exclusive lock +enabled. + +Signed-off-by: Mike Christie +--- + libmultipath/checkers/rbd.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/libmultipath/checkers/rbd.c b/libmultipath/checkers/rbd.c +index a6f3405..e34bf53 100644 +--- a/libmultipath/checkers/rbd.c ++++ b/libmultipath/checkers/rbd.c +@@ -33,6 +33,8 @@ typedef int (thread_fn)(struct rbd_checker_context *ct, char *msg); + + #define RBD_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args); + ++#define RBD_FEATURE_EXCLUSIVE_LOCK (1 << 2) ++ + struct rbd_checker_context { + int rbd_bus_id; + char *client_addr; +@@ -65,8 +67,9 @@ int libcheck_init(struct checker * c) + struct udev_device *bus_dev; + struct udev *udev; + struct stat sb; +- const char *block_name, *addr, *config_info; ++ const char *block_name, *addr, *config_info, *features_str; + const char *image, *pool, *snap, *username; ++ uint64_t features = 0; + char sysfs_path[PATH_SIZE]; + int ret; + +@@ -119,6 +122,15 @@ int libcheck_init(struct checker * c) + if (!ct->client_addr) + goto free_dev; + ++ features_str = udev_device_get_sysattr_value(bus_dev, "features"); ++ if (!features_str) ++ goto free_addr; ++ features = strtoll(features_str, NULL, 16); ++ if (!(features & RBD_FEATURE_EXCLUSIVE_LOCK)) { ++ condlog(3, "Exclusive lock not set."); ++ goto free_addr; ++ } ++ + config_info = udev_device_get_sysattr_value(bus_dev, "config_info"); + if (!config_info) + goto free_addr; +-- +1.8.3.1 + diff --git a/SOURCES/0187-rbd-fixup-log-messages.patch b/SOURCES/0187-rbd-fixup-log-messages.patch new file mode 100644 index 0000000..c4ed6db --- /dev/null +++ b/SOURCES/0187-rbd-fixup-log-messages.patch @@ -0,0 +1,238 @@ +From 3ed9a923904887e41c774c71232ae2a1ff6fc3fb Mon Sep 17 00:00:00 2001 +From: Mike Christie +Date: Wed, 31 Aug 2016 15:59:53 -0500 +Subject: [PATCH 11/11] rbd: fixup log messages + +Add rbd device prefix to condlog messages that was missing it, and drop +it in RBD_MSG because it is already added by caller. + +Signed-off-by: Mike Christie +--- + libmultipath/checkers/rbd.c | 67 +++++++++++++++++++++++---------------------- + 1 file changed, 35 insertions(+), 32 deletions(-) + +diff --git a/libmultipath/checkers/rbd.c b/libmultipath/checkers/rbd.c +index e34bf53..8e6cd3c 100644 +--- a/libmultipath/checkers/rbd.c ++++ b/libmultipath/checkers/rbd.c +@@ -113,8 +113,8 @@ int libcheck_init(struct checker * c) + + addr = udev_device_get_sysattr_value(bus_dev, "client_addr"); + if (!addr) { +- condlog(0, "Could not find client_addr in rbd sysfs. Try " +- "updating kernel"); ++ condlog(0, "rbd%d: Could not find client_addr in rbd sysfs. " ++ "Try updating kernel", ct->rbd_bus_id); + goto free_dev; + } + +@@ -127,7 +127,7 @@ int libcheck_init(struct checker * c) + goto free_addr; + features = strtoll(features_str, NULL, 16); + if (!(features & RBD_FEATURE_EXCLUSIVE_LOCK)) { +- condlog(3, "Exclusive lock not set."); ++ condlog(3, "rbd%d: Exclusive lock not set.", ct->rbd_bus_id); + goto free_addr; + } + +@@ -136,7 +136,8 @@ int libcheck_init(struct checker * c) + goto free_addr; + + if (!strstr(config_info, "noshare")) { +- condlog(3, "Only nonshared clients supported."); ++ condlog(3, "rbd%d: Only nonshared clients supported.", ++ ct->rbd_bus_id); + goto free_addr; + } + +@@ -189,18 +190,20 @@ int libcheck_init(struct checker * c) + } + + if (rados_create(&ct->cluster, NULL) < 0) { +- condlog(0, "Could not create rados cluster"); ++ condlog(0, "rbd%d: Could not create rados cluster", ++ ct->rbd_bus_id); + goto free_snap; + } + + if (rados_conf_read_file(ct->cluster, NULL) < 0) { +- condlog(0, "Could not read rados conf"); ++ condlog(0, "rbd%d: Could not read rados conf", ct->rbd_bus_id); + goto shutdown_rados; + } + + ret = rados_connect(ct->cluster); + if (ret < 0) { +- condlog(0, "Could not connect to rados cluster"); ++ condlog(0, "rbd%d: Could not connect to rados cluster", ++ ct->rbd_bus_id); + goto shutdown_rados; + } + +@@ -291,8 +294,7 @@ static int rbd_is_blacklisted(struct rbd_checker_context *ct, char *msg) + ret = rados_mon_command(ct->cluster, (const char **)cmd, 1, "", 0, + &blklist, &blklist_len, &stat, &stat_len); + if (ret < 0) { +- RBD_MSG(msg, "rbd checker failed: mon command failed %d", +- ret); ++ RBD_MSG(msg, "checker failed: mon command failed %d", ret); + return ret; + } + +@@ -313,16 +315,15 @@ static int rbd_is_blacklisted(struct rbd_checker_context *ct, char *msg) + + end = strchr(addr_tok, ' '); + if (!end) { +- RBD_MSG(msg, "rbd%d checker failed: invalid blacklist %s", +- ct->rbd_bus_id, addr_tok); ++ RBD_MSG(msg, "checker failed: invalid blacklist %s", ++ addr_tok); + break; + } + *end = '\0'; + + if (!strcmp(addr_tok, ct->client_addr)) { + ct->blacklisted = 1; +- RBD_MSG(msg, "rbd%d checker: %s is blacklisted", +- ct->rbd_bus_id, ct->client_addr); ++ RBD_MSG(msg, "%s is blacklisted", ct->client_addr); + ret = 1; + break; + } +@@ -339,7 +340,7 @@ int rbd_check(struct rbd_checker_context *ct, char *msg) + if (ct->blacklisted || rbd_is_blacklisted(ct, msg) == 1) + return PATH_DOWN; + +- RBD_MSG(msg, "rbd checker reports path is up"); ++ RBD_MSG(msg, "checker reports path is up"); + /* + * Path may have issues, but the ceph cluster is at least + * accepting IO, so we can attempt to do IO. +@@ -411,10 +412,12 @@ static int rbd_remap(struct rbd_checker_context *ct) + argv[i] = NULL; + + ret = execvp(argv[0], argv); +- condlog(0, "Error executing rbd: %s", strerror(errno)); ++ condlog(0, "rbd%d: Error executing rbd: %s", ct->rbd_bus_id, ++ strerror(errno)); + exit(-1); + case -1: +- condlog(0, "fork failed: %s", strerror(errno)); ++ condlog(0, "rbd%d: fork failed: %s", ct->rbd_bus_id, ++ strerror(errno)); + return -1; + default: + ret = -1; +@@ -424,7 +427,8 @@ static int rbd_remap(struct rbd_checker_context *ct) + if (status == 0) + ret = 0; + else +- condlog(0, "rbd failed with %d", status); ++ condlog(0, "rbd%d: failed with %d", ++ ct->rbd_bus_id, status); + } + } + +@@ -454,12 +458,12 @@ static int rbd_rm_blacklist(struct rbd_checker_context *ct) + ret = rados_mon_command(ct->cluster, (const char **)cmd, 1, "", 0, + NULL, 0, &stat, &stat_len); + if (ret < 0) { +- condlog(1, "rbd%d repair failed to remove blacklist for %s %d", ++ condlog(1, "rbd%d: repair failed to remove blacklist for %s %d", + ct->rbd_bus_id, ct->client_addr, ret); + goto free_cmd; + } + +- condlog(1, "rbd%d repair rm blacklist for %s", ++ condlog(1, "rbd%d: repair rm blacklist for %s", + ct->rbd_bus_id, ct->client_addr); + free(stat); + free_cmd: +@@ -478,8 +482,7 @@ static int rbd_repair(struct rbd_checker_context *ct, char *msg) + if (!ct->remapped) { + ret = rbd_remap(ct); + if (ret) { +- RBD_MSG(msg, "rbd%d repair failed to remap. Err %d", +- ct->rbd_bus_id, ret); ++ RBD_MSG(msg, "repair failed to remap. Err %d", ret); + return PATH_DOWN; + } + } +@@ -488,22 +491,21 @@ static int rbd_repair(struct rbd_checker_context *ct, char *msg) + snprintf(del, sizeof(del), "%d force", ct->rbd_bus_id); + ret = sysfs_write_rbd_remove(del, strlen(del) + 1); + if (ret) { +- RBD_MSG(msg, "rbd%d repair failed to clean up. Err %d", +- ct->rbd_bus_id, ret); ++ RBD_MSG(msg, "repair failed to clean up. Err %d", ret); + return PATH_DOWN; + } + + ret = rbd_rm_blacklist(ct); + if (ret) { +- RBD_MSG(msg, "rbd%d repair could not remove blacklist entry. Err %d", +- ct->rbd_bus_id, ret); ++ RBD_MSG(msg, "repair could not remove blacklist entry. Err %d", ++ ret); + return PATH_DOWN; + } + + ct->remapped = 0; + ct->blacklisted = 0; + +- RBD_MSG(msg, "rbd%d has been repaired", ct->rbd_bus_id); ++ RBD_MSG(msg, "has been repaired"); + return PATH_UP; + } + +@@ -528,7 +530,7 @@ void *rbd_thread(void *ctx) + struct rbd_checker_context *ct = ctx; + int state; + +- condlog(3, "rbd%d thread starting up", ct->rbd_bus_id); ++ condlog(3, "rbd%d: thread starting up", ct->rbd_bus_id); + + ct->message[0] = '\0'; + /* This thread can be canceled, so setup clean up */ +@@ -547,7 +549,7 @@ void *rbd_thread(void *ctx) + pthread_mutex_unlock(&ct->lock); + pthread_cond_signal(&ct->active); + +- condlog(3, "rbd%d thead finished, state %s", ct->rbd_bus_id, ++ condlog(3, "rbd%d: thead finished, state %s", ct->rbd_bus_id, + checker_state_name(state)); + rbd_thread_cleanup_pop(ct); + return ((void *)0); +@@ -577,16 +579,17 @@ static int rbd_exec_fn(struct checker *c, thread_fn *fn) + */ + r = pthread_mutex_lock(&ct->lock); + if (r != 0) { +- condlog(2, "rbd%d mutex lock failed with %d", ct->rbd_bus_id, ++ condlog(2, "rbd%d: mutex lock failed with %d", ct->rbd_bus_id, + r); +- MSG(c, "rbd%d thread failed to initialize", ct->rbd_bus_id); ++ MSG(c, "rbd%d: thread failed to initialize", ct->rbd_bus_id); + return PATH_WILD; + } + + if (ct->running) { + /* Check if checker is still running */ + if (ct->thread) { +- condlog(3, "rbd%d thread not finished", ct->rbd_bus_id); ++ condlog(3, "rbd%d: thread not finished", ++ ct->rbd_bus_id); + rbd_status = PATH_PENDING; + } else { + /* checker done */ +@@ -623,7 +626,7 @@ static int rbd_exec_fn(struct checker *c, thread_fn *fn) + + if (ct->thread && + (rbd_status == PATH_PENDING || rbd_status == PATH_UNCHECKED)) { +- condlog(3, "rbd%d thread still running", ++ condlog(3, "rbd%d: thread still running", + ct->rbd_bus_id); + ct->running = 1; + rbd_status = PATH_PENDING; +-- +1.8.3.1 + diff --git a/SOURCES/0188-RHBZ-1368501-dont-exit.patch b/SOURCES/0188-RHBZ-1368501-dont-exit.patch new file mode 100644 index 0000000..4783991 --- /dev/null +++ b/SOURCES/0188-RHBZ-1368501-dont-exit.patch @@ -0,0 +1,208 @@ +--- + libmultipath/configure.c | 8 +++-- + multipathd/main.c | 68 +++++++++++++++++++++++++++++++++++++---------- + 2 files changed, 59 insertions(+), 17 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -829,8 +829,10 @@ coalesce_paths (struct vectors * vecs, v + * at this point, we know we really got a new mp + */ + mpp = add_map_with_path(vecs, pp1, 0); +- if (!mpp) +- return 1; ++ if (!mpp) { ++ orphan_path(pp1); ++ continue; ++ } + + if (pp1->priority == PRIO_UNDEF) + mpp->action = ACT_REJECT; +@@ -879,7 +881,7 @@ coalesce_paths (struct vectors * vecs, v + condlog(3, "%s: domap (%u) failure " + "for create/reload map", + mpp->alias, r); +- if (r == DOMAP_FAIL) { ++ if (r == DOMAP_FAIL || conf->daemon) { + condlog(2, "%s: %s map", + mpp->alias, (mpp->action == ACT_CREATE)? + "ignoring" : "removing"); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -821,7 +821,7 @@ map_discovery (struct vectors * vecs) + + vector_foreach_slot (vecs->mpvec, mpp, i) + if (setup_multipath(vecs, mpp)) +- return 1; ++ i--; + + return 0; + } +@@ -1523,21 +1523,29 @@ configure (struct vectors * vecs, int st + vector mpvec; + int i, ret; + +- if (!vecs->pathvec && !(vecs->pathvec = vector_alloc())) ++ if (!vecs->pathvec && !(vecs->pathvec = vector_alloc())) { ++ condlog(0, "couldn't allocate path vec in configure"); + return 1; ++ } + +- if (!vecs->mpvec && !(vecs->mpvec = vector_alloc())) ++ if (!vecs->mpvec && !(vecs->mpvec = vector_alloc())) { ++ condlog(0, "couldn't allocate multipath vec in configure"); + return 1; ++ } + +- if (!(mpvec = vector_alloc())) ++ if (!(mpvec = vector_alloc())) { ++ condlog(0, "couldn't allocate new maps vec in configure"); + return 1; ++ } + + /* + * probe for current path (from sysfs) and map (from dm) sets + */ + ret = path_discovery(vecs->pathvec, conf, DI_ALL); +- if (ret < 0) ++ if (ret < 0) { ++ condlog(0, "configure failed at path discovery"); + return 1; ++ } + + vector_foreach_slot (vecs->pathvec, pp, i){ + if (filter_path(conf, pp) > 0){ +@@ -1548,21 +1556,27 @@ configure (struct vectors * vecs, int st + else + pp->checkint = conf->checkint; + } +- if (map_discovery(vecs)) ++ if (map_discovery(vecs)) { ++ condlog(0, "configure failed at map discovery"); + return 1; ++ } + + /* + * create new set of maps & push changed ones into dm + */ +- if (coalesce_paths(vecs, mpvec, NULL, 1)) ++ if (coalesce_paths(vecs, mpvec, NULL, 1)) { ++ condlog(0, "configure failed while coalescing paths"); + return 1; ++ } + + /* + * may need to remove some maps which are no longer relevant + * e.g., due to blacklist changes in conf file + */ +- if (coalesce_maps(vecs, mpvec)) ++ if (coalesce_maps(vecs, mpvec)) { ++ condlog(0, "configure failed while coalescing maps"); + return 1; ++ } + + dm_lib_release(); + +@@ -1588,11 +1602,15 @@ configure (struct vectors * vecs, int st + * start dm event waiter threads for these new maps + */ + vector_foreach_slot(vecs->mpvec, mpp, i) { +- if (setup_multipath(vecs, mpp)) +- return 1; ++ if (setup_multipath(vecs, mpp)) { ++ i--; ++ continue; ++ } + if (start_waiters) +- if (start_waiter_thread(mpp, vecs)) +- return 1; ++ if (start_waiter_thread(mpp, vecs)) { ++ remove_map(mpp, vecs, 1); ++ i--; ++ } + } + return 0; + } +@@ -1857,15 +1875,23 @@ child (void * param) + condlog(2, "--------start up--------"); + condlog(2, "read " DEFAULT_CONFIGFILE); + +- if (load_config(DEFAULT_CONFIGFILE, udev)) ++ if (load_config(DEFAULT_CONFIGFILE, udev)) { ++ condlog(0, "failed to load config"); ++ if (logsink) ++ log_thread_stop(); + exit(1); ++ } + + if (init_checkers()) { + condlog(0, "failed to initialize checkers"); ++ if (logsink) ++ log_thread_stop(); + exit(1); + } + if (init_prio()) { + condlog(0, "failed to initialize prioritizers"); ++ if (logsink) ++ log_thread_stop(); + exit(1); + } + +@@ -1898,8 +1924,12 @@ child (void * param) + } + + vecs = gvecs = init_vecs(); +- if (!vecs) ++ if (!vecs) { ++ condlog(0, "failed to create vecs"); ++ if (logsink) ++ log_thread_stop(); + exit(1); ++ } + + setscheduler(); + set_oom_adj(); +@@ -1911,11 +1941,15 @@ child (void * param) + */ + if ((rc = pthread_create(&uevent_thr, &uevent_attr, ueventloop, udev))) { + condlog(0, "failed to create uevent thread: %d", rc); ++ if (logsink) ++ log_thread_stop(); + exit(1); + } + pthread_attr_destroy(&uevent_attr); + if ((rc = pthread_create(&uxlsnr_thr, &misc_attr, uxlsnrloop, vecs))) { + condlog(0, "failed to create cli listener: %d", rc); ++ if (logsink) ++ log_thread_stop(); + exit(1); + } + /* +@@ -1927,6 +1961,8 @@ child (void * param) + if (configure(vecs, 1)) { + unlock(vecs->lock); + condlog(0, "failure during configuration"); ++ if (logsink) ++ log_thread_stop(); + exit(1); + } + unlock(vecs->lock); +@@ -1936,10 +1972,14 @@ child (void * param) + */ + if ((rc = pthread_create(&check_thr, &misc_attr, checkerloop, vecs))) { + condlog(0,"failed to create checker loop thread: %d", rc); ++ if (logsink) ++ log_thread_stop(); + exit(1); + } + if ((rc = pthread_create(&uevq_thr, &misc_attr, uevqloop, vecs))) { + condlog(0, "failed to create uevent dispatcher: %d", rc); ++ if (logsink) ++ log_thread_stop(); + exit(1); + } + pthread_attr_destroy(&misc_attr); diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index 979d525..afe42c1 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: 85%{?dist}.6 +Release: 99%{?dist} License: GPL+ Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ @@ -140,11 +140,62 @@ Patch0129: 0129-UPBZ-1254292-iscsi-targetname.patch Patch0130: 0130-RHBZ-1259523-host_name_len.patch Patch0131: 0131-UPBZ-1259831-lock-retry.patch Patch0132: 0132-RHBZ-1296979-fix-define.patch -Patch0133: 0133-RHBZ-1321019-wait-for-map-add.patch -Patch0134: 0134-UPBZ-1328515-dont-fail-discovery.patch -Patch0135: 0135-RHBZ-1330480-kpartx-sync.patch -Patch0136: 0136-RHBZ-1335746-clear-chkr-msg.patch -Patch0137: 0137-RHBZ-1364905-ordering.patch +Patch0133: 0133-RHBZ-1241774-sun-partition-numbering.patch +Patch0134: 0134-RHBZ-1241528-check-mpath-prefix.patch +Patch0135: 0135-RHBZ-1299600-path-dev-uevents.patch +Patch0136: 0136-RHBZ-1304687-wait-for-map-add.patch +Patch0137: 0137-RHBZ-1280524-clear-chkr-msg.patch +Patch0138: 0138-RHBZ-1288660-fix-mpathconf-allow.patch +Patch0139: 0139-RHBZ-1273173-queue-no-daemon-doc.patch +Patch0140: 0140-RHBZ-1299647-fix-help.patch +Patch0141: 0141-RHBZ-1303953-mpathpersist-typo.patch +Patch0142: 0142-RHBZ-1283750-kpartx-fix.patch +Patch0143: 0143-RHBZ-1299648-kpartx-sync.patch +Patch0144: 0144-RHBZ-1299652-alua-pref-arg.patch +Patch0145: 0145-UP-resize-help-msg.patch +Patch0146: 0146-UPBZ-1299651-raw-output.patch +Patch0147: 0147-RHBZ-1272620-fail-rm-msg.patch +Patch0148: 0148-RHBZ-1292599-verify-before-remove.patch +Patch0149: 0149-RHBZ-1292599-restore-removed-parts.patch +Patch0150: 0150-RHBZ-1253913-fix-startup-msg.patch +Patch0151: 0151-RHBZ-1297456-weighted-fix.patch +Patch0152: 0152-RHBZ-1269293-fix-blk-unit-file.patch +Patch0153: 0153-RH-fix-i686-size-bug.patch +Patch0154: 0154-UPBZ-1291406-disable-reinstate.patch +Patch0155: 0155-UPBZ-1300415-PURE-config.patch +Patch0156: 0156-UPBZ-1313324-dont-fail-discovery.patch +Patch0157: 0157-RHBZ-1319853-multipath-c-error-msg.patch +Patch0158: 0158-RHBZ-1318581-timestamp-doc-fix.patch +Patch0159: 0159-UPBZ-1255885-udev-waits.patch +Patch0160: 0160-RH-udev-flags.patch +Patch0161: 0161-RHBZ-1311659-no-kpartx.patch +Patch0162: 0162-RHBZ-1333331-huawei-config.patch +Patch0163: 0163-UPBZ-1333492-resize-map.patch +Patch0164: 0164-RHBZ-1311463-dos-part-rollover.patch +Patch0165: 0165-UPBZ-1341748-MSA-2040-conf.patch +Patch0166: 0166-RHBZ-1323429-dont-allow-new-wwid.patch +Patch0167: 0167-RHBZ-1335176-fix-show-cmds.patch +Patch0168: 0168-RHBZ-1347769-shared-lock.patch +Patch0169: 0169-UPBZ-1353357-json-output.patch +Patch0170: 0170-UPBZ-1352925-fix-typo.patch +Patch0171: 0171-UPBZ-1356651-allow-zero-size.patch +Patch0172: 0172-RHBZ-1350931-no-active-add.patch +Patch0173: 0173-RH-update-man-page.patch +Patch0174: 0174-RHBZ-1362396-modprobe.patch +Patch0175: 0175-RHBZ-1357382-ordering.patch +Patch0176: 0176-RHBZ-1363830-fix-rename.patch +Patch0177: 0177-libmultipath-correctly-initialize-pp-sg_id.patch +Patch0178: 0178-libmultipath-add-rbd-discovery.patch +Patch0179: 0179-multipath-tools-add-checker-callout-to-repair-path.patch +Patch0180: 0180-multipath-tools-Add-rbd-checker.patch +Patch0181: 0181-multipath-tools-Add-rbd-to-the-hwtable.patch +Patch0182: 0182-multipath-tools-check-for-initialized-checker-before.patch +Patch0183: 0183-multipathd-Don-t-call-repair-on-blacklisted-path.patch +Patch0184: 0184-rbd-fix-sync-repair-support.patch +Patch0185: 0185-rbd-check-for-nonshared-clients.patch +Patch0186: 0186-rbd-check-for-exclusive-lock-enabled.patch +Patch0187: 0187-rbd-fixup-log-messages.patch +Patch0188: 0188-RHBZ-1368501-dont-exit.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -160,6 +211,9 @@ BuildRequires: libaio-devel, device-mapper-devel >= 1.02.89 BuildRequires: libselinux-devel, libsepol-devel BuildRequires: readline-devel, ncurses-devel BuildRequires: systemd-units, systemd-devel +%ifarch x86_64 +BuildRequires: librados2-devel +%endif BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) @@ -334,6 +388,57 @@ kpartx manages partition creation and removal for device-mapper devices. %patch0135 -p1 %patch0136 -p1 %patch0137 -p1 +%patch0138 -p1 +%patch0139 -p1 +%patch0140 -p1 +%patch0141 -p1 +%patch0142 -p1 +%patch0143 -p1 +%patch0144 -p1 +%patch0145 -p1 +%patch0146 -p1 +%patch0147 -p1 +%patch0148 -p1 +%patch0149 -p1 +%patch0150 -p1 +%patch0151 -p1 +%patch0152 -p1 +%patch0153 -p1 +%patch0154 -p1 +%patch0155 -p1 +%patch0156 -p1 +%patch0157 -p1 +%patch0158 -p1 +%patch0159 -p1 +%patch0160 -p1 +%patch0161 -p1 +%patch0162 -p1 +%patch0163 -p1 +%patch0164 -p1 +%patch0165 -p1 +%patch0166 -p1 +%patch0167 -p1 +%patch0168 -p1 +%patch0169 -p1 +%patch0170 -p1 +%patch0171 -p1 +%patch0172 -p1 +%patch0173 -p1 +%patch0174 -p1 +%patch0175 -p1 +%patch0176 -p1 +%patch0177 -p1 +%patch0178 -p1 +%patch0179 -p1 +%patch0180 -p1 +%patch0181 -p1 +%patch0182 -p1 +%patch0183 -p1 +%patch0184 -p1 +%patch0185 -p1 +%patch0186 -p1 +%patch0187 -p1 +%patch0188 -p1 cp %{SOURCE1} . %build @@ -428,35 +533,176 @@ bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: %{_mandir}/man8/kpartx.8.gz %changelog -* Mon May 16 2016 Benjamin Marzinski 0.4.9-85.6 -- Add 0137-RHBZ-1364905-ordering.patch +* Wed Sep 7 2016 Benjamin Marzinski 0.4.9-99 +- Add 0188-RHBZ-1368501-dont-exit.patch + * make multipathd not exit if it encounters recoverable errors on startup +- Resolves: bz #1368501 + +* Thu Sep 1 2016 Benjamin Marzinski 0.4.9-98 +- Modified 0180-multipath-tools-Add-rbd-checker.patch + * make the rbd path checker only compile if librados2-devel is installed +- Make librados2-devel only be BuildRequired on x86_64 +- Resolves: bz #1348372 + +* Thu Sep 1 2016 Benjamin Marzinski 0.4.9-97 +- Add 0177-libmultipath-correctly-initialize-pp-sg_id.patch + * This and all the following patches add the rbd patch checker +- Add 0178-libmultipath-add-rbd-discovery.patch +- Add 0179-multipath-tools-add-checker-callout-to-repair-path.patch +- Add 0180-multipath-tools-Add-rbd-checker.patch +- Add 0181-multipath-tools-Add-rbd-to-the-hwtable.patch +- Add 0182-multipath-tools-check-for-initialized-checker-before.patch +- Add 0183-multipathd-Don-t-call-repair-on-blacklisted-path.patch +- Add 0184-rbd-fix-sync-repair-support.patch +- Add 0185-rbd-check-for-nonshared-clients.patch +- Add 0186-rbd-check-for-exclusive-lock-enabled.patch +- Add 0187-rbd-fixup-log-messages.patch +- Added BuildRequires on librados2-devel +- Resolves: bz #1348372 + + +* Mon Aug 8 2016 Benjamin Marzinski 0.4.9-96 +- Modify 0136-RHBZ-1304687-wait-for-map-add.patch + * change missing_uev_msg_delay to missing_uev_msg_timeout, and make + multipathd re-enable table loads if the timeout has passed +- Refresh 0137-RHBZ-1280524-clear-chkr-msg.patch +- Refresh 0139-RHBZ-1273173-queue-no-daemon-doc.patch +- Refresh 0150-RHBZ-1253913-fix-startup-msg.patch +- Refresh 0154-UPBZ-1291406-disable-reinstate.patch +- Refresh 0155-UPBZ-1300415-PURE-config.patch +- Refresh 0156-UPBZ-1313324-dont-fail-discovery.patch +- Refresh 0161-RHBZ-1311659-no-kpartx.patch +- Refresh 0167-RHBZ-1335176-fix-show-cmds.patch +- Add 0173-RH-update-man-page.patch +- Add 0174-RHBZ-1362396-modprobe.patch + * make starting the multipathd service modprobe dm-multipath in the + sysvinit scripts +- Add 0175-RHBZ-1357382-ordering.patch * force multipathd.service to start after systemd-udev-trigger.service -- Resolves: bz #1364905 - -* Mon May 16 2016 Benjamin Marzinski 0.4.9-85.5 -- Add 0136-RHBZ-1335746-clear-chkr-msg.patch - * clear old checker message for offline paths. -- Resolves: bz #1335746 - -* Wed Apr 27 2016 Benjamin Marzinski 0.4.9-85.4 -- Add 0135-RHBZ-1330480-kpartx-sync.patch - * default to using udev sync mode -- Resolves: bz #1330480 - -* Tue Apr 19 2016 Benjamin Marzinski 0.4.9-85.3 -- Add 0134-UPBZ-1328515-dont-fail-discovery.patch +- Add 0176-RHBZ-1363830-fix-rename.patch + * initialized a variable to make dm_rename not fail randomly +- Resolves: bz #1304687, #1362396, #1357382, #1363830 + +* Wed Jul 20 2016 Benjamin Marzinski 0.4.9-95 +- Add 0170-UPBZ-1352925-fix-typo.patch +- Add 0171-UPBZ-1356651-allow-zero-size.patch + * Allow zero-sized paths to be added to a multipath device +- Add 0172-RHBZ-1350931-no-active-add.patch + * Allow paths to be added to a new map if no active paths exist. Also + fixes 1351430 +- Resolves: bz #1350931, #1351430, #1352925, #1356651 + + +* Mon Jul 18 2016 Benjamin Marzinski 0.4.9-94 +- Modify 0169-UPBZ-1353357-json-output.patch + * Add manpage documentation +- Resolves: bz #1353357 + +* Fri Jul 15 2016 Benjamin Marzinski 0.4.9-93 +- Modify 0135-RHBZ-1299600-path-dev-uevents.patch + * trigger uevents when adding wwids for existing devices during startup +- Refresh 0136-RHBZ-1304687-wait-for-map-add.patch +- Refresh 0150-RHBZ-1253913-fix-startup-msg.patch +- Add 0168-RHBZ-1347769-shared-lock.patch + * make multipath lock the path devices with a shared lock +- Add 0169-UPBZ-1353357-json-output.patch + * add mulitpathd json output command +- Resolves: bz #1299600, #1347769, #1353357 + +* Tue Jul 5 2016 Benjamin Marzinski 0.4.9-92 +- Add 0166-RHBZ-1323429-dont-allow-new-wwid.patch + * don't allow path wwid to change while it is in use +- Add 0167-RHBZ-1335176-fix-show-cmds.patch + * and new show multipath format wildcard, 'f' to sho number of failures. + This will hopefully be useful for tracking what happens to multipath + devices for bz #1335176 +- Resolves: bz #1323429 + +* Thu Jun 2 2016 Benjamin Marzinski 0.4.9-91 +- Add 0165-UPBZ-1341748-MSA-2040-conf.patch + * Add default config for MSA 2040 array +- Resolves: bz #1341748 + +* Wed Jun 1 2016 Benjamin Marzinski 0.4.9-90 +- Modify 0159-UPBZ-1255885-udev-waits.patch + * fix bug in failure path +- Add 0160-RH-udev-flags.patch +- Add 0161-RHBZ-1311659-no-kpartx.patch + * skip_kpartx option disables kpartx running on multipath devices +- Add 0162-RHBZ-1333331-huawei-config.patch + * Add default config for Huawei XSG1 array +- Add 0163-UPBZ-1333492-resize-map.patch + * restore old size if resize fails +- Add 0164-RHBZ-1311463-dos-part-rollover.patch + * fix incorrect partition size due to 4k device size rollover +- Resolves: bz #1255885, #1311463, #1311659, #1333331, #1333492 + +* Wed Apr 20 2016 Benjamin Marzinski 0.4.9-89 +- Modify 0151-RHBZ-1297456-weighted-fix.patch + * add documentation +- Add 0157-RHBZ-1319853-multipath-c-error-msg.patch + * better error reporting for multipath -c +- Add 0158-RHBZ-1318581-timestamp-doc-fix.patch + * add documentation for -T +- Add 0159-UPBZ-1255885-udev-waits.patch + * make multipath and kpartx wait after for udev after each command +- Resolves: bz #1297456, #1319853, #1318581, #1255885 + +* Tue Mar 29 2016 Benjamin Marzinski 0.4.9-88 +- Add 0151-RHBZ-1297456-weighted-fix.patch + * add wwn keyword to weighted prioritizer for persistent naming +- Add 0152-RHBZ-1269293-fix-blk-unit-file.patch + * use "Wants" instead of "Requires" +- Add 0153-RH-fix-i686-size-bug.patch + * use 64-bit keycodes for multipathd client commands +- Add 0154-UPBZ-1291406-disable-reinstate.patch + * don't automatically reinstate ghost paths for implicit alua devices +- Add 0155-UPBZ-1300415-PURE-config.patch + * Add default config for PURE FlashArray +- Add 0156-UPBZ-1313324-dont-fail-discovery.patch * don't fail discovery because individual paths failed. -- Resolves: bz #1328515 - -* Mon Mar 28 2016 Benjamin Marzinski 0.4.9-85.2 -- Add 0133-RHBZ-1321019-wait-for-map-add.patch +- Resolves: bz #1297456, #1269293, #1291406, #1300415, #1313324 + +* Fri Feb 26 2016 Benjamin Marzinski 0.4.9-87 +- Add 0133-RHBZ-1241774-sun-partition-numbering.patch + * makr kpartx device numbers match partition numbers +- Add 0134-RHBZ-1241528-check-mpath-prefix.patch + * only touch devices with a "mpath-" dm uuid prefix +- Add 0135-RHBZ-1299600-path-dev-uevents.patch + * trigger path uevent the first time a path is claimed by multipath +- Add 0136-RHBZ-1304687-wait-for-map-add.patch * wait for the device to finish being added before reloading it. -- Resolves: bz #1321019 - -* Mon Feb 01 2016 Benjamin Marzinski 0.4.9-85.1 +- Add 0137-RHBZ-1280524-clear-chkr-msg.patch +- Add 0138-RHBZ-1288660-fix-mpathconf-allow.patch + * don't remove existing lines from blacklist_exceptions section +- Add 0139-RHBZ-1273173-queue-no-daemon-doc.patch +- Add 0140-RHBZ-1299647-fix-help.patch +- Add 0141-RHBZ-1303953-mpathpersist-typo.patch +- Add 0142-RHBZ-1283750-kpartx-fix.patch + * only remove devices if their uuid says that they are the correct + partition device +- Add 0143-RHBZ-1299648-kpartx-sync.patch + * default to using udev sync mode +- Add 0144-RHBZ-1299652-alua-pref-arg.patch + * allow "exclusive_pref_bit" argument to alua prioritizer +- Add 0145-UP-resize-help-msg.patch +- Add 0146-UPBZ-1299651-raw-output.patch + * allow raw format mutipathd show commands, that remove headers and padding +- Add 0147-RHBZ-1272620-fail-rm-msg.patch +- Add 0148-RHBZ-1292599-verify-before-remove.patch + * verify that all partitions are unused before attempting to remove a device +- Add 0149-RHBZ-1292599-restore-removed-parts.patch + * don't disable kpartx when restoring the first path of a device. +- Add 0150-RHBZ-1253913-fix-startup-msg.patch + * wait for multipathd daemon to write pidfile before returning +- Resolves: bz #1241528, #1241774, #1253913, #1272620, #1273173, #1280524 +- Resolves: bz #1283750, #1288660, #1292599, #1299600, #1299647, #1299648 +- Resolves: bz #1299651, #1299652, #1303953, #1304687 + +* Wed Jan 27 2016 Benjamin Marzinski 0.4.9-86 - Add 0132-RHBZ-1296979-fix-define.patch * look for the correct libudev function to set define -- Resolves: bz #1303623 +- Resolves: bz # 1296979 * Thu Sep 17 2015 Benjamin Marzinski 0.4.9-85 - Fix device-mapper Requires line in spec file