From a1c519a6ee5eb5fa450f5ece9b2950f6941a6795 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 05 2019 20:54:10 +0000 Subject: import device-mapper-multipath-0.8.0-5.el8 --- diff --git a/.device-mapper-multipath.metadata b/.device-mapper-multipath.metadata index 198838d..8a1df89 100644 --- a/.device-mapper-multipath.metadata +++ b/.device-mapper-multipath.metadata @@ -1 +1 @@ -dd5d23dd9dda7102741ca65e1042f06ecabedf55 SOURCES/multipath-tools-0.7.8.tgz +30bf38b713001c2b80b86d67473fbe20dc0f28cc SOURCES/multipath-tools-0.8.0.tgz diff --git a/.gitignore b/.gitignore index 9cdeea9..512d533 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/multipath-tools-0.7.8.tgz +SOURCES/multipath-tools-0.8.0.tgz diff --git a/SOURCES/0001-BZ-1668693-disable-user_friendly_names-for-NetApp.patch b/SOURCES/0001-BZ-1668693-disable-user_friendly_names-for-NetApp.patch new file mode 100644 index 0000000..491a21d --- /dev/null +++ b/SOURCES/0001-BZ-1668693-disable-user_friendly_names-for-NetApp.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 24 Jan 2019 14:09:23 -0600 +Subject: [PATCH] BZ 1668693: disable user_friendly_names for NetApp + +NetApp has tools that rely on devices using WWID names. To avoid +breaking these, NetApp devices should continue to use WWID names, even +if the default config is set to enable user_friendly_names. If users +want to use user_friendly_names on NetApp devices, the must specifically +override the device config. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/hwtable.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c +index d3a8d9b..8776411 100644 +--- a/libmultipath/hwtable.c ++++ b/libmultipath/hwtable.c +@@ -719,6 +719,7 @@ static struct hwentry default_hw[] = { + .flush_on_last_del = FLUSH_ENABLED, + .dev_loss = MAX_DEV_LOSS_TMO, + .prio_name = PRIO_ONTAP, ++ .user_friendly_names = USER_FRIENDLY_NAMES_OFF, + }, + { + /* +-- +2.17.2 + diff --git a/SOURCES/0001-multipath-tweak-logging-style.patch b/SOURCES/0001-multipath-tweak-logging-style.patch deleted file mode 100644 index 1ba1b7a..0000000 --- a/SOURCES/0001-multipath-tweak-logging-style.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 26 Sep 2018 16:08:59 -0500 -Subject: [PATCH] multipath: tweak logging style - -When multipathd commands are run, errors should be printed to stderr, -instead of syslog. Also, when the multipath is run and calls -device-mapper, device-mapper should log to stderr instead of stdout, -just like multipath does now. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/devmapper.c | 8 ++++---- - multipathd/main.c | 2 ++ - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index 8136d15..0433b49 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -80,11 +80,11 @@ dm_write_log (int level, const char *file, int line, const char *f, ...) - strftime(buff, sizeof(buff), "%b %d %H:%M:%S", tb); - buff[sizeof(buff)-1] = '\0'; - -- fprintf(stdout, "%s | ", buff); -+ fprintf(stderr, "%s | ", buff); - } -- fprintf(stdout, "libdevmapper: %s(%i): ", file, line); -- vfprintf(stdout, f, ap); -- fprintf(stdout, "\n"); -+ fprintf(stderr, "libdevmapper: %s(%i): ", file, line); -+ vfprintf(stderr, f, ap); -+ fprintf(stderr, "\n"); - } else { - condlog(level, "libdevmapper: %s(%i): ", file, line); - log_safe(level + 3, f, ap); -diff --git a/multipathd/main.c b/multipathd/main.c -index af33239..5f0193b 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -2984,6 +2984,7 @@ main (int argc, char *argv[]) - logsink = -1; - break; - case 'k': -+ logsink = 0; - conf = load_config(DEFAULT_CONFIGFILE); - if (!conf) - exit(1); -@@ -3013,6 +3014,7 @@ main (int argc, char *argv[]) - char * s = cmd; - char * c = s; - -+ logsink = 0; - conf = load_config(DEFAULT_CONFIGFILE); - if (!conf) - exit(1); --- -2.7.4 - diff --git a/SOURCES/0002-libmultipath-handle-existing-paths-in-marginal_path-.patch b/SOURCES/0002-libmultipath-handle-existing-paths-in-marginal_path-.patch new file mode 100644 index 0000000..93a3d7c --- /dev/null +++ b/SOURCES/0002-libmultipath-handle-existing-paths-in-marginal_path-.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 25 Jan 2019 16:45:26 -0600 +Subject: [PATCH] libmultipath: handle existing paths in marginal_path enqueue + +If the path that enqueue_io_err_stat_by_path() is trying to add +is already on the list, just return success. There's no reason +to fail in this case. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/io_err_stat.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c +index 02b1453..1cb3ffe 100644 +--- a/libmultipath/io_err_stat.c ++++ b/libmultipath/io_err_stat.c +@@ -254,7 +254,6 @@ static void free_io_err_pathvec(struct io_err_stat_pathvec *p) + * return value + * 0: enqueue OK + * 1: fails because of internal error +- * 2: fails because of existing already + */ + static int enqueue_io_err_stat_by_path(struct path *path) + { +@@ -264,7 +263,7 @@ static int enqueue_io_err_stat_by_path(struct path *path) + p = find_err_path_by_dev(paths->pathvec, path->dev); + if (p) { + pthread_mutex_unlock(&paths->mutex); +- return 2; ++ return 0; + } + pthread_mutex_unlock(&paths->mutex); + +@@ -418,9 +417,8 @@ int hit_io_err_recheck_time(struct path *pp) + io_err_stat_log(3, "%s: enqueue fails, to recover", + pp->dev); + goto recover; +- } else if (!r) { ++ } else + pp->io_err_pathfail_cnt = PATH_IO_ERR_IN_CHECKING; +- } + } + + return 1; +-- +2.17.2 + diff --git a/SOURCES/0002-multipathd-check-for-NULL-udevice-in-cli_add_path.patch b/SOURCES/0002-multipathd-check-for-NULL-udevice-in-cli_add_path.patch deleted file mode 100644 index ccfc1ef..0000000 --- a/SOURCES/0002-multipathd-check-for-NULL-udevice-in-cli_add_path.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Fri, 5 Oct 2018 17:20:38 -0500 -Subject: [PATCH] multipathd: check for NULL udevice in cli_add_path - -If cli_add_path can't get a udevice for the path, it should fail, -instead of continuing with a NULL udevice. - -Signed-off-by: Benjamin Marzinski ---- - multipathd/cli_handlers.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c -index bb16472..7500080 100644 ---- a/multipathd/cli_handlers.c -+++ b/multipathd/cli_handlers.c -@@ -720,6 +720,10 @@ cli_add_path (void * v, char ** reply, int * len, void * data) - udevice = udev_device_new_from_subsystem_sysname(udev, - "block", - param); -+ if (!udevice) { -+ condlog(0, "%s: can't find path", param); -+ return 1; -+ } - conf = get_multipath_config(); - pthread_cleanup_push(put_multipath_config, conf); - r = store_pathinfo(vecs->pathvec, conf, --- -2.7.4 - diff --git a/SOURCES/0003-libmultipath-remove-max_fds-code-duplication.patch b/SOURCES/0003-libmultipath-remove-max_fds-code-duplication.patch deleted file mode 100644 index cc3621a..0000000 --- a/SOURCES/0003-libmultipath-remove-max_fds-code-duplication.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 8 Oct 2018 11:41:03 -0500 -Subject: [PATCH] libmultipath: remove max_fds code duplication - -Instead of multipath, multipathd, and mpathpersist all having code to -set the max number of open file descriptors, just use a util function to -do it. - -Signed-off-by: Benjamin Marzinski ---- - libmpathpersist/mpath_persist.c | 11 +---------- - libmultipath/util.c | 31 +++++++++++++++++++++++++++++++ - libmultipath/util.h | 1 + - multipath/main.c | 12 +----------- - multipathd/main.c | 31 +++---------------------------- - 5 files changed, 37 insertions(+), 49 deletions(-) - -diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c -index 4229a94..29e7fb4 100644 ---- a/libmpathpersist/mpath_persist.c -+++ b/libmpathpersist/mpath_persist.c -@@ -31,7 +31,6 @@ - #include - #include - #include --#include - - #define __STDC_FORMAT_MACROS 1 - -@@ -48,15 +47,7 @@ mpath_lib_init (void) - return NULL; - } - -- if (conf->max_fds) { -- struct rlimit fd_limit; -- -- fd_limit.rlim_cur = conf->max_fds; -- fd_limit.rlim_max = conf->max_fds; -- if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0) -- condlog(0, "can't set open fds limit to %d : %s", -- conf->max_fds, strerror(errno)); -- } -+ set_max_fds(conf->max_fds); - - return conf; - } -diff --git a/libmultipath/util.c b/libmultipath/util.c -index 347af5b..d08112d 100644 ---- a/libmultipath/util.c -+++ b/libmultipath/util.c -@@ -7,6 +7,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -465,3 +467,32 @@ int safe_write(int fd, const void *buf, size_t count) - } - return 0; - } -+ -+void set_max_fds(int max_fds) -+{ -+ struct rlimit fd_limit; -+ -+ if (!max_fds) -+ return; -+ -+ if (getrlimit(RLIMIT_NOFILE, &fd_limit) < 0) { -+ condlog(0, "can't get open fds limit: %s", -+ strerror(errno)); -+ fd_limit.rlim_cur = 0; -+ fd_limit.rlim_max = 0; -+ } -+ if (fd_limit.rlim_cur < max_fds) { -+ fd_limit.rlim_cur = max_fds; -+ if (fd_limit.rlim_max < max_fds) -+ fd_limit.rlim_max = max_fds; -+ if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0) { -+ condlog(0, "can't set open fds limit to " -+ "%lu/%lu : %s", -+ fd_limit.rlim_cur, fd_limit.rlim_max, -+ strerror(errno)); -+ } else { -+ condlog(3, "set open fds limit to %lu/%lu", -+ fd_limit.rlim_cur, fd_limit.rlim_max); -+ } -+ } -+} -diff --git a/libmultipath/util.h b/libmultipath/util.h -index 56cec76..c246295 100644 ---- a/libmultipath/util.h -+++ b/libmultipath/util.h -@@ -21,6 +21,7 @@ int get_linux_version_code(void); - int parse_prkey(char *ptr, uint64_t *prkey); - int parse_prkey_flags(char *ptr, uint64_t *prkey, uint8_t *flags); - int safe_write(int fd, const void *buf, size_t count); -+void set_max_fds(int max_fds); - - #define KERNEL_VERSION(maj, min, ptc) ((((maj) * 256) + (min)) * 256 + (ptc)) - -diff --git a/multipath/main.c b/multipath/main.c -index d5aad95..05b7bf0 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -56,8 +56,6 @@ - #include "pgpolicies.h" - #include "version.h" - #include --#include --#include - #include "wwids.h" - #include "uxsock.h" - #include "mpath_cmd.h" -@@ -1002,15 +1000,7 @@ main (int argc, char *argv[]) - logsink = 1; - } - -- if (conf->max_fds) { -- struct rlimit fd_limit; -- -- fd_limit.rlim_cur = conf->max_fds; -- fd_limit.rlim_max = conf->max_fds; -- if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0) -- condlog(0, "can't set open fds limit to %d : %s", -- conf->max_fds, strerror(errno)); -- } -+ set_max_fds(conf->max_fds); - - libmp_udev_set_sync_support(1); - -diff --git a/multipathd/main.c b/multipathd/main.c -index 5f0193b..d3f7719 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -12,8 +12,6 @@ - #include - #include - #include --#include --#include - #include - #include - #include -@@ -2663,33 +2661,10 @@ child (void * param) - - envp = getenv("LimitNOFILE"); - -- if (envp) { -+ if (envp) - condlog(2,"Using systemd provided open fds limit of %s", envp); -- } else if (conf->max_fds) { -- struct rlimit fd_limit; -- -- if (getrlimit(RLIMIT_NOFILE, &fd_limit) < 0) { -- condlog(0, "can't get open fds limit: %s", -- strerror(errno)); -- fd_limit.rlim_cur = 0; -- fd_limit.rlim_max = 0; -- } -- if (fd_limit.rlim_cur < conf->max_fds) { -- fd_limit.rlim_cur = conf->max_fds; -- if (fd_limit.rlim_max < conf->max_fds) -- fd_limit.rlim_max = conf->max_fds; -- if (setrlimit(RLIMIT_NOFILE, &fd_limit) < 0) { -- condlog(0, "can't set open fds limit to " -- "%lu/%lu : %s", -- fd_limit.rlim_cur, fd_limit.rlim_max, -- strerror(errno)); -- } else { -- condlog(3, "set open fds limit to %lu/%lu", -- fd_limit.rlim_cur, fd_limit.rlim_max); -- } -- } -- -- } -+ else -+ set_max_fds(conf->max_fds); - - vecs = gvecs = init_vecs(); - if (!vecs) --- -2.7.4 - diff --git a/SOURCES/0003-multipathd-cleanup-marginal-paths-checking-timers.patch b/SOURCES/0003-multipathd-cleanup-marginal-paths-checking-timers.patch new file mode 100644 index 0000000..ece5218 --- /dev/null +++ b/SOURCES/0003-multipathd-cleanup-marginal-paths-checking-timers.patch @@ -0,0 +1,70 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 25 Jan 2019 17:09:42 -0600 +Subject: [PATCH] multipathd: cleanup marginal paths checking timers + +When a path gets recovered in hit_io_err_recheck_time(), it will +continue running in check_path(), so there is no reason to schedule +another path check as soon as possible (since one is currently +happening). + +Also, there isn't much point in restarting the io err stat checking when +the path is down, so hit_io_err_recheck_time() should only be run when +the path is up. Downed marginal paths can be treated just like any other +downed path. + +Finally, there is no reason to set reset pp->io_err_dis_reinstate_time +when we decide to enqueue a path. Either th enqueue will fail and the +path will get recovered, or it will succeed, and we won't check the +reinstate time again until poll_io_err_stat() marks the path as needing +a requeue. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/io_err_stat.c | 8 -------- + multipathd/main.c | 3 ++- + 2 files changed, 2 insertions(+), 9 deletions(-) + +diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c +index 1cb3ffe..416e13a 100644 +--- a/libmultipath/io_err_stat.c ++++ b/libmultipath/io_err_stat.c +@@ -400,13 +400,6 @@ int hit_io_err_recheck_time(struct path *pp) + io_err_stat_log(4, "%s: reschedule checking after %d seconds", + pp->dev, + pp->mpp->marginal_path_err_recheck_gap_time); +- /* +- * to reschedule io error checking again +- * if the path is good enough, we claim it is good +- * and can be reinsated as soon as possible in the +- * check_path routine. +- */ +- pp->io_err_dis_reinstate_time = curr_time.tv_sec; + r = enqueue_io_err_stat_by_path(pp); + /* + * Enqueue fails because of internal error. +@@ -426,7 +419,6 @@ int hit_io_err_recheck_time(struct path *pp) + recover: + pp->io_err_pathfail_cnt = 0; + pp->io_err_disable_reinstate = 0; +- pp->tick = 1; + return 0; + } + +diff --git a/multipathd/main.c b/multipathd/main.c +index fb520b6..fe6d8ef 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -2079,7 +2079,8 @@ check_path (struct vectors * vecs, struct path * pp, int ticks) + return 1; + } + +- if (pp->io_err_disable_reinstate && hit_io_err_recheck_time(pp)) { ++ if ((newstate == PATH_UP || newstate == PATH_GHOST) && ++ pp->io_err_disable_reinstate && hit_io_err_recheck_time(pp)) { + pp->state = PATH_SHAKY; + /* + * to reschedule as soon as possible,so that this path can +-- +2.17.2 + diff --git a/SOURCES/0004-libmultipath-fix-marginal-paths-queueing-errors.patch b/SOURCES/0004-libmultipath-fix-marginal-paths-queueing-errors.patch new file mode 100644 index 0000000..9417741 --- /dev/null +++ b/SOURCES/0004-libmultipath-fix-marginal-paths-queueing-errors.patch @@ -0,0 +1,176 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 28 Jan 2019 00:20:53 -0600 +Subject: [PATCH] libmultipath: fix marginal paths queueing errors + +The current marginal paths code tries to enqueue paths for io error +checking when multipathd receives a uevent on path failure. This can run +into a couple of problems. First, this uevent could happen before or +after multipathd actually fails the path, so simply checking nr_active +doesn't tell us if this is the last active path. Also, The code to fail +the path in enqueue_io_err_stat_by_path() doesn't ever update the path +state. This can cause the path to get failed twice, temporarily leading +to incorrect nr_active counts. Further, The point when multipathd should +care if this is the last active path is when the path has come up again, +not when it goes down. Lastly, if the path is down, it is often +impossible to open the path device, causing setup_directio_ctx() to +fail, which causes multipathd to skip io error checking and mark the +path as not marginal. + +Instead, multipathd should just make sure that if the path is marginal, +it gets failed in the uevent, so as not to race with the checkerloop +thread. Then, when the path comes back up, check_path() can enqueue it, +just like it does for paths that need to get rechecked. To make it +obvious that the state PATH_IO_ERR_IN_POLLING_RECHECK and the function +hit_io_err_recheck_time() now apply to paths waiting to be enqueued for +the first time as well, I've also changed their names to +PATH_IO_ERR_WAITING_TO_CHECK and need_io_err_check(), respectively. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/io_err_stat.c | 55 +++++++++++++++++--------------------- + libmultipath/io_err_stat.h | 2 +- + multipathd/main.c | 2 +- + 3 files changed, 27 insertions(+), 32 deletions(-) + +diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c +index 416e13a..72aacf3 100644 +--- a/libmultipath/io_err_stat.c ++++ b/libmultipath/io_err_stat.c +@@ -41,7 +41,7 @@ + #define CONCUR_NR_EVENT 32 + + #define PATH_IO_ERR_IN_CHECKING -1 +-#define PATH_IO_ERR_IN_POLLING_RECHECK -2 ++#define PATH_IO_ERR_WAITING_TO_CHECK -2 + + #define io_err_stat_log(prio, fmt, args...) \ + condlog(prio, "io error statistic: " fmt, ##args) +@@ -283,24 +283,6 @@ static int enqueue_io_err_stat_by_path(struct path *path) + vector_set_slot(paths->pathvec, p); + pthread_mutex_unlock(&paths->mutex); + +- if (!path->io_err_disable_reinstate) { +- /* +- *fail the path in the kernel for the time of the to make +- *the test more reliable +- */ +- io_err_stat_log(3, "%s: fail dm path %s before checking", +- path->mpp->alias, path->dev); +- path->io_err_disable_reinstate = 1; +- dm_fail_path(path->mpp->alias, path->dev_t); +- update_queue_mode_del_path(path->mpp); +- +- /* +- * schedule path check as soon as possible to +- * update path state to delayed state +- */ +- path->tick = 1; +- +- } + io_err_stat_log(2, "%s: enqueue path %s to check", + path->mpp->alias, path->dev); + return 0; +@@ -317,7 +299,6 @@ free_ioerr_path: + int io_err_stat_handle_pathfail(struct path *path) + { + struct timespec curr_time; +- int res; + + if (uatomic_read(&io_err_thread_running) == 0) + return 1; +@@ -332,8 +313,6 @@ int io_err_stat_handle_pathfail(struct path *path) + + if (!path->mpp) + return 1; +- if (path->mpp->nr_active <= 1) +- return 1; + if (path->mpp->marginal_path_double_failed_time <= 0 || + path->mpp->marginal_path_err_sample_time <= 0 || + path->mpp->marginal_path_err_recheck_gap_time <= 0 || +@@ -371,17 +350,33 @@ int io_err_stat_handle_pathfail(struct path *path) + } + path->io_err_pathfail_cnt++; + if (path->io_err_pathfail_cnt >= FLAKY_PATHFAIL_THRESHOLD) { +- res = enqueue_io_err_stat_by_path(path); +- if (!res) +- path->io_err_pathfail_cnt = PATH_IO_ERR_IN_CHECKING; +- else +- path->io_err_pathfail_cnt = 0; ++ path->io_err_disable_reinstate = 1; ++ path->io_err_pathfail_cnt = PATH_IO_ERR_WAITING_TO_CHECK; ++ /* enqueue path as soon as it comes up */ ++ path->io_err_dis_reinstate_time = 0; ++ if (path->state != PATH_DOWN) { ++ struct config *conf; ++ int oldstate = path->state; ++ int checkint; ++ ++ conf = get_multipath_config(); ++ checkint = conf->checkint; ++ put_multipath_config(conf); ++ io_err_stat_log(2, "%s: mark as failed", path->dev); ++ path->mpp->stat_path_failures++; ++ path->state = PATH_DOWN; ++ path->dmstate = PSTATE_FAILED; ++ if (oldstate == PATH_UP || oldstate == PATH_GHOST) ++ update_queue_mode_del_path(path->mpp); ++ if (path->tick > checkint) ++ path->tick = checkint; ++ } + } + + return 0; + } + +-int hit_io_err_recheck_time(struct path *pp) ++int need_io_err_check(struct path *pp) + { + struct timespec curr_time; + int r; +@@ -392,7 +387,7 @@ int hit_io_err_recheck_time(struct path *pp) + io_err_stat_log(2, "%s: recover path early", pp->dev); + goto recover; + } +- if (pp->io_err_pathfail_cnt != PATH_IO_ERR_IN_POLLING_RECHECK) ++ if (pp->io_err_pathfail_cnt != PATH_IO_ERR_WAITING_TO_CHECK) + return 1; + if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0 || + (curr_time.tv_sec - pp->io_err_dis_reinstate_time) > +@@ -489,7 +484,7 @@ static int poll_io_err_stat(struct vectors *vecs, struct io_err_stat_path *pp) + } else if (path->mpp && path->mpp->nr_active > 1) { + io_err_stat_log(3, "%s: keep failing the dm path %s", + path->mpp->alias, path->dev); +- path->io_err_pathfail_cnt = PATH_IO_ERR_IN_POLLING_RECHECK; ++ path->io_err_pathfail_cnt = PATH_IO_ERR_WAITING_TO_CHECK; + path->io_err_disable_reinstate = 1; + path->io_err_dis_reinstate_time = currtime.tv_sec; + io_err_stat_log(3, "%s: disable reinstating of %s", +diff --git a/libmultipath/io_err_stat.h b/libmultipath/io_err_stat.h +index bbf31b4..53d6d7d 100644 +--- a/libmultipath/io_err_stat.h ++++ b/libmultipath/io_err_stat.h +@@ -10,6 +10,6 @@ extern pthread_attr_t io_err_stat_attr; + int start_io_err_stat_thread(void *data); + void stop_io_err_stat_thread(void); + int io_err_stat_handle_pathfail(struct path *path); +-int hit_io_err_recheck_time(struct path *pp); ++int need_io_err_check(struct path *pp); + + #endif /* _IO_ERR_STAT_H */ +diff --git a/multipathd/main.c b/multipathd/main.c +index fe6d8ef..43830e8 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -2080,7 +2080,7 @@ check_path (struct vectors * vecs, struct path * pp, int ticks) + } + + if ((newstate == PATH_UP || newstate == PATH_GHOST) && +- pp->io_err_disable_reinstate && hit_io_err_recheck_time(pp)) { ++ pp->io_err_disable_reinstate && need_io_err_check(pp)) { + pp->state = PATH_SHAKY; + /* + * to reschedule as soon as possible,so that this path can +-- +2.17.2 + diff --git a/SOURCES/0004-multipathd-set-return-code-for-multipathd-commands.patch b/SOURCES/0004-multipathd-set-return-code-for-multipathd-commands.patch deleted file mode 100644 index 4ef2265..0000000 --- a/SOURCES/0004-multipathd-set-return-code-for-multipathd-commands.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 8 Oct 2018 14:49:30 -0500 -Subject: [PATCH] multipathd: set return code for multipathd commands - -Failed multipathd commands should set the return code to 1. - -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 8 ++++---- - multipathd/uxclnt.c | 13 ++++++++----- - 2 files changed, 12 insertions(+), 9 deletions(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index d3f7719..2d45d98 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -2966,9 +2966,9 @@ main (int argc, char *argv[]) - if (verbosity) - conf->verbosity = verbosity; - uxsock_timeout = conf->uxsock_timeout; -- uxclnt(optarg, uxsock_timeout + 100); -+ err = uxclnt(optarg, uxsock_timeout + 100); - free_config(conf); -- exit(0); -+ return err; - case 'B': - bindings_read_only = 1; - break; -@@ -3005,9 +3005,9 @@ main (int argc, char *argv[]) - optind++; - } - c += snprintf(c, s + CMDSIZE - c, "\n"); -- uxclnt(s, uxsock_timeout + 100); -+ err = uxclnt(s, uxsock_timeout + 100); - free_config(conf); -- exit(0); -+ return err; - } - - if (foreground) { -diff --git a/multipathd/uxclnt.c b/multipathd/uxclnt.c -index 08db0e8..a76f8e2 100644 ---- a/multipathd/uxclnt.c -+++ b/multipathd/uxclnt.c -@@ -103,14 +103,14 @@ static void process(int fd, unsigned int timeout) - } - } - --static void process_req(int fd, char * inbuf, unsigned int timeout) -+static int process_req(int fd, char * inbuf, unsigned int timeout) - { - char *reply; - int ret; - - if (send_packet(fd, inbuf) != 0) { - printf("cannot send packet\n"); -- return; -+ return 1; - } - ret = recv_packet(fd, &reply, timeout); - if (ret < 0) { -@@ -118,9 +118,12 @@ static void process_req(int fd, char * inbuf, unsigned int timeout) - printf("timeout receiving packet\n"); - else - printf("error %d receiving packet\n", ret); -+ return 1; - } else { - printf("%s", reply); -+ ret = (strcmp(reply, "fail\n") == 0); - FREE(reply); -+ return ret; - } - } - -@@ -129,16 +132,16 @@ static void process_req(int fd, char * inbuf, unsigned int timeout) - */ - int uxclnt(char * inbuf, unsigned int timeout) - { -- int fd; -+ int fd, ret = 0; - - fd = mpath_connect(); - if (fd == -1) - exit(1); - - if (inbuf) -- process_req(fd, inbuf, timeout); -+ ret = process_req(fd, inbuf, timeout); - else - process(fd, timeout); - mpath_disconnect(fd); -- return 0; -+ return ret; - } --- -2.7.4 - diff --git a/SOURCES/0005-libmultipath-fix-marginal_paths-nr_active-check.patch b/SOURCES/0005-libmultipath-fix-marginal_paths-nr_active-check.patch new file mode 100644 index 0000000..486e03a --- /dev/null +++ b/SOURCES/0005-libmultipath-fix-marginal_paths-nr_active-check.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 29 Jan 2019 18:26:04 -0600 +Subject: [PATCH] libmultipath: fix marginal_paths nr_active check + +Marginal paths are SHAKY, so they don't count towards the number of +active paths. poll_io_err_stat() shouldn't automatically reinstate a +marginal path if there already is an active path. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/io_err_stat.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c +index 72aacf3..554b777 100644 +--- a/libmultipath/io_err_stat.c ++++ b/libmultipath/io_err_stat.c +@@ -481,7 +481,7 @@ static int poll_io_err_stat(struct vectors *vecs, struct io_err_stat_path *pp) + */ + path->tick = 1; + +- } else if (path->mpp && path->mpp->nr_active > 1) { ++ } else if (path->mpp && path->mpp->nr_active > 0) { + io_err_stat_log(3, "%s: keep failing the dm path %s", + path->mpp->alias, path->dev); + path->io_err_pathfail_cnt = PATH_IO_ERR_WAITING_TO_CHECK; +-- +2.17.2 + diff --git a/SOURCES/0005-mpathpersist-fix-registration-rollback-issue.patch b/SOURCES/0005-mpathpersist-fix-registration-rollback-issue.patch deleted file mode 100644 index 3cba08d..0000000 --- a/SOURCES/0005-mpathpersist-fix-registration-rollback-issue.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 8 Oct 2018 16:45:11 -0500 -Subject: [PATCH] mpathpersist: fix registration rollback issue - -When mpathpersist tries to rollback the registration, it copies -the SARK to the RK, and clears the SARK. However, it repeated this step -for each thread. This means that the first rollback thread correctly -had the RK set to the SARK used during registration. However, if more -than one registration needed to be rolled back, later threads would have -both the RK and SARK cleared. This commit fixes that by only copying and -clearing the SARK once. - -Signed-off-by: Benjamin Marzinski ---- - libmpathpersist/mpath_persist.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c -index 29e7fb4..2ffe56e 100644 ---- a/libmpathpersist/mpath_persist.c -+++ b/libmpathpersist/mpath_persist.c -@@ -559,11 +559,10 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope, - } - if (rollback && ((rq_servact == MPATH_PROUT_REG_SA) && sa_key != 0 )){ - condlog (3, "%s: ERROR: initiating pr out rollback", mpp->wwid); -+ memcpy(¶mp->key, ¶mp->sa_key, 8); -+ memset(¶mp->sa_key, 0, 8); - for( i=0 ; i < count ; i++){ - if(thread[i].param.status == MPATH_PR_SUCCESS) { -- memcpy(&thread[i].param.paramp->key, &thread[i].param.paramp->sa_key, 8); -- memset(&thread[i].param.paramp->sa_key, 0, 8); -- thread[i].param.status = MPATH_PR_SUCCESS; - rc = pthread_create(&thread[i].id, &attr, mpath_prout_pthread_fn, - (void *)(&thread[i].param)); - if (rc){ --- -2.7.4 - diff --git a/SOURCES/0006-libmultipath-timeout-on-unresponsive-tur-thread.patch b/SOURCES/0006-libmultipath-timeout-on-unresponsive-tur-thread.patch deleted file mode 100644 index 0e44f49..0000000 --- a/SOURCES/0006-libmultipath-timeout-on-unresponsive-tur-thread.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 10 Oct 2018 11:15:30 -0500 -Subject: [PATCH] libmultipath: timeout on unresponsive tur thread - -If the tur checker thread has been cancelled but isn't responding, -timeout instead of doing a sync check. This will keep one bad -device from impacting all of multipathd. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/checkers/tur.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c -index 86c0cdc..b2a2170 100644 ---- a/libmultipath/checkers/tur.c -+++ b/libmultipath/checkers/tur.c -@@ -305,10 +305,10 @@ int libcheck_check(struct checker * c) - } else { - if (uatomic_read(&ct->holders) > 1) { - /* The thread has been cancelled but hasn't -- * quilt. Fail back to synchronous mode */ -- condlog(3, "%d:%d : tur checker failing back to sync", -+ * quit. exit with timeout. */ -+ condlog(3, "%d:%d : tur thread not responding", - major(ct->devt), minor(ct->devt)); -- return tur_check(c->fd, c->timeout, c->message); -+ return PATH_TIMEOUT; - } - /* Start new TUR checker */ - pthread_mutex_lock(&ct->lock); --- -2.7.4 - diff --git a/SOURCES/0006-multipathd-Fix-miscounting-active-paths.patch b/SOURCES/0006-multipathd-Fix-miscounting-active-paths.patch new file mode 100644 index 0000000..4eb50f5 --- /dev/null +++ b/SOURCES/0006-multipathd-Fix-miscounting-active-paths.patch @@ -0,0 +1,92 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 15 Feb 2019 17:19:46 -0600 +Subject: [PATCH] multipathd: Fix miscounting active paths + +When multipathd gets a change uevent, it calls pathinfo with DI_NOIO. +This sets the path state to the return value of path_offline(). If a +path is in the PATH_DOWN state but path_offline() returns PATH_UP, when +that path gets a change event, its state will get moved to PATH_UP +without either reinstating the path, or reloading the map. The next +call to check_path() will move the path back to PATH_DOWN. Since +check_path() simply increments and decrements nr_active instead of +calculating it based on the actual number of active paths, nr_active +will get decremented a second time for this failed path, potentially +putting the multipath device into recovery mode. + +This commit does two things to avoid this situation. It makes the +DI_NOIO flag only set pp->state in pathinfo() if DI_CHECKER is also set. +This isn't set in uev_update_path() to avoid changing the path state in +this case. Also, to guard against pp->state getting changed in some +other code path without properly updating the map state, check_path() +now calls set_no_path_retry, which recalculates nr_active based on the +actual number of active paths, and makes sure that the queue_if_no_path +value in the features line is correct. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 11 ++++++----- + multipath/main.c | 2 +- + multipathd/main.c | 4 +++- + 3 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 10bd8cd..729bcb9 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1914,11 +1914,12 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + if (path_state == PATH_REMOVED) + goto blank; + else if (mask & DI_NOIO) { +- /* +- * Avoid any IO on the device itself. +- * Behave like DI_CHECKER in the "path unavailable" case. +- */ +- pp->chkrstate = pp->state = path_state; ++ if (mask & DI_CHECKER) ++ /* ++ * Avoid any IO on the device itself. ++ * simply use the path_offline() return as its state ++ */ ++ pp->chkrstate = pp->state = path_state; + return PATHINFO_OK; + } + +diff --git a/multipath/main.c b/multipath/main.c +index 5abb118..69141db 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -356,7 +356,7 @@ static int check_usable_paths(struct config *conf, + pp->udev = get_udev_device(pp->dev_t, DEV_DEVT); + if (pp->udev == NULL) + continue; +- if (pathinfo(pp, conf, DI_SYSFS|DI_NOIO) != PATHINFO_OK) ++ if (pathinfo(pp, conf, DI_SYSFS|DI_NOIO|DI_CHECKER) != PATHINFO_OK) + continue; + + if (pp->state == PATH_UP && +diff --git a/multipathd/main.c b/multipathd/main.c +index 43830e8..678ecf8 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -392,7 +392,8 @@ static void set_no_path_retry(struct multipath *mpp) + default: + if (mpp->nr_active > 0) { + mpp->retry_tick = 0; +- dm_queue_if_no_path(mpp->alias, 1); ++ if (!is_queueing) ++ dm_queue_if_no_path(mpp->alias, 1); + } else if (is_queueing && mpp->retry_tick == 0) + enter_recovery_mode(mpp); + break; +@@ -2072,6 +2073,7 @@ check_path (struct vectors * vecs, struct path * pp, int ticks) + /* if update_multipath_strings orphaned the path, quit early */ + if (!pp->mpp) + return 0; ++ set_no_path_retry(pp->mpp); + + if ((newstate == PATH_UP || newstate == PATH_GHOST) && + check_path_reinstate_state(pp)) { +-- +2.17.2 + diff --git a/SOURCES/0007-RH-fixup-udev-rules-for-redhat.patch b/SOURCES/0007-RH-fixup-udev-rules-for-redhat.patch deleted file mode 100644 index b3e4428..0000000 --- a/SOURCES/0007-RH-fixup-udev-rules-for-redhat.patch +++ /dev/null @@ -1,82 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 13 Apr 2017 07:22:23 -0500 -Subject: [PATCH] RH: fixup udev rules for redhat - -The multipath rules need to run after scsi_id is run. This means moving -them after 60-persistent-storage.rules for redhat. Redhat also uses a -different naming scheme for partitions than SuSE. Also, there are some -false warnings that gcc throws because of the changed options. Fix these -too. - -Signed-off-by: Benjamin Marzinski ---- - Makefile.inc | 2 +- - kpartx/kpartx.rules | 2 +- - multipath/Makefile | 4 ++-- - multipath/main.c | 2 +- - 4 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/Makefile.inc b/Makefile.inc -index a83f02c..b86cba6 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -51,7 +51,7 @@ endif - prefix = - exec_prefix = $(prefix) - usr_prefix = $(prefix) --bindir = $(exec_prefix)/sbin -+bindir = $(exec_prefix)/usr/sbin - libudevdir = $(prefix)/$(SYSTEMDPATH)/udev - udevrulesdir = $(libudevdir)/rules.d - multipathdir = $(TOPDIR)/libmultipath -diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules -index 8f99049..8a3a171 100644 ---- a/kpartx/kpartx.rules -+++ b/kpartx/kpartx.rules -@@ -32,6 +32,6 @@ LABEL="mpath_kpartx_end" - GOTO="kpartx_end" - - LABEL="run_kpartx" --RUN+="/sbin/kpartx -un -p -part /dev/$name" -+RUN+="/sbin/kpartx -un /dev/$name" - - LABEL="kpartx_end" -diff --git a/multipath/Makefile b/multipath/Makefile -index 0828a8f..b9bbb3c 100644 ---- a/multipath/Makefile -+++ b/multipath/Makefile -@@ -24,7 +24,7 @@ install: - $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ - $(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) - $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) -- $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules -+ $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules - $(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir) - $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir) - $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) -@@ -33,7 +33,7 @@ install: - uninstall: - $(RM) $(DESTDIR)$(bindir)/$(EXEC) - $(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules -- $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules -+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules - $(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz - $(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz - -diff --git a/multipath/main.c b/multipath/main.c -index 05b7bf0..ffa5b22 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -401,7 +401,7 @@ static int find_multipaths_check_timeout(const struct path *pp, long tmo, - struct timespec now, ftimes[2], tdiff; - struct stat st; - long fd; -- int r, err, retries = 0; -+ int r, err = 0, retries = 0; - - clock_gettime(CLOCK_REALTIME, &now); - --- -2.7.4 - diff --git a/SOURCES/0007-multipathd-ignore-failed-wwid-recheck.patch b/SOURCES/0007-multipathd-ignore-failed-wwid-recheck.patch new file mode 100644 index 0000000..37fdae1 --- /dev/null +++ b/SOURCES/0007-multipathd-ignore-failed-wwid-recheck.patch @@ -0,0 +1,71 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 20 Feb 2019 17:05:08 -0600 +Subject: [PATCH] multipathd: ignore failed wwid recheck + +If disable_changed_wwids is set, when multipathd gets a change event on +a path, it verifies that the wwid hasn't changed in uev_update_path(). +If get_uid() failed, uev_update_path treated this as a wwid change to 0. +This could cause paths to suddenly be dropped due to an issue with +getting the wwid. Even if get_uid() failed because the path was down, +it no change uevent happend when it later became active, multipathd +would continue to ignore the path. Also, scsi_uid_fallback() clears the +failure return if it doesn't attempt to fallback, causing get_uid() +to return success, when it actually failed. + +Multipathd should neither set nor clear wwid_changed if get_uid() +returned failure. Also, scsi_uid_fallback() should retain the old return +value if it doesn't attempt to fallback. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 6 +++--- + multipathd/main.c | 6 ++++-- + 2 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 729bcb9..b08cb2d 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1755,9 +1755,9 @@ get_vpd_uid(struct path * pp) + } + + static ssize_t scsi_uid_fallback(struct path *pp, int path_state, +- const char **origin) ++ const char **origin, ssize_t old_len) + { +- ssize_t len = 0; ++ ssize_t len = old_len; + int retrigger; + struct config *conf; + +@@ -1828,7 +1828,7 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev) + origin = "sysfs"; + } + if (len <= 0 && pp->bus == SYSFS_BUS_SCSI) +- len = scsi_uid_fallback(pp, path_state, &origin); ++ len = scsi_uid_fallback(pp, path_state, &origin, len); + } + if ( len < 0 ) { + condlog(1, "%s: failed to get %s uid: %s", +diff --git a/multipathd/main.c b/multipathd/main.c +index 678ecf8..fd83a6a 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1234,9 +1234,11 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + goto out; + + strcpy(wwid, pp->wwid); +- get_uid(pp, pp->state, uev->udev); ++ rc = get_uid(pp, pp->state, uev->udev); + +- if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { ++ if (rc != 0) ++ strcpy(pp->wwid, wwid); ++ else if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { + condlog(0, "%s: path wwid changed from '%s' to '%s'. %s", + uev->kernel, wwid, pp->wwid, + (disable_changed_wwids ? "disallowing" : +-- +2.17.2 + diff --git a/SOURCES/0008-RH-Remove-the-property-blacklist-exception-builtin.patch b/SOURCES/0008-RH-Remove-the-property-blacklist-exception-builtin.patch deleted file mode 100644 index 87eba36..0000000 --- a/SOURCES/0008-RH-Remove-the-property-blacklist-exception-builtin.patch +++ /dev/null @@ -1,80 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 2 Jul 2014 12:49:53 -0500 -Subject: [PATCH] RH: Remove the property blacklist exception builtin - -Multipath set the default property blacklist exceptions to -(ID_SCSI_VPD|ID_WWN). This has the effect of blacklisting some internal -devices. These devices may never have multiple paths, but it is nice -to be able to set multipath up on them all the same. This patch simply -removes the default, and makes it so that if no property -blacklist_exception is given, then devices aren't failed for not matching -it. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/blacklist.c | 12 ++++-------- - multipath/multipath.conf.5 | 14 ++++++-------- - 2 files changed, 10 insertions(+), 16 deletions(-) - -diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c -index 318ec03..c0cfbca 100644 ---- a/libmultipath/blacklist.c -+++ b/libmultipath/blacklist.c -@@ -204,12 +204,6 @@ setup_default_blist (struct config * conf) - if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT)) - return 1; - -- str = STRDUP("(SCSI_IDENT_|ID_WWN)"); -- if (!str) -- return 1; -- if (store_ble(conf->elist_property, str, ORIGIN_DEFAULT)) -- return 1; -- - vector_foreach_slot (conf->hwtable, hwe, i) { - if (hwe->bl_product) { - if (find_blacklist_device(conf->blist_device, -@@ -394,9 +388,11 @@ filter_property(struct config * conf, struct udev_device * udev) - if (udev) { - /* - * This is the inverse of the 'normal' matching; -- * the environment variable _has_ to match. -+ * the environment variable _has_ to match -+ * if a whitelist is present. - */ -- r = MATCH_PROPERTY_BLIST_MISSING; -+ if (VECTOR_SIZE(conf->elist_property)) -+ r = MATCH_PROPERTY_BLIST_MISSING; - udev_list_entry_foreach(list_entry, - udev_device_get_properties_list_entry(udev)) { - -diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 -index 6333366..3dab26b 100644 ---- a/multipath/multipath.conf.5 -+++ b/multipath/multipath.conf.5 -@@ -1195,16 +1195,14 @@ keywords. Both are regular expressions. For a full description of these keywords - Regular expression for an udev property. All - devices that have matching udev properties will be excluded/included. - The handling of the \fIproperty\fR keyword is special, --because devices \fBmust\fR have at least one whitelisted udev property; -+because if a property blacklist_exception is set, devices \fBmust\fR have at -+least one whitelisted udev property; - otherwise they're treated as blacklisted, and the message - "\fIblacklisted, udev property missing\fR" is displayed in the logs. --. --.RS --.PP --The default \fIblacklist exception\fR is: \fB(SCSI_IDENT_|ID_WWN)\fR, causing --well-behaved SCSI devices and devices that provide a WWN (World Wide Number) --to be included, and all others to be excluded. --.RE -+For example, setting the property blacklist_exception to -+\fB(SCSI_IDENT_|ID_WWN)\fR, will cause well-behaved SCSI devices and devices -+that provide a WWN (World Wide Number) to be included, and all others to be -+excluded. This works to exclude most non-multipathable devices. - .TP - .B protocol - Regular expression for the protocol of a device to be excluded/included. --- -2.7.4 - diff --git a/SOURCES/0008-libmutipath-continue-to-use-old-state-on-PATH_PENDIN.patch b/SOURCES/0008-libmutipath-continue-to-use-old-state-on-PATH_PENDIN.patch new file mode 100644 index 0000000..aa43b94 --- /dev/null +++ b/SOURCES/0008-libmutipath-continue-to-use-old-state-on-PATH_PENDIN.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 21 Feb 2019 13:05:43 -0600 +Subject: [PATCH] libmutipath: continue to use old state on PATH_PENDING + +When pathinfo() sets pp->state to PATH_PENDING, it can cause problems +with path checking. It should act more like check_path(). When +check_path() sees a new state of PATH_PENDING, it doesn't update the +path state at all, so a path's old state is normally never PATH_PENDING. + +As and example of the problems of setting a path to PATH_PENDING, If +check_path() sets a path's state to PATH_UP, then a call to pathinfo() +sets the state to PATH_PENDING, and then another call the check_path() +sets the state to PATH_DOWN, multipathd won't fail the path in the +kernel. Also, if a path's state is PATH_PENDING, and nr_active is +recalculated, that path will count as down, even if the state was +previously PATH_UP. If a path already has a state of PATH_WILD or +PATH_UNCHECKED, changing it to PATH_PENDING won't hurt anything, and it +will help anyone who sees it know what's actually happening. But +otherwise, pathinfo() should leave the previous state alone. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index b08cb2d..28c00e5 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1946,8 +1946,11 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + + if (mask & DI_CHECKER) { + if (path_state == PATH_UP) { +- pp->chkrstate = pp->state = get_state(pp, conf, 0, +- path_state); ++ int newstate = get_state(pp, conf, 0, path_state); ++ if (newstate != PATH_PENDING || ++ pp->state == PATH_UNCHECKED || ++ pp->state == PATH_WILD) ++ pp->chkrstate = pp->state = newstate; + if (pp->state == PATH_TIMEOUT) + pp->state = PATH_DOWN; + if (pp->state == PATH_UP && !pp->size) { +-- +2.17.2 + diff --git a/SOURCES/0009-RH-don-t-start-without-a-config-file.patch b/SOURCES/0009-RH-don-t-start-without-a-config-file.patch deleted file mode 100644 index 2fb890b..0000000 --- a/SOURCES/0009-RH-don-t-start-without-a-config-file.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 15 Oct 2014 10:39:30 -0500 -Subject: [PATCH] RH: don't start without a config file - -If /etc/multipath.conf doesn't exist, don't start multipathd and blacklist -all devices when running multipath. A completely blank configuration file -is almost never what users want. Also, people may have the multipath -packages installed but don't want to use them. This patch provides a -simple way to disable multipath. Simply removing or renaming -/etc/multipath.conf will keep multipath from doing anything. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/config.c | 15 +++++++++++++++ - libmultipath/config.h | 1 + - multipath/multipath.rules | 1 + - multipathd/multipathd.8 | 2 ++ - multipathd/multipathd.service | 1 + - 5 files changed, 20 insertions(+) - -diff --git a/libmultipath/config.c b/libmultipath/config.c -index 0aef186..6a9340a 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -26,6 +26,7 @@ - #include "devmapper.h" - #include "mpath_cmd.h" - #include "propsel.h" -+#include "version.h" - - static int - hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2) -@@ -745,6 +746,20 @@ load_config (char * file) - goto out; - } - factorize_hwtable(conf->hwtable, builtin_hwtable_size, file); -+ } else { -+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); -+ if (conf->blist_devnode == NULL) { -+ conf->blist_devnode = vector_alloc(); -+ if (!conf->blist_devnode) { -+ condlog(0, "cannot allocate blacklist\n"); -+ goto out; -+ } -+ } -+ if (store_ble(conf->blist_devnode, strdup(".*"), -+ ORIGIN_NO_CONFIG)) { -+ condlog(0, "cannot store default no-config blacklist\n"); -+ goto out; -+ } - } - - conf->processed_main_config = 1; -diff --git a/libmultipath/config.h b/libmultipath/config.h -index 7d0cd9a..d7fb8e2 100644 ---- a/libmultipath/config.h -+++ b/libmultipath/config.h -@@ -9,6 +9,7 @@ - - #define ORIGIN_DEFAULT 0 - #define ORIGIN_CONFIG 1 -+#define ORIGIN_NO_CONFIG 2 - - /* - * In kernel, fast_io_fail == 0 means immediate failure on rport delete. -diff --git a/multipath/multipath.rules b/multipath/multipath.rules -index d658073..b3f54d7 100644 ---- a/multipath/multipath.rules -+++ b/multipath/multipath.rules -@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath" - ENV{nompath}=="?*", GOTO="end_mpath" - IMPORT{cmdline}="multipath" - ENV{multipath}=="off", GOTO="end_mpath" -+TEST!="/etc/multipath.conf", GOTO="end_mpath" - - ENV{DEVTYPE}!="partition", GOTO="test_dev" - IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH" -diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8 -index 94c3f97..ed13efd 100644 ---- a/multipathd/multipathd.8 -+++ b/multipathd/multipathd.8 -@@ -38,6 +38,8 @@ map regains its maximum performance and redundancy. - This daemon executes the external \fBmultipath\fR tool when events occur. - In turn, the multipath tool signals the multipathd daemon when it is done with - devmap reconfiguration, so that it can refresh its failed path list. -+ -+In this Linux distribution, multipathd does not run unless a /etc/multipath.conf file exists. - . - . - .\" ---------------------------------------------------------------------------- -diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index ba24983..17434ce 100644 ---- a/multipathd/multipathd.service -+++ b/multipathd/multipathd.service -@@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service - Before=iscsi.service iscsid.service lvm2-activation-early.service - Before=local-fs-pre.target blk-availability.service - After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service -+ConditionPathExists=/etc/multipath.conf - DefaultDependencies=no - Conflicts=shutdown.target - ConditionKernelCommandLine=!nompath --- -2.7.4 - diff --git a/SOURCES/0009-multipathd-use-update_path_groups-instead-of-reload_.patch b/SOURCES/0009-multipathd-use-update_path_groups-instead-of-reload_.patch new file mode 100644 index 0000000..cc429c5 --- /dev/null +++ b/SOURCES/0009-multipathd-use-update_path_groups-instead-of-reload_.patch @@ -0,0 +1,76 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 21 Feb 2019 17:00:17 -0600 +Subject: [PATCH] multipathd: use update_path_groups instead of reload_map + +reload_map() doesn't do the work to sync the state after reloading the +map. Instead of calling it directly, cli_reload() and uev_update_path() +should call update_path_groups(), which calls reload_map() with all the +necessary syncing. + +Signed-off-by: Benjamin Marzinski +--- + multipathd/cli_handlers.c | 2 +- + multipathd/main.c | 13 ++++++++----- + multipathd/main.h | 2 ++ + 3 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index f95813e..60e17d6 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -877,7 +877,7 @@ cli_reload(void *v, char **reply, int *len, void *data) + return 1; + } + +- return reload_map(vecs, mpp, 0, 1); ++ return update_path_groups(mpp, vecs, 0); + } + + int resize_map(struct multipath *mpp, unsigned long long size, +diff --git a/multipathd/main.c b/multipathd/main.c +index fd83a6a..7a317d9 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1273,10 +1273,13 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + else { + if (ro == 1) + pp->mpp->force_readonly = 1; +- retval = reload_map(vecs, mpp, 0, 1); +- pp->mpp->force_readonly = 0; +- condlog(2, "%s: map %s reloaded (retval %d)", +- uev->kernel, mpp->alias, retval); ++ retval = update_path_groups(mpp, vecs, 0); ++ if (retval == 2) ++ condlog(2, "%s: map removed during reload", pp->dev); ++ else { ++ pp->mpp->force_readonly = 0; ++ condlog(2, "%s: map %s reloaded (retval %d)", uev->kernel, mpp->alias, retval); ++ } + } + } + } +@@ -1832,7 +1835,7 @@ int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh) + + dm_lib_release(); + if (setup_multipath(vecs, mpp) != 0) +- return 1; ++ return 2; + sync_map_state(mpp); + + return 0; +diff --git a/multipathd/main.h b/multipathd/main.h +index 8fd426b..e5c1398 100644 +--- a/multipathd/main.h ++++ b/multipathd/main.h +@@ -43,5 +43,7 @@ int __setup_multipath (struct vectors * vecs, struct multipath * mpp, + int reset); + #define setup_multipath(vecs, mpp) __setup_multipath(vecs, mpp, 1) + int update_multipath (struct vectors *vecs, char *mapname, int reset); ++int update_path_groups(struct multipath *mpp, struct vectors *vecs, ++ int refresh); + + #endif /* MAIN_H */ +-- +2.17.2 + diff --git a/SOURCES/0010-RH-use-rpm-optflags-if-present.patch b/SOURCES/0010-RH-use-rpm-optflags-if-present.patch deleted file mode 100644 index dd221ac..0000000 --- a/SOURCES/0010-RH-use-rpm-optflags-if-present.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 19 Apr 2017 06:10:01 -0500 -Subject: [PATCH] RH: use rpm optflags if present - -Use the passed in optflags when compiling as an RPM, and keep the -default flags as close as possible to the current fedora flags, while -still being generic. - -Signed-off-by: Benjamin Marzinski ---- - Makefile.inc | 24 ++++++++++++++++-------- - 1 file changed, 16 insertions(+), 8 deletions(-) - -diff --git a/Makefile.inc b/Makefile.inc -index b86cba6..70accd7 100644 ---- a/Makefile.inc -+++ b/Makefile.inc -@@ -85,15 +85,23 @@ TEST_CC_OPTION = $(shell \ - echo "$(2)"; \ - fi) - --STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector) - ERROR_DISCARDED_QUALIFIERS := $(call TEST_CC_OPTION,-Werror=discarded-qualifiers,) -- --OPTFLAGS = -O2 -g -pipe -Wall -Wextra -Wformat=2 -Werror=implicit-int \ -- -Werror=implicit-function-declaration -Werror=format-security \ -- -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered \ -- -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \ -- -Wp,-D_FORTIFY_SOURCE=2 $(STACKPROT) \ -- --param=ssp-buffer-size=4 -+ifndef RPM_OPT_FLAGS -+ STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector) -+ OPTFLAGS = -O2 -g -pipe -Wall -Werror=format-security \ -+ -Wp,-D_FORTIFY_SOURCE=2 -fexceptions \ -+ $(STACKPROT) --param=ssp-buffer-size=4 \ -+ -grecord-gcc-switches -+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-hardened-cc1 && echo 1),1) -+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -+ endif -+else -+ OPTFLAGS = $(RPM_OPT_FLAGS) -+endif -+OPTFLAGS += -Wextra -Wstrict-prototypes -Wformat=2 -Werror=implicit-int \ -+ -Werror=implicit-function-declaration -Wno-sign-compare \ -+ -Wno-unused-parameter $(ERROR_DISCARDED_QUALIFIERS) \ -+ -Werror=cast-qual - - CFLAGS := $(OPTFLAGS) -DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \ - -MMD -MP $(CFLAGS) --- -2.7.4 - diff --git a/SOURCES/0010-multipath.conf-add-missing-options-to-man-page.patch b/SOURCES/0010-multipath.conf-add-missing-options-to-man-page.patch new file mode 100644 index 0000000..394952d --- /dev/null +++ b/SOURCES/0010-multipath.conf-add-missing-options-to-man-page.patch @@ -0,0 +1,56 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Tue, 26 Feb 2019 12:22:59 -0600 +Subject: [PATCH] multipath.conf: add missing options to man page + +Signed-off-by: Benjamin Marzinski +--- + multipath/multipath.conf.5 | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index 0fe8461..864d7eb 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -1468,6 +1468,8 @@ section: + .TP + .B uid_attribute + .TP ++.B getuid_callout ++.TP + .B path_selector + .TP + .B path_checker +@@ -1494,6 +1496,8 @@ section: + .TP + .B flush_on_last_del + .TP ++.B user_friendly_names ++.TP + .B retain_attached_hw_handler + .TP + .B detect_prio +@@ -1525,6 +1529,8 @@ section: + .B max_sectors_kb + .TP + .B ghost_delay ++.TP ++.B all_tg_pt + .RE + .PD + .LP +@@ -1604,7 +1610,11 @@ the values are taken from the \fIdevices\fR or \fIdefaults\fR sections: + .TP + .B skip_kpartx + .TP ++.B max_sectors_kb ++.TP + .B ghost_delay ++.TP ++.B all_tg_pt + .RE + .PD + .LP +-- +2.17.2 + diff --git a/SOURCES/0011-RH-add-mpathconf.patch b/SOURCES/0011-RH-add-mpathconf.patch deleted file mode 100644 index cfb9ed9..0000000 --- a/SOURCES/0011-RH-add-mpathconf.patch +++ /dev/null @@ -1,667 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 16 Oct 2014 15:49:01 -0500 -Subject: [PATCH] RH: add mpathconf - -mpathconf is a program (largely based on lvmcomf) to help users -configure /etc/multipath.conf and enable or disable multipathing. It -has a couple of built-in options that can be set directly from the -command line. But, mostly it is used to get a multipath.conf file -with the OS defaults, and to enable and disable multipathing via -a single command. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/config.c | 2 + - multipath/Makefile | 5 + - multipath/mpathconf | 464 ++++++++++++++++++++++++++++++++++++++++++++++++++ - multipath/mpathconf.8 | 119 +++++++++++++ - 4 files changed, 590 insertions(+) - create mode 100644 multipath/mpathconf - create mode 100644 multipath/mpathconf.8 - -diff --git a/libmultipath/config.c b/libmultipath/config.c -index 6a9340a..bfd07e3 100644 ---- a/libmultipath/config.c -+++ b/libmultipath/config.c -@@ -748,6 +748,8 @@ load_config (char * file) - factorize_hwtable(conf->hwtable, builtin_hwtable_size, file); - } else { - condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); -+ condlog(0, "You can run \"/sbin/mpathconf --enable\" to create"); -+ condlog(0, "/etc/multipath.conf. See man mpathconf(8) for more details"); - if (conf->blist_devnode == NULL) { - conf->blist_devnode = vector_alloc(); - if (!conf->blist_devnode) { -diff --git a/multipath/Makefile b/multipath/Makefile -index b9bbb3c..e720c7f 100644 ---- a/multipath/Makefile -+++ b/multipath/Makefile -@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so - $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS) - $(GZIP) $(EXEC).8 > $(EXEC).8.gz - $(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz -+ $(GZIP) mpathconf.8 > mpathconf.8.gz - - install: - $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) - $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ -+ $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/ - $(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) - $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) - $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules -@@ -29,13 +31,16 @@ install: - $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir) - $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) - $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir) -+ $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(man8dir) - - uninstall: - $(RM) $(DESTDIR)$(bindir)/$(EXEC) - $(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules - $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules -+ $(RM) $(DESTDIR)$(bindir)/mpathconf - $(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz - $(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz -+ $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz - - clean: dep_clean - $(RM) core *.o $(EXEC) *.gz -diff --git a/multipath/mpathconf b/multipath/mpathconf -new file mode 100644 -index 0000000..e839134 ---- /dev/null -+++ b/multipath/mpathconf -@@ -0,0 +1,464 @@ -+#!/bin/bash -+# -+# Copyright (C) 2010 Red Hat, Inc. All rights reserved. -+# -+# This file is part of the device-mapper-multipath package. -+# -+# This copyrighted material is made available to anyone wishing to use, -+# modify, copy, or redistribute it subject to the terms and conditions -+# of the GNU General Public License v.2. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software Foundation, -+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ -+# -+# Simple editting of /etc/multipath.conf -+# This program was largely ripped off from lvmconf -+# -+ -+unset ENABLE FIND FRIENDLY MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST -+ -+DEFAULT_CONFIG="# device-mapper-multipath configuration file -+ -+# For a complete list of the default configuration values, run either: -+# # multipath -t -+# or -+# # multipathd show config -+ -+# For a list of configuration options with descriptions, see the -+# multipath.conf man page. -+ -+defaults { -+ user_friendly_names yes -+ find_multipaths yes -+} -+ -+blacklist_exceptions { -+ property \"(SCSI_IDENT_|ID_WWN)\" -+}" -+ -+CONFIGFILE="/etc/multipath.conf" -+OUTPUTFILE="/etc/multipath.conf" -+MULTIPATHDIR="/etc/multipath" -+TMPFILE="/etc/multipath/.multipath.conf.tmp" -+WWIDS=0 -+ -+function usage -+{ -+ echo "usage: $0 " -+ echo "" -+ echo "Commands:" -+ echo "Enable: --enable " -+ echo "Disable: --disable" -+ echo "Only allow certain wwids (instead of enable): --allow " -+ echo "Set user_friendly_names (Default y): --user_friendly_names " -+ echo "Set find_multipaths (Default y): --find_multipaths " -+ echo "Load the dm-multipath modules on enable (Default y): --with_module " -+ echo "start/stop/reload multipathd (Default n): --with_multipathd " -+ echo "select output file (Default /etc/multipath.conf): --outfile " -+ 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 -+ while [ -n "$1" -a -n "$2" ]; do -+ MAJOR=$(echo $1 | tr -d '(,') -+ MINOR=$(echo $2 | tr -d ')') -+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null` -+ if [ -n "$UUID" ] ; then -+ set_dm_wwid $UUID -+ fi -+ shift 2 -+ done -+} -+ -+function set_dm_wwid -+{ -+ if [[ "$1" =~ ^part[[:digit:]]+-mpath- ]] ; then -+ add_wwid "${1##part*-mpath-}" -+ elif [[ "$1" =~ ^mpath- ]] ; then -+ add_wwid "${1##mpath-}" -+ else -+ get_dm_deps `dmsetup deps -u $1` -+ fi -+} -+ -+function set_wwid -+{ -+ UUID="" -+ if [[ "$1" =~ ^[[:digit:]]+:[[:digit:]]+$ ]] ; then -+ MAJOR=${1%%:*} -+ MINOR=${1##*:} -+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null` -+ else -+ UUID=`dmsetup info -c --noheadings -o uuid $1 2> /dev/null` -+ fi -+ if [ -n "$UUID" ] ; then -+ set_dm_wwid $UUID -+ else -+ add_wwid "$1" -+ fi -+} -+ -+function parse_args -+{ -+ while [ -n "$1" ]; do -+ case $1 in -+ --enable) -+ ENABLE=1 -+ shift -+ ;; -+ --disable) -+ ENABLE=0 -+ shift -+ ;; -+ --allow) -+ ENABLE=2 -+ if [ -n "$2" ]; then -+ set_wwid $2 -+ shift 2 -+ else -+ usage -+ exit 1 -+ fi -+ ;; -+ --user_friendly_names) -+ if [ -n "$2" ]; then -+ FRIENDLY=$2 -+ shift 2 -+ else -+ usage -+ exit 1 -+ fi -+ ;; -+ --find_multipaths) -+ if [ -n "$2" ]; then -+ FIND=$2 -+ shift 2 -+ else -+ usage -+ exit 1 -+ fi -+ ;; -+ --with_module) -+ if [ -n "$2" ]; then -+ MODULE=$2 -+ shift 2 -+ else -+ usage -+ exit 1 -+ fi -+ ;; -+ --with_multipathd) -+ if [ -n "$2" ]; then -+ MULTIPATHD=$2 -+ shift 2 -+ else -+ usage -+ exit 1 -+ fi -+ ;; -+ --outfile) -+ if [ -n "$2" ]; then -+ OUTPUTFILE=$2 -+ HAVE_OUTFILE=1 -+ shift 2 -+ else -+ usage -+ exit 1 -+ fi -+ ;; -+ *) -+ usage -+ exit -+ esac -+ done -+} -+ -+function validate_args -+{ -+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$MODULE" ]; then -+ echo "ignoring extra parameters on disable" -+ FRIENDLY="" -+ FIND="" -+ MODULE="" -+ fi -+ if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then -+ echo "--user_friendly_names must be either 'y' or 'n'" -+ exit 1 -+ fi -+ if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then -+ echo "--find_multipaths must be either 'y' or 'n'" -+ exit 1 -+ fi -+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" ]; then -+ SHOW_STATUS=1 -+ fi -+ if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then -+ echo "--with_module must be either 'y' or 'n'" -+ exit 1 -+ fi -+ if [ -n "$MULTIPATHD" ] && [ "$MULTIPATHD" != "y" -a "$MULTIPATHD" != "n" ]; then -+ echo "--with_multipathd must be either 'y' or 'n'" -+ exit 1 -+ fi -+ if [ "$ENABLE" = 2 -a -z "$HAVE_OUTFILE" ]; then -+ echo "Because --allow makes changes that cannot be automatically reversed," -+ echo "you must set --outfile when you set --allow" -+ exit 1 -+ fi -+} -+ -+function add_blacklist_exceptions -+{ -+ INDEX=0 -+ while [ "$INDEX" -lt "$WWIDS" ] ; do -+ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\ -+ wwid '"\"${WWID_LIST[$INDEX]}\""' -+' $TMPFILE -+ ((INDEX++)) -+ done -+} -+ -+umask 0077 -+ -+parse_args "$@" -+ -+validate_args -+ -+if [ ! -d "$MULTIPATHDIR" ]; then -+ echo "/etc/multipath/ does not exist. failing" -+ exit 1 -+fi -+ -+rm $TMPFILE 2> /dev/null -+echo "$DEFAULT_CONFIG" > $TMPFILE -+if [ -f "$CONFIGFILE" ]; then -+ cp $CONFIGFILE $TMPFILE -+fi -+ -+if grep -q "^blacklist[[:space:]]*{" $TMPFILE ; then -+ HAVE_BLACKLIST=1 -+fi -+ -+if grep -q "^blacklist_exceptions[[:space:]]*{" $TMPFILE ; then -+ HAVE_EXCEPTIONS=1 -+fi -+ -+if grep -q "^defaults[[:space:]]*{" $TMPFILE ; then -+ HAVE_DEFAULTS=1 -+fi -+ -+if [ -z "$MODULE" -o "$MODULE" = "y" ]; then -+ if lsmod | grep -q "dm_multipath" ; then -+ HAVE_MODULE=1 -+ else -+ HAVE_MODULE=0 -+ fi -+fi -+ -+if [ "$MULTIPATHD" = "y" ]; then -+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then -+ HAVE_MULTIPATHD=1 -+ else -+ HAVE_MULTIPATHD=0 -+ fi -+fi -+ -+if [ "$HAVE_BLACKLIST" = "1" ]; then -+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then -+ HAVE_DISABLE=1 -+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then -+ HAVE_DISABLE=0 -+ fi -+fi -+ -+if [ "$HAVE_BLACKLIST" = "1" ]; then -+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then -+ HAVE_WWID_DISABLE=1 -+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then -+ HAVE_WWID_DISABLE=0 -+ fi -+fi -+ -+if [ "$HAVE_DEFAULTS" = "1" ]; then -+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then -+ HAVE_FIND=1 -+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then -+ HAVE_FIND=0 -+ fi -+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then -+ HAVE_FRIENDLY=1 -+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then -+ HAVE_FRIENDLY=0 -+ fi -+fi -+ -+if [ -n "$SHOW_STATUS" ]; then -+ if [ -z "$HAVE_DISABLE" -o "$HAVE_DISABLE" = 0 ]; then -+ echo "multipath is enabled" -+ else -+ echo "multipath is disabled" -+ fi -+ if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then -+ echo "find_multipaths is disabled" -+ else -+ echo "find_multipaths is enabled" -+ fi -+ if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then -+ echo "user_friendly_names is disabled" -+ else -+ echo "user_friendly_names is enabled" -+ fi -+ if [ -n "$HAVE_MODULE" ]; then -+ if [ "$HAVE_MODULE" = 1 ]; then -+ echo "dm_multipath module is loaded" -+ else -+ echo "dm_multipath module is not loaded" -+ fi -+ fi -+ if [ -z "$HAVE_MULTIPATHD" ]; then -+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then -+ HAVE_MULTIPATHD=1 -+ else -+ HAVE_MULTIPATHD=0 -+ fi -+ fi -+ if [ "$HAVE_MULTIPATHD" = 1 ]; then -+ echo "multipathd is running" -+ else -+ echo "multipathd is not running" -+ fi -+ exit 0 -+fi -+ -+if [ -z "$HAVE_BLACKLIST" ]; then -+ cat >> $TMPFILE <<- _EOF_ -+ -+blacklist { -+} -+_EOF_ -+fi -+ -+if [ -z "$HAVE_DEFAULTS" ]; then -+ cat >> $TMPFILE <<- _EOF_ -+ -+defaults { -+} -+_EOF_ -+fi -+ -+if [ "$ENABLE" = 2 ]; then -+ if [ "$HAVE_DISABLE" = 1 ]; then -+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE -+ fi -+ if [ -z "$HAVE_WWID_DISABLE" ]; then -+ sed -i '/^blacklist[[:space:]]*{/ a\ -+ wwid ".*" -+' $TMPFILE -+ elif [ "$HAVE_WWID_DISABLE" = 0 ]; then -+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE -+ fi -+ if [ "$HAVE_EXCEPTIONS" = 1 ]; then -+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE -+ else -+ cat >> $TMPFILE <<- _EOF_ -+ -+blacklist_exceptions { -+} -+_EOF_ -+ fi -+ add_blacklist_exceptions -+elif [ "$ENABLE" = 1 ]; then -+ if [ "$HAVE_DISABLE" = 1 ]; then -+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE -+ fi -+elif [ "$ENABLE" = 0 ]; then -+ if [ -z "$HAVE_DISABLE" ]; then -+ sed -i '/^blacklist[[:space:]]*{/ a\ -+ devnode ".*" -+' $TMPFILE -+ elif [ "$HAVE_DISABLE" = 0 ]; then -+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE -+ fi -+fi -+ -+if [ "$FIND" = "n" ]; then -+ if [ "$HAVE_FIND" = 1 ]; then -+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE -+ CHANGED_CONFIG=1 -+ fi -+elif [ "$FIND" = "y" ]; then -+ if [ -z "$HAVE_FIND" ]; then -+ sed -i '/^defaults[[:space:]]*{/ a\ -+ find_multipaths yes -+' $TMPFILE -+ CHANGED_CONFIG=1 -+ elif [ "$HAVE_FIND" = 0 ]; then -+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE -+ CHANGED_CONFIG=1 -+ fi -+fi -+ -+if [ "$FRIENDLY" = "n" ]; then -+ if [ "$HAVE_FRIENDLY" = 1 ]; then -+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE -+ CHANGED_CONFIG=1 -+ fi -+elif [ "$FRIENDLY" = "y" ]; then -+ if [ -z "$HAVE_FRIENDLY" ]; then -+ sed -i '/^defaults[[:space:]]*{/ a\ -+ user_friendly_names yes -+' $TMPFILE -+ CHANGED_CONFIG=1 -+ elif [ "$HAVE_FRIENDLY" = 0 ]; then -+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE -+ CHANGED_CONFIG=1 -+ fi -+fi -+ -+if [ -f "$OUTPUTFILE" ]; then -+ cp $OUTPUTFILE $OUTPUTFILE.old -+ if [ $? != 0 ]; then -+ echo "failed to backup old config file, $OUTPUTFILE not updated" -+ exit 1 -+ fi -+fi -+ -+cp $TMPFILE $OUTPUTFILE -+if [ $? != 0 ]; then -+ echo "failed to copy new config file into place, check $OUTPUTFILE is still OK" -+ exit 1 -+fi -+ -+rm -f $TMPFILE -+ -+if [ "$ENABLE" = 1 ]; then -+ if [ "$HAVE_MODULE" = 0 ]; then -+ modprobe dm_multipath -+ fi -+ if [ "$HAVE_MULTIPATHD" = 0 ]; then -+ systemctl start multipathd.service -+ fi -+elif [ "$ENABLE" = 0 ]; then -+ if [ "$HAVE_MULTIPATHD" = 1 ]; then -+ systemctl stop multipathd.service -+ fi -+elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then -+ systemctl reload multipathd.service -+fi -diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8 -new file mode 100644 -index 0000000..5b7ae0c ---- /dev/null -+++ b/multipath/mpathconf.8 -@@ -0,0 +1,119 @@ -+.TH MPATHCONF 8 "June 2010" "" "Linux Administrator's Manual" -+.SH NAME -+mpathconf - A tool for configuring device-mapper-multipath -+.SH SYNOPSIS -+.B mpathconf -+.RB [\| commands \|] -+.RB [\| options \|] -+.SH DESCRIPTION -+.B mpathconf -+is a utility that creates or modifies -+.B /etc/multipath.conf. -+It can enable or disable multipathing and configure some common options. -+.B mpathconf -+can also load the -+.B dm_multipath -+module, start and stop the -+.B multipathd -+daemon, and configure the -+.B multipathd -+service to start automatically or not. If -+.B mpathconf -+is called with no commands, it will display the current configuration, but -+will not create of modify -+.B /etc/multipath.conf -+ -+The default options for mpathconf are -+.B --with_module -+The -+.B --with_multipathd -+option is not set by default. Enabling multipathing will load the -+.B dm_multipath -+module but it will not immediately start it. This is so -+that users can manually edit their config file if necessary, before starting -+.B multipathd. -+ -+If -+.B /etc/multipath.conf -+already exists, mpathconf will edit it. If it does not exist, mpathconf will -+create a default file with -+.B user_friendly_names -+and -+.B find_multipaths -+set. To disable these, use the -+.B --user_friendly_names n -+and -+.B --find_multipaths n -+options -+.SH COMMANDS -+.TP -+.B --enable -+Removes any line that blacklists all device nodes from the -+.B /etc/multipath.conf -+blacklist section. Also, creates -+.B /etc/multipath.conf -+if it doesn't exist. -+.TP -+.B --disable -+Adds a line that blacklists all device nodes to the -+.B /etc/multipath.conf -+blacklist section. If no blacklist section exists, it will create one. -+.TP -+.B --allow \fB\fP -+Modifies the \fB/etc/multipath/conf\fP blacklist to blacklist all -+wwids and the blacklist_exceptions to whitelist \fB\fP. \fB\fP -+can be in the form of MAJOR:MINOR, a wwid, or the name of a device-mapper -+device, either a multipath device, or any device on stacked on top of one or -+more multipath devices. This command can be used multiple times to allow -+multiple devices. \fBNOTE:\fP This action will create a configuration file that -+mpathconf will not be able to revert back to its previous state. Because -+of this, \fB--outfile\fP is required when using \fB--allow\fP. -+.TP -+.B --user_friendly_name \fP { \fBy\fP | \fBn\fP } -+If set to \fBy\fP, this adds the line -+.B user_friendly_names yes -+to the -+.B /etc/multipath.conf -+defaults section. If set to \fBn\fP, this removes the line, if present. This -+command can be used along with any other command. -+.TP -+.B --find_multipaths\fP { \fBy\fP | \fBn\fP } -+If set to \fBy\fP, this adds the line -+.B find_multipaths yes -+to the -+.B /etc/multipath.conf -+defaults section. If set to \fBn\fP, this removes the line, if present. This -+command can be used aldong with any other command. -+.TP -+.B --outfile \fB\fP -+Write the resulting multipath configuration to \fB\fP instead of -+\fB/etc/multipath.conf\fP. -+.SH OPTIONS -+.TP -+.B --with_module\fP { \fBy\fP | \fBn\fP } -+If set to \fBy\fP, this runs -+.B modprobe dm_multipath -+to install the multipath modules. This option only works with the -+.B --enable -+command. This option is set to \fBy\fP by default. -+.TP -+.B --with_multipathd { \fBy\fP | \fBn\fP } -+If set to \fBy\fP, this runs -+.B service multipathd start -+to start the multipathd daemon on \fB--enable\fP, -+.B service multipathd stop -+to stop the multipathd daemon on \fB--disable\fP, and -+.B service multipathd reload -+to reconfigure multipathd on \fB--user_frindly_names\fP and -+\fB--find_multipaths\fP. -+This option is set to \fBn\fP by default. -+.SH FILES -+.BR /etc/multipath.conf -+.SH "SEE ALSO" -+.BR multipath.conf (5), -+.BR modprobe (8), -+.BR multipath (8), -+.BR multipathd (8), -+.BR service (8), -+.SH AUTHOR -+Benjamin Marzinski --- -2.7.4 - diff --git a/SOURCES/0011-libmultipath-add-get_uid-fallback-code-for-NVMe-devi.patch b/SOURCES/0011-libmultipath-add-get_uid-fallback-code-for-NVMe-devi.patch new file mode 100644 index 0000000..31cabca --- /dev/null +++ b/SOURCES/0011-libmultipath-add-get_uid-fallback-code-for-NVMe-devi.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 7 Mar 2019 16:14:35 -0600 +Subject: [PATCH] libmultipath: add get_uid fallback code for NVMe devices + +If multipath can't get the uid for NVMe devices from udev, it can get it +directly from sysfs. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 49 ++++++++++++++++++++++++++++------------ + 1 file changed, 34 insertions(+), 15 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 28c00e5..bece67c 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1754,8 +1754,8 @@ get_vpd_uid(struct path * pp) + return get_vpd_sysfs(parent, 0x83, pp->wwid, WWID_SIZE); + } + +-static ssize_t scsi_uid_fallback(struct path *pp, int path_state, +- const char **origin, ssize_t old_len) ++static ssize_t uid_fallback(struct path *pp, int path_state, ++ const char **origin, ssize_t old_len) + { + ssize_t len = old_len; + int retrigger; +@@ -1764,17 +1764,36 @@ static ssize_t scsi_uid_fallback(struct path *pp, int path_state, + conf = get_multipath_config(); + retrigger = conf->retrigger_tries; + put_multipath_config(conf); +- if (pp->retriggers >= retrigger && +- !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) { +- len = get_vpd_uid(pp); +- *origin = "sysfs"; +- pp->uid_attribute = NULL; +- if (len < 0 && path_state == PATH_UP) { +- condlog(1, "%s: failed to get sysfs uid: %s", +- pp->dev, strerror(-len)); +- len = get_vpd_sgio(pp->fd, 0x83, pp->wwid, +- WWID_SIZE); +- *origin = "sgio"; ++ if (pp->retriggers >= retrigger) { ++ if (pp->bus == SYSFS_BUS_SCSI && ++ !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) { ++ len = get_vpd_uid(pp); ++ *origin = "sysfs"; ++ pp->uid_attribute = NULL; ++ if (len < 0 && path_state == PATH_UP) { ++ condlog(1, "%s: failed to get sysfs uid: %s", ++ pp->dev, strerror(-len)); ++ len = get_vpd_sgio(pp->fd, 0x83, pp->wwid, ++ WWID_SIZE); ++ *origin = "sgio"; ++ } ++ } else if (pp->bus == SYSFS_BUS_NVME) { ++ char value[256]; ++ len = sysfs_attr_get_value(pp->udev, "wwid", value, ++ sizeof(value)); ++ if (len <= 0) ++ return -1; ++ len = strlcpy(pp->wwid, value, WWID_SIZE); ++ if (len >= WWID_SIZE) { ++ len = fix_broken_nvme_wwid(pp, value, ++ WWID_SIZE); ++ if (len > 0) ++ return len; ++ condlog(0, "%s: wwid overflow", pp->dev); ++ len = WWID_SIZE; ++ } ++ *origin = "sysfs"; ++ pp->uid_attribute = NULL; + } + } + return len; +@@ -1827,8 +1846,8 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev) + len = get_vpd_uid(pp); + origin = "sysfs"; + } +- if (len <= 0 && pp->bus == SYSFS_BUS_SCSI) +- len = scsi_uid_fallback(pp, path_state, &origin, len); ++ if (len <= 0) ++ len = uid_fallback(pp, path_state, &origin, len); + } + if ( len < 0 ) { + condlog(1, "%s: failed to get %s uid: %s", +-- +2.17.2 + diff --git a/SOURCES/0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/SOURCES/0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch deleted file mode 100644 index d7c4c8a..0000000 --- a/SOURCES/0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +++ /dev/null @@ -1,167 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Fri, 17 Oct 2014 11:20:34 -0500 -Subject: [PATCH] RH: add wwids from kernel cmdline mpath.wwids with -A - -This patch adds another option to multipath, "-A", which reads -/proc/cmdline for mpath.wwid= options, and adds any wwids it finds -to /etc/multipath/wwids. While this isn't usually important during -normal operation, since these wwids should already be added, it can be -helpful during installation, to make sure that multipath can claim -devices as its own, before LVM or something else makes use of them. The -patch also execs "/sbin/multipath -A" before running multipathd in -multipathd.service - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/wwids.c | 44 +++++++++++++++++++++++++++++++++++++++++++ - libmultipath/wwids.h | 1 + - multipath/main.c | 10 ++++++++-- - multipath/multipath.8 | 5 ++++- - multipathd/multipathd.service | 1 + - 5 files changed, 58 insertions(+), 3 deletions(-) - -diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c -index 53e7951..39e08cd 100644 ---- a/libmultipath/wwids.c -+++ b/libmultipath/wwids.c -@@ -443,3 +443,47 @@ int op ## _wwid(const char *wwid) \ - declare_failed_wwid_op(is_failed, false) - declare_failed_wwid_op(mark_failed, true) - declare_failed_wwid_op(unmark_failed, true) -+ -+int remember_cmdline_wwid(void) -+{ -+ FILE *f = NULL; -+ char buf[LINE_MAX], *next, *ptr; -+ int ret = 0; -+ -+ f = fopen("/proc/cmdline", "re"); -+ if (!f) { -+ condlog(0, "can't open /proc/cmdline : %s", strerror(errno)); -+ return -1; -+ } -+ -+ if (!fgets(buf, sizeof(buf), f)) { -+ if (ferror(f)) -+ condlog(0, "read of /proc/cmdline failed : %s", -+ strerror(errno)); -+ else -+ condlog(0, "couldn't read /proc/cmdline"); -+ fclose(f); -+ return -1; -+ } -+ fclose(f); -+ next = buf; -+ while((ptr = strstr(next, "mpath.wwid="))) { -+ ptr += 11; -+ next = strpbrk(ptr, " \t\n"); -+ if (next) { -+ *next = '\0'; -+ next++; -+ } -+ if (strlen(ptr)) { -+ if (remember_wwid(ptr) != 0) -+ ret = -1; -+ } -+ else { -+ condlog(0, "empty mpath.wwid kernel command line option"); -+ ret = -1; -+ } -+ if (!next) -+ break; -+ } -+ return ret; -+} -diff --git a/libmultipath/wwids.h b/libmultipath/wwids.h -index 0c6ee54..e32a0b0 100644 ---- a/libmultipath/wwids.h -+++ b/libmultipath/wwids.h -@@ -17,6 +17,7 @@ int remember_wwid(char *wwid); - int check_wwids_file(char *wwid, int write_wwid); - int remove_wwid(char *wwid); - int replace_wwids(vector mp); -+int remember_cmdline_wwid(void); - - enum { - WWID_IS_NOT_FAILED = 0, -diff --git a/multipath/main.c b/multipath/main.c -index ffa5b22..ccb6091 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -120,7 +120,7 @@ usage (char * progname) - { - fprintf (stderr, VERSION_STRING); - fprintf (stderr, "Usage:\n"); -- fprintf (stderr, " %s [-a|-c|-w|-W] [-d] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); -+ fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); - fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [-R num] [dev]\n", progname); - fprintf (stderr, " %s -F [-v lvl] [-R num]\n", progname); - fprintf (stderr, " %s [-t|-T]\n", progname); -@@ -134,6 +134,8 @@ usage (char * progname) - " -f flush a multipath device map\n" - " -F flush all multipath device maps\n" - " -a add a device wwid to the wwids file\n" -+ " -A add devices from kernel command line mpath.wwids\n" -+ " parameters to wwids file\n" - " -c check if a device should be a path in a multipath device\n" - " -C check if a multipath device has usable paths\n" - " -q allow queue_if_no_path when multipathd is not running\n" -@@ -868,7 +870,7 @@ main (int argc, char *argv[]) - exit(1); - multipath_conf = conf; - conf->retrigger_tries = 0; -- while ((arg = getopt(argc, argv, ":adcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) { -+ while ((arg = getopt(argc, argv, ":aAdcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) { - switch(arg) { - case 1: printf("optarg : %s\n",optarg); - break; -@@ -938,6 +940,10 @@ main (int argc, char *argv[]) - case 'T': - cmd = CMD_DUMP_CONFIG; - break; -+ case 'A': -+ if (remember_cmdline_wwid() != 0) -+ exit(1); -+ exit(0); - case 'h': - usage(argv[0]); - exit(0); -diff --git a/multipath/multipath.8 b/multipath/multipath.8 -index b5e5292..5bd5229 100644 ---- a/multipath/multipath.8 -+++ b/multipath/multipath.8 -@@ -25,7 +25,7 @@ multipath \- Device mapper target autoconfig. - .RB [\| \-b\ \c - .IR bindings_file \|] - .RB [\| \-d \|] --.RB [\| \-h | \-l | \-ll | \-f | \-t | \-T | \-F | \-B | \-c | \-C | \-q | \-r | \-i | \-a | \-u | \-U | \-w | \-W \|] -+.RB [\| \-h | \-l | \-ll | \-f | \-t | \-T | \-F | \-B | \-c | \-C | \-q | \-r | \-i | \-a | \-A | \-u | \-U | \-w | \-W \|] - .RB [\| \-p\ \c - .IR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|] - .RB [\| \-R\ \c -@@ -141,6 +141,9 @@ Add the WWID for the specified device to the WWIDs file. - Check if the device specified in the program environment should be - a path in a multipath device. - . -+.B \-A -+add wwids from any kernel command line mpath.wwid parameters to the wwids file -+. - .TP - .B \-U - Check if the device specified in the program environment is a multipath device -diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service -index 17434ce..0fbcc46 100644 ---- a/multipathd/multipathd.service -+++ b/multipathd/multipathd.service -@@ -15,6 +15,7 @@ Type=notify - NotifyAccess=main - LimitCORE=infinity - ExecStartPre=-/sbin/modprobe -a scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm-multipath -+ExecStartPre=-/sbin/multipath -A - ExecStart=/sbin/multipathd -d -s - ExecReload=/sbin/multipathd reconfigure - TasksMax=infinity --- -2.7.4 - diff --git a/SOURCES/0012-libmulitpath-cleanup-uid_fallback-code.patch b/SOURCES/0012-libmulitpath-cleanup-uid_fallback-code.patch new file mode 100644 index 0000000..c47f70a --- /dev/null +++ b/SOURCES/0012-libmulitpath-cleanup-uid_fallback-code.patch @@ -0,0 +1,129 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 27 Mar 2019 12:21:57 -0500 +Subject: [PATCH] libmulitpath: cleanup uid_fallback code + +Instead of always calling uid_fallback() if the configured method to get +the uid failed, get_uid now checks if the path supports fallbacks and if +all the retriggers have occurred. If so, it calls uid_fallback(), which +just attempts to get the uid using the appropriate fallback method. None +of these changes should make the code function any differently. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 85 ++++++++++++++++++++++------------------ + 1 file changed, 46 insertions(+), 39 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index bece67c..3ec60d6 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1755,50 +1755,50 @@ get_vpd_uid(struct path * pp) + } + + static ssize_t uid_fallback(struct path *pp, int path_state, +- const char **origin, ssize_t old_len) ++ const char **origin) + { +- ssize_t len = old_len; +- int retrigger; +- struct config *conf; +- +- conf = get_multipath_config(); +- retrigger = conf->retrigger_tries; +- put_multipath_config(conf); +- if (pp->retriggers >= retrigger) { +- if (pp->bus == SYSFS_BUS_SCSI && +- !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) { +- len = get_vpd_uid(pp); +- *origin = "sysfs"; +- pp->uid_attribute = NULL; +- if (len < 0 && path_state == PATH_UP) { +- condlog(1, "%s: failed to get sysfs uid: %s", +- pp->dev, strerror(-len)); +- len = get_vpd_sgio(pp->fd, 0x83, pp->wwid, ++ ssize_t len = -1; ++ ++ if (pp->bus == SYSFS_BUS_SCSI && ++ !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) { ++ len = get_vpd_uid(pp); ++ *origin = "sysfs"; ++ pp->uid_attribute = NULL; ++ if (len < 0 && path_state == PATH_UP) { ++ condlog(1, "%s: failed to get sysfs uid: %s", ++ pp->dev, strerror(-len)); ++ len = get_vpd_sgio(pp->fd, 0x83, pp->wwid, ++ WWID_SIZE); ++ *origin = "sgio"; ++ } ++ } else if (pp->bus == SYSFS_BUS_NVME) { ++ char value[256]; ++ len = sysfs_attr_get_value(pp->udev, "wwid", value, ++ sizeof(value)); ++ if (len <= 0) ++ return -1; ++ len = strlcpy(pp->wwid, value, WWID_SIZE); ++ if (len >= WWID_SIZE) { ++ len = fix_broken_nvme_wwid(pp, value, + WWID_SIZE); +- *origin = "sgio"; +- } +- } else if (pp->bus == SYSFS_BUS_NVME) { +- char value[256]; +- len = sysfs_attr_get_value(pp->udev, "wwid", value, +- sizeof(value)); +- if (len <= 0) +- return -1; +- len = strlcpy(pp->wwid, value, WWID_SIZE); +- if (len >= WWID_SIZE) { +- len = fix_broken_nvme_wwid(pp, value, +- WWID_SIZE); +- if (len > 0) +- return len; +- condlog(0, "%s: wwid overflow", pp->dev); +- len = WWID_SIZE; +- } +- *origin = "sysfs"; +- pp->uid_attribute = NULL; ++ if (len > 0) ++ return len; ++ condlog(0, "%s: wwid overflow", pp->dev); ++ len = WWID_SIZE; + } ++ *origin = "sysfs"; ++ pp->uid_attribute = NULL; + } + return len; + } + ++static int has_uid_fallback(struct path *pp) ++{ ++ return ((pp->bus == SYSFS_BUS_SCSI && ++ !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) || ++ pp->bus == SYSFS_BUS_NVME); ++} ++ + int + get_uid (struct path * pp, int path_state, struct udev_device *udev) + { +@@ -1846,8 +1846,15 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev) + len = get_vpd_uid(pp); + origin = "sysfs"; + } +- if (len <= 0) +- len = uid_fallback(pp, path_state, &origin, len); ++ if (len <= 0 && has_uid_fallback(pp)) { ++ int retrigger_tries; ++ ++ conf = get_multipath_config(); ++ retrigger_tries = conf->retrigger_tries; ++ put_multipath_config(conf); ++ if (pp->retriggers >= retrigger_tries) ++ len = uid_fallback(pp, path_state, &origin); ++ } + } + if ( len < 0 ) { + condlog(1, "%s: failed to get %s uid: %s", +-- +2.17.2 + diff --git a/SOURCES/0013-RH-warn-on-invalid-regex-instead-of-failing.patch b/SOURCES/0013-RH-warn-on-invalid-regex-instead-of-failing.patch deleted file mode 100644 index aa64be1..0000000 --- a/SOURCES/0013-RH-warn-on-invalid-regex-instead-of-failing.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 6 Nov 2017 21:39:28 -0600 -Subject: [PATCH] RH: warn on invalid regex instead of failing - -multipath.conf used to allow "*" as a match everything regular expression, -instead of requiring ".*". Instead of erroring when the old style -regular expressions are used, it should print a warning and convert -them. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/dict.c | 27 +++++++++++++++++++++------ - libmultipath/parser.c | 13 +++++++++++++ - libmultipath/parser.h | 1 + - 3 files changed, 35 insertions(+), 6 deletions(-) - -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index bf4701e..9d63d26 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -58,6 +58,21 @@ set_str(vector strvec, void *ptr) - } - - static int -+set_regex(vector strvec, void *ptr) -+{ -+ char **str_ptr = (char **)ptr; -+ -+ if (*str_ptr) -+ FREE(*str_ptr); -+ *str_ptr = set_regex_value(strvec); -+ -+ if (!*str_ptr) -+ return 1; -+ -+ return 0; -+} -+ -+static int - set_yes_no(vector strvec, void *ptr) - { - char * buff; -@@ -1336,7 +1351,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \ - if (!conf->option) \ - return 1; \ - \ -- buff = set_value(strvec); \ -+ buff = set_regex_value(strvec); \ - if (!buff) \ - return 1; \ - \ -@@ -1352,7 +1367,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \ - if (!conf->option) \ - return 1; \ - \ -- buff = set_value(strvec); \ -+ buff = set_regex_value(strvec); \ - if (!buff) \ - return 1; \ - \ -@@ -1455,16 +1470,16 @@ device_handler(struct config *conf, vector strvec) - return 0; - } - --declare_hw_handler(vendor, set_str) -+declare_hw_handler(vendor, set_regex) - declare_hw_snprint(vendor, print_str) - --declare_hw_handler(product, set_str) -+declare_hw_handler(product, set_regex) - declare_hw_snprint(product, print_str) - --declare_hw_handler(revision, set_str) -+declare_hw_handler(revision, set_regex) - declare_hw_snprint(revision, print_str) - --declare_hw_handler(bl_product, set_str) -+declare_hw_handler(bl_product, set_regex) - declare_hw_snprint(bl_product, print_str) - - declare_hw_handler(hwhandler, set_str) -diff --git a/libmultipath/parser.c b/libmultipath/parser.c -index 92ef7cf..4289336 100644 ---- a/libmultipath/parser.c -+++ b/libmultipath/parser.c -@@ -384,6 +384,19 @@ set_value(vector strvec) - return alloc; - } - -+void * -+set_regex_value(vector strvec) -+{ -+ char *buff = set_value(strvec); -+ -+ if (buff && strcmp("*", buff) == 0) { -+ condlog(0, "Invalid regular expression \"*\" in multipath.conf. Using \".*\""); -+ FREE(buff); -+ return strdup(".*"); -+ } -+ return buff; -+} -+ - /* non-recursive configuration stream handler */ - static int kw_level = 0; - -diff --git a/libmultipath/parser.h b/libmultipath/parser.h -index 62906e9..b791705 100644 ---- a/libmultipath/parser.h -+++ b/libmultipath/parser.h -@@ -77,6 +77,7 @@ extern void dump_keywords(vector keydump, int level); - extern void free_keywords(vector keywords); - extern vector alloc_strvec(char *string); - extern void *set_value(vector strvec); -+extern void *set_regex_value(vector strvec); - extern int process_file(struct config *conf, char *conf_file); - extern struct keyword * find_keyword(vector keywords, vector v, char * name); - int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, --- -2.7.4 - diff --git a/SOURCES/0013-multipathd-handle-changed-wwids-by-removal-and-addit.patch b/SOURCES/0013-multipathd-handle-changed-wwids-by-removal-and-addit.patch new file mode 100644 index 0000000..45c0366 --- /dev/null +++ b/SOURCES/0013-multipathd-handle-changed-wwids-by-removal-and-addit.patch @@ -0,0 +1,83 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 27 Mar 2019 23:27:47 -0500 +Subject: [PATCH] multipathd: handle changed wwids by removal and addition + +If a path's WWID changes, it's not necessarily failed. But it certainly +has to be removed from an existing map, otherwise data corruption is +imminent. Instead of keeping the path in the map, failing it, and +remembering the "changed WWID" state, this patch simply removes and +re-adds the path. + +This is patch is heavily based on the previous patch of the same name +by Martin Wilck. + +Signed-off-by: Benjamin Marzinski +--- + multipathd/main.c | 28 ++++++---------------------- + 1 file changed, 6 insertions(+), 22 deletions(-) + +diff --git a/multipathd/main.c b/multipathd/main.c +index 7a317d9..b3571d9 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1191,7 +1191,6 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + int ro, retval = 0, rc; + struct path * pp; + struct config *conf; +- int disable_changed_wwids; + int needs_reinit = 0; + + switch ((rc = change_foreign(uev->udev))) { +@@ -1209,12 +1208,6 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + break; + } + +- conf = get_multipath_config(); +- disable_changed_wwids = conf->disable_changed_wwids; +- put_multipath_config(conf); +- +- ro = uevent_get_disk_ro(uev); +- + pthread_cleanup_push(cleanup_lock, &vecs->lock); + lock(&vecs->lock); + pthread_testcancel(); +@@ -1239,22 +1232,12 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + if (rc != 0) + strcpy(pp->wwid, wwid); + else if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { +- condlog(0, "%s: path wwid changed from '%s' to '%s'. %s", +- uev->kernel, wwid, pp->wwid, +- (disable_changed_wwids ? "disallowing" : +- "continuing")); +- strcpy(pp->wwid, wwid); +- if (disable_changed_wwids) { +- if (!pp->wwid_changed) { +- pp->wwid_changed = 1; +- pp->tick = 1; +- if (pp->mpp) +- dm_fail_path(pp->mpp->alias, pp->dev_t); +- } +- goto out; +- } ++ condlog(0, "%s: path wwid changed from '%s' to '%s'", ++ uev->kernel, wwid, pp->wwid); ++ ev_remove_path(pp, vecs, 1); ++ needs_reinit = 1; ++ goto out; + } else { +- pp->wwid_changed = 0; + udev_device_unref(pp->udev); + pp->udev = udev_device_ref(uev->udev); + conf = get_multipath_config(); +@@ -1265,6 +1248,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + pthread_cleanup_pop(1); + } + ++ ro = uevent_get_disk_ro(uev); + if (mpp && ro >= 0) { + condlog(2, "%s: update path write_protect to '%d' (uevent)", uev->kernel, ro); + +-- +2.17.2 + diff --git a/SOURCES/0014-RH-reset-default-find_mutipaths-value-to-off.patch b/SOURCES/0014-RH-reset-default-find_mutipaths-value-to-off.patch deleted file mode 100644 index 782c3d3..0000000 --- a/SOURCES/0014-RH-reset-default-find_mutipaths-value-to-off.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 7 Jun 2018 17:43:52 -0500 -Subject: [PATCH] RH: reset default find_mutipaths value to off - -Upstream has changed to default find_multipaths to "strict". For now -Redhat will retain the previous default of "off". - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/defaults.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h -index 7f3839f..c84d31d 100644 ---- a/libmultipath/defaults.h -+++ b/libmultipath/defaults.h -@@ -17,7 +17,7 @@ - #define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF - #define DEFAULT_VERBOSITY 2 - #define DEFAULT_REASSIGN_MAPS 0 --#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_STRICT -+#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_OFF - #define DEFAULT_FAST_IO_FAIL 5 - #define DEFAULT_DEV_LOSS_TMO 600 - #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON --- -2.7.4 - diff --git a/SOURCES/0014-multipathd-remove-wwid_changed-path-attribute.patch b/SOURCES/0014-multipathd-remove-wwid_changed-path-attribute.patch new file mode 100644 index 0000000..59279e5 --- /dev/null +++ b/SOURCES/0014-multipathd-remove-wwid_changed-path-attribute.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 18 Mar 2019 13:12:34 +0100 +Subject: [PATCH] multipathd: remove "wwid_changed" path attribute + +This is now not needed any more. + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/structs.h | 1 - + multipathd/main.c | 6 ------ + 2 files changed, 7 deletions(-) + +diff --git a/libmultipath/structs.h b/libmultipath/structs.h +index b794b0d..7879d76 100644 +--- a/libmultipath/structs.h ++++ b/libmultipath/structs.h +@@ -280,7 +280,6 @@ struct path { + int fd; + int initialized; + int retriggers; +- int wwid_changed; + unsigned int path_failures; + time_t dis_reinstate_time; + int disable_reinstate; +diff --git a/multipathd/main.c b/multipathd/main.c +index b3571d9..e4f95a0 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -2001,12 +2001,6 @@ check_path (struct vectors * vecs, struct path * pp, int ticks) + if (newstate == PATH_REMOVED) + newstate = PATH_DOWN; + +- if (pp->wwid_changed) { +- condlog(2, "%s: path wwid has changed. Refusing to use", +- pp->dev); +- newstate = PATH_DOWN; +- } +- + if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) { + condlog(2, "%s: unusable path (%s) - checker failed", + pp->dev, checker_state_name(newstate)); +-- +2.17.2 + diff --git a/SOURCES/0015-libmultipath-free-allocated-value-in-set_int.patch b/SOURCES/0015-libmultipath-free-allocated-value-in-set_int.patch deleted file mode 100644 index 497d3ad..0000000 --- a/SOURCES/0015-libmultipath-free-allocated-value-in-set_int.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 11 Oct 2018 15:14:25 -0500 -Subject: [PATCH] libmultipath: free allocated value in set_int - -set_int() needs to free the buffer it got back from set_value() - -Fixes: 8f9ac30d ("libmultipath: fix set_int error path") -Signed-off-by: Benjamin Marzinski ---- - libmultipath/dict.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/libmultipath/dict.c b/libmultipath/dict.c -index 9d63d26..47ddce7 100644 ---- a/libmultipath/dict.c -+++ b/libmultipath/dict.c -@@ -39,6 +39,7 @@ set_int(vector strvec, void *ptr) - - *int_ptr = atoi(buff); - -+ FREE(buff); - return 0; - } - --- -2.17.1 - diff --git a/SOURCES/0015-multipathd-ignore-disable_changed_wwids.patch b/SOURCES/0015-multipathd-ignore-disable_changed_wwids.patch new file mode 100644 index 0000000..8565203 --- /dev/null +++ b/SOURCES/0015-multipathd-ignore-disable_changed_wwids.patch @@ -0,0 +1,98 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 18 Mar 2019 13:12:35 +0100 +Subject: [PATCH] multipathd: ignore "disable_changed_wwids" + +This option has no effect any more. + +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/config.c | 1 - + libmultipath/config.h | 1 - + libmultipath/dict.c | 18 +++++++++++++++--- + multipath/multipath.conf.5 | 8 ++------ + 4 files changed, 17 insertions(+), 11 deletions(-) + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index 24d71ae..141f092 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -715,7 +715,6 @@ load_config (char * file) + conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; + conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; + conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT; +- conf->disable_changed_wwids = DEFAULT_DISABLE_CHANGED_WWIDS; + conf->remove_retries = 0; + conf->ghost_delay = DEFAULT_GHOST_DELAY; + conf->all_tg_pt = DEFAULT_ALL_TG_PT; +diff --git a/libmultipath/config.h b/libmultipath/config.h +index b938c26..f5bf5b1 100644 +--- a/libmultipath/config.h ++++ b/libmultipath/config.h +@@ -182,7 +182,6 @@ struct config { + int delayed_reconfig; + int uev_wait_timeout; + int skip_kpartx; +- int disable_changed_wwids; + int remove_retries; + int max_sectors_kb; + int ghost_delay; +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index eaad4f1..96815f8 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -156,6 +156,12 @@ out: + return len; + } + ++static int ++print_ignored (char *buff, int len) ++{ ++ return snprintf(buff, len, "ignored"); ++} ++ + static int + print_yes_no (char *buff, int len, long v) + { +@@ -548,9 +554,15 @@ declare_hw_handler(skip_kpartx, set_yes_no_undef) + declare_hw_snprint(skip_kpartx, print_yes_no_undef) + declare_mp_handler(skip_kpartx, set_yes_no_undef) + declare_mp_snprint(skip_kpartx, print_yes_no_undef) +- +-declare_def_handler(disable_changed_wwids, set_yes_no) +-declare_def_snprint(disable_changed_wwids, print_yes_no) ++static int def_disable_changed_wwids_handler(struct config *conf, vector strvec) ++{ ++ return 0; ++} ++static int snprint_def_disable_changed_wwids(struct config *conf, char *buff, ++ int len, const void *data) ++{ ++ return print_ignored(buff, len); ++} + + declare_def_handler(remove_retries, set_int) + declare_def_snprint(remove_retries, print_int) +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index 864d7eb..646c156 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -1148,12 +1148,8 @@ The default is: \fBno\fR + . + .TP + .B disable_changed_wwids +-If set to \fIyes\fR, multipathd will check the path wwid on change events, and +-if it has changed from the wwid of the multipath device, multipathd will +-disable access to the path until the wwid changes back. +-.RS +-.TP +-The default is: \fBno\fR ++This option is deprecated and ignored. If the WWID of a path suddenly changes, ++multipathd handles it as if it was removed and then added again. + .RE + . + . +-- +2.17.2 + diff --git a/SOURCES/0016-kpartx-fix-new-memory-leak-in-dm_find_part.patch b/SOURCES/0016-kpartx-fix-new-memory-leak-in-dm_find_part.patch deleted file mode 100644 index 3670438..0000000 --- a/SOURCES/0016-kpartx-fix-new-memory-leak-in-dm_find_part.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 11 Oct 2018 15:37:52 -0500 -Subject: [PATCH] kpartx: fix new memory leak in dm_find_part - -While commit 960bb238 fixed one memory leak, it created another. - -Fixes: 960bb238 ("kpartx: Fix memory leak of uuid found by coverity") -Signed-off-by: Benjamin Marzinski ---- - kpartx/devmapper.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/kpartx/devmapper.c b/kpartx/devmapper.c -index 8db1eb5..3aa4988 100644 ---- a/kpartx/devmapper.c -+++ b/kpartx/devmapper.c -@@ -690,6 +690,7 @@ int dm_find_part(const char *parent, const char *delim, int part, - - r = dm_rename(tmp, name); - if (r == 1) { -+ free(tmp); - *part_uuid = uuid; - return 1; - } --- -2.17.1 - diff --git a/SOURCES/0016-multipathd-Don-t-use-fallback-code-after-getting-wwi.patch b/SOURCES/0016-multipathd-Don-t-use-fallback-code-after-getting-wwi.patch new file mode 100644 index 0000000..61e0f0d --- /dev/null +++ b/SOURCES/0016-multipathd-Don-t-use-fallback-code-after-getting-wwi.patch @@ -0,0 +1,135 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 28 Mar 2019 15:17:48 -0500 +Subject: [PATCH] multipathd: Don't use fallback code after getting wwid + +The fallback code is necessary to set up mutipath devices, if multipath +temporarily can't get the information from udev. However, once the +devices are set up, udev is the definitive source of this information. + +The wwid gotten from the fallback code and the udev code should always +be the same, in which case it doesn't matter where we get the wwid +from. But if they are different, it's important to try to do the +right thing. + +Working under the assumption that udev will either never give us this +information, or that it usually will. multipath should assume that if +there are multiple paths to a device, either they will all never get +a wwid from udev, or some of them will likely already have gotten the +correct wwid from udev. In this case, we should fix this as soon as +possible. + +This does mean that devices where udev will never give out the uuid +will not notice if the wwid changes, but that's a small price to pay +for doing the right thing most of the time. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/discovery.c | 22 +++++++++------------- + libmultipath/discovery.h | 3 ++- + multipathd/main.c | 2 +- + 3 files changed, 12 insertions(+), 15 deletions(-) + +diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c +index 3ec60d6..744cf2c 100644 +--- a/libmultipath/discovery.c ++++ b/libmultipath/discovery.c +@@ -1763,7 +1763,6 @@ static ssize_t uid_fallback(struct path *pp, int path_state, + !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) { + len = get_vpd_uid(pp); + *origin = "sysfs"; +- pp->uid_attribute = NULL; + if (len < 0 && path_state == PATH_UP) { + condlog(1, "%s: failed to get sysfs uid: %s", + pp->dev, strerror(-len)); +@@ -1787,7 +1786,6 @@ static ssize_t uid_fallback(struct path *pp, int path_state, + len = WWID_SIZE; + } + *origin = "sysfs"; +- pp->uid_attribute = NULL; + } + return len; + } +@@ -1800,12 +1798,14 @@ static int has_uid_fallback(struct path *pp) + } + + int +-get_uid (struct path * pp, int path_state, struct udev_device *udev) ++get_uid (struct path * pp, int path_state, struct udev_device *udev, ++ int allow_fallback) + { + char *c; + const char *origin = "unknown"; + ssize_t len = 0; + struct config *conf; ++ int used_fallback = 0; + + if (!pp->uid_attribute && !pp->getuid) { + conf = get_multipath_config(); +@@ -1846,14 +1846,9 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev) + len = get_vpd_uid(pp); + origin = "sysfs"; + } +- if (len <= 0 && has_uid_fallback(pp)) { +- int retrigger_tries; +- +- conf = get_multipath_config(); +- retrigger_tries = conf->retrigger_tries; +- put_multipath_config(conf); +- if (pp->retriggers >= retrigger_tries) +- len = uid_fallback(pp, path_state, &origin); ++ if (len <= 0 && allow_fallback && has_uid_fallback(pp)) { ++ used_fallback = 1; ++ len = uid_fallback(pp, path_state, &origin); + } + } + if ( len < 0 ) { +@@ -1870,7 +1865,7 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev) + c--; + } + } +- condlog(3, "%s: uid = %s (%s)", pp->dev, ++ condlog((used_fallback)? 1 : 3, "%s: uid = %s (%s)", pp->dev, + *pp->wwid == '\0' ? "" : pp->wwid, origin); + return 0; + } +@@ -1994,7 +1989,8 @@ int pathinfo(struct path *pp, struct config *conf, int mask) + } + + if ((mask & DI_WWID) && !strlen(pp->wwid)) { +- get_uid(pp, path_state, pp->udev); ++ get_uid(pp, path_state, pp->udev, ++ (pp->retriggers >= conf->retrigger_tries)); + if (!strlen(pp->wwid)) { + if (pp->bus == SYSFS_BUS_UNDEF) + return PATHINFO_SKIPPED; +diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h +index 9aacf75..8fd126b 100644 +--- a/libmultipath/discovery.h ++++ b/libmultipath/discovery.h +@@ -52,7 +52,8 @@ ssize_t sysfs_get_vpd (struct udev_device * udev, int pg, unsigned char * buff, + size_t len); + int sysfs_get_asymmetric_access_state(struct path *pp, + char *buff, int buflen); +-int get_uid(struct path * pp, int path_state, struct udev_device *udev); ++int get_uid(struct path * pp, int path_state, struct udev_device *udev, ++ int allow_fallback); + + /* + * discovery bitmask +diff --git a/multipathd/main.c b/multipathd/main.c +index e4f95a0..1413c6d 100644 +--- a/multipathd/main.c ++++ b/multipathd/main.c +@@ -1227,7 +1227,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) + goto out; + + strcpy(wwid, pp->wwid); +- rc = get_uid(pp, pp->state, uev->udev); ++ rc = get_uid(pp, pp->state, uev->udev, 0); + + if (rc != 0) + strcpy(pp->wwid, wwid); +-- +2.17.2 + diff --git a/SOURCES/0017-BZ-1648397-fix-mpp-hwe-handling-when-paths-are-freed.patch b/SOURCES/0017-BZ-1648397-fix-mpp-hwe-handling-when-paths-are-freed.patch deleted file mode 100644 index 2b87453..0000000 --- a/SOURCES/0017-BZ-1648397-fix-mpp-hwe-handling-when-paths-are-freed.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 20 Nov 2018 22:05:43 -0600 -Subject: [PATCH] BZ 1648397: fix mpp->hwe handling when paths are freed - -Commit 1f962693 didn't deal with all of cases where a path that was part -of a multipath device could be removed. verify_paths() removes any path -that no longer exists in sysfs. mpp->hwe needs to be updated here as -well, since verify_paths() could remove the path whose hwe vector is -pointed to by mpp->hwe. Also, now that extract_hwe_from_path() is -called in verify_paths(), the extract_hwe_from_path() calls that -happened immediately after verify_paths() can be dropped. - -The other part of this fix is mostly cosmetic. In ev_add_path(), if -domap() fails after the path is added to the multipath device and -verify_paths() is called, the code can loop back to the rescan label. If -the size of the path or the multipath device changed in the interim, -ev_add_path() would remove the path, without updating mpp->hwe; but -there is no way for the size to change. Just to make that clearer in the -code, I've moved the size check to before the rescan label so it only -happens once. - -Fixes: 1f962693 "multipathd: fix mpp->hwe handling on path removal" -Cc: Martin Wilck -Signed-off-by: Benjamin Marzinski ---- - libmultipath/structs_vec.c | 7 +++++++ - multipathd/main.c | 21 ++++++++------------- - 2 files changed, 15 insertions(+), 13 deletions(-) - -diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c -index f87d69d..cd95ad4 100644 ---- a/libmultipath/structs_vec.c -+++ b/libmultipath/structs_vec.c -@@ -404,6 +404,12 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs) - vector_del_slot(mpp->paths, i); - i--; - -+ /* Make sure mpp->hwe doesn't point to freed memory. -+ * We call extract_hwe_from_path() below to restore -+ * mpp->hwe -+ */ -+ if (mpp->hwe == pp->hwe) -+ mpp->hwe = NULL; - if ((j = find_slot(vecs->pathvec, - (void *)pp)) != -1) - vector_del_slot(vecs->pathvec, j); -@@ -413,6 +419,7 @@ int verify_paths(struct multipath *mpp, struct vectors *vecs) - mpp->alias, pp->dev, pp->dev_t); - } - } -+ extract_hwe_from_path(mpp); - return count; - } - -diff --git a/multipathd/main.c b/multipathd/main.c -index 2d45d98..4e2835d 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -470,7 +470,6 @@ retry: - verify_paths(mpp, vecs); - mpp->action = ACT_RELOAD; - -- extract_hwe_from_path(mpp); - if (setup_map(mpp, params, PARAMS_SIZE, vecs)) { - condlog(0, "%s: failed to setup new map in update", mpp->alias); - retries = -1; -@@ -904,6 +903,14 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map) - goto fail; /* leave path added to pathvec */ - } - mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); -+ if (mpp && pp->size && mpp->size != pp->size) { -+ condlog(0, "%s: failed to add new path %s, device size mismatch", mpp->alias, pp->dev); -+ int i = find_slot(vecs->pathvec, (void *)pp); -+ if (i != -1) -+ vector_del_slot(vecs->pathvec, i); -+ free_path(pp); -+ return 1; -+ } - if (mpp && mpp->wait_for_udev && - (pathcount(mpp, PATH_UP) > 0 || - (pathcount(mpp, PATH_GHOST) > 0 && pp->tpgs != TPGS_IMPLICIT && -@@ -919,17 +926,6 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map) - pp->mpp = mpp; - rescan: - if (mpp) { -- if (pp->size && mpp->size != pp->size) { -- condlog(0, "%s: failed to add new path %s, " -- "device size mismatch", -- mpp->alias, pp->dev); -- int i = find_slot(vecs->pathvec, (void *)pp); -- if (i != -1) -- vector_del_slot(vecs->pathvec, i); -- free_path(pp); -- return 1; -- } -- - condlog(4,"%s: adopting all paths for path %s", - mpp->alias, pp->dev); - if (adopt_paths(vecs->pathvec, mpp)) -@@ -937,7 +933,6 @@ rescan: - - verify_paths(mpp, vecs); - mpp->action = ACT_RELOAD; -- extract_hwe_from_path(mpp); - } else { - if (!should_multipath(pp, vecs->pathvec, vecs->mpvec)) { - orphan_path(pp, "only one path"); --- -2.17.2 - diff --git a/SOURCES/0017-libmultipath-silence-dm_is_mpath-error-messages.patch b/SOURCES/0017-libmultipath-silence-dm_is_mpath-error-messages.patch new file mode 100644 index 0000000..203ed74 --- /dev/null +++ b/SOURCES/0017-libmultipath-silence-dm_is_mpath-error-messages.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 28 Mar 2019 17:49:38 -0500 +Subject: [PATCH] libmultipath: silence dm_is_mpath error messages + +When "multipath -F" is run, dm_is_mpath was printing error messages +about partition devices, because they had already been removed, when +it checked. Lower the error logging level so this doesn't happen on +the default verbosity. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/devmapper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c +index 3294bd4..2e79667 100644 +--- a/libmultipath/devmapper.c ++++ b/libmultipath/devmapper.c +@@ -746,7 +746,7 @@ out_task: + dm_task_destroy(dmt); + out: + if (r < 0) +- condlog(2, "%s: dm command failed in %s", name, __FUNCTION__); ++ condlog(3, "%s: dm command failed in %s: %s", name, __FUNCTION__, strerror(errno)); + return r; + } + +-- +2.17.2 + diff --git a/SOURCES/0018-RH-fixup-udev-rules-for-redhat.patch b/SOURCES/0018-RH-fixup-udev-rules-for-redhat.patch new file mode 100644 index 0000000..6c1bf63 --- /dev/null +++ b/SOURCES/0018-RH-fixup-udev-rules-for-redhat.patch @@ -0,0 +1,66 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 13 Apr 2017 07:22:23 -0500 +Subject: [PATCH] RH: fixup udev rules for redhat + +The multipath rules need to run after scsi_id is run. This means moving +them after 60-persistent-storage.rules for redhat. Redhat also uses a +different naming scheme for partitions than SuSE. + +Signed-off-by: Benjamin Marzinski +--- + Makefile.inc | 2 +- + kpartx/kpartx.rules | 2 +- + multipath/Makefile | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index fc728ca..2f0bcea 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -48,7 +48,7 @@ endif + prefix = + exec_prefix = $(prefix) + usr_prefix = $(prefix) +-bindir = $(exec_prefix)/sbin ++bindir = $(exec_prefix)/usr/sbin + libudevdir = $(prefix)/$(SYSTEMDPATH)/udev + udevrulesdir = $(libudevdir)/rules.d + multipathdir = $(TOPDIR)/libmultipath +diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules +index 8f99049..8a3a171 100644 +--- a/kpartx/kpartx.rules ++++ b/kpartx/kpartx.rules +@@ -32,6 +32,6 @@ LABEL="mpath_kpartx_end" + GOTO="kpartx_end" + + LABEL="run_kpartx" +-RUN+="/sbin/kpartx -un -p -part /dev/$name" ++RUN+="/sbin/kpartx -un /dev/$name" + + LABEL="kpartx_end" +diff --git a/multipath/Makefile b/multipath/Makefile +index 0828a8f..b9bbb3c 100644 +--- a/multipath/Makefile ++++ b/multipath/Makefile +@@ -24,7 +24,7 @@ install: + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) + $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) +- $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules ++ $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) +@@ -33,7 +33,7 @@ install: + uninstall: + $(RM) $(DESTDIR)$(bindir)/$(EXEC) + $(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules +- $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules ++ $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules + $(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz + $(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz + +-- +2.17.2 + diff --git a/SOURCES/0018-libmultipath-cleanup-pthread_cleanup_pop-call.patch b/SOURCES/0018-libmultipath-cleanup-pthread_cleanup_pop-call.patch deleted file mode 100644 index a6f315c..0000000 --- a/SOURCES/0018-libmultipath-cleanup-pthread_cleanup_pop-call.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 26 Nov 2018 16:42:24 -0600 -Subject: [PATCH] libmultipath: cleanup pthread_cleanup_pop call - -pthread_cleanup_push() and pthread_cleanup_pop() must be called in the -same lexical scope. In uevent_listen(), the pthread_cleanup_pop() call -to cleanup the udev monitor is called in a nested 'if' block, within -the block where pthread_cleanup_push() is called. Since this is a -single-statement if block, it doesn't actually cause any problems, but -it should be fixed anyways. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/uevent.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c -index 5f910e6..f73de8c 100644 ---- a/libmultipath/uevent.c -+++ b/libmultipath/uevent.c -@@ -806,7 +806,7 @@ int uevent_listen(struct udev *udev) - monitor = udev_monitor_new_from_netlink(udev, "udev"); - if (!monitor) { - condlog(2, "failed to create udev monitor"); -- goto out; -+ goto failback; - } - pthread_cleanup_push(monitor_cleanup, monitor); - #ifdef LIBUDEV_API_RECVBUF -@@ -893,8 +893,8 @@ int uevent_listen(struct udev *udev) - } - need_failback = 0; - out: -- if (monitor) -- pthread_cleanup_pop(1); -+ pthread_cleanup_pop(1); -+failback: - if (need_failback) - err = failback_listen(); - pthread_cleanup_pop(1); --- -2.17.2 - diff --git a/SOURCES/0019-RH-Remove-the-property-blacklist-exception-builtin.patch b/SOURCES/0019-RH-Remove-the-property-blacklist-exception-builtin.patch new file mode 100644 index 0000000..81c12b9 --- /dev/null +++ b/SOURCES/0019-RH-Remove-the-property-blacklist-exception-builtin.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 2 Jul 2014 12:49:53 -0500 +Subject: [PATCH] RH: Remove the property blacklist exception builtin + +Multipath set the default property blacklist exceptions to +(ID_SCSI_VPD|ID_WWN). This has the effect of blacklisting some internal +devices. These devices may never have multiple paths, but it is nice +to be able to set multipath up on them all the same. This patch simply +removes the default, and makes it so that if no property +blacklist_exception is given, then devices aren't failed for not matching +it. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/blacklist.c | 12 ++++-------- + multipath/multipath.conf.5 | 14 ++++++-------- + 2 files changed, 10 insertions(+), 16 deletions(-) + +diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c +index e0d0279..556c0b9 100644 +--- a/libmultipath/blacklist.c ++++ b/libmultipath/blacklist.c +@@ -204,12 +204,6 @@ setup_default_blist (struct config * conf) + if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT)) + return 1; + +- str = STRDUP("(SCSI_IDENT_|ID_WWN)"); +- if (!str) +- return 1; +- if (store_ble(conf->elist_property, str, ORIGIN_DEFAULT)) +- return 1; +- + vector_foreach_slot (conf->hwtable, hwe, i) { + if (hwe->bl_product) { + if (find_blacklist_device(conf->blist_device, +@@ -394,9 +388,11 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl) + if (udev) { + /* + * This is the inverse of the 'normal' matching; +- * the environment variable _has_ to match. ++ * the environment variable _has_ to match ++ * if a whitelist is present. + */ +- r = MATCH_PROPERTY_BLIST_MISSING; ++ if (VECTOR_SIZE(conf->elist_property)) ++ r = MATCH_PROPERTY_BLIST_MISSING; + udev_list_entry_foreach(list_entry, + udev_device_get_properties_list_entry(udev)) { + +diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5 +index 646c156..768ab83 100644 +--- a/multipath/multipath.conf.5 ++++ b/multipath/multipath.conf.5 +@@ -1235,16 +1235,14 @@ keywords. Both are regular expressions. For a full description of these keywords + Regular expression for an udev property. All + devices that have matching udev properties will be excluded/included. + The handling of the \fIproperty\fR keyword is special, +-because devices \fBmust\fR have at least one whitelisted udev property; ++because if a property blacklist_exception is set, devices \fBmust\fR have at ++least one whitelisted udev property; + otherwise they're treated as blacklisted, and the message + "\fIblacklisted, udev property missing\fR" is displayed in the logs. +-. +-.RS +-.PP +-The default \fIblacklist exception\fR is: \fB(SCSI_IDENT_|ID_WWN)\fR, causing +-well-behaved SCSI devices and devices that provide a WWN (World Wide Number) +-to be included, and all others to be excluded. +-.RE ++For example, setting the property blacklist_exception to ++\fB(SCSI_IDENT_|ID_WWN)\fR, will cause well-behaved SCSI devices and devices ++that provide a WWN (World Wide Number) to be included, and all others to be ++excluded. This works to exclude most non-multipathable devices. + .TP + .B protocol + Regular expression for the protocol of a device to be excluded/included. +-- +2.17.2 + diff --git a/SOURCES/0019-libmultipath-fix-false-removes-in-dmevents-polling-c.patch b/SOURCES/0019-libmultipath-fix-false-removes-in-dmevents-polling-c.patch deleted file mode 100644 index 8b9a4e5..0000000 --- a/SOURCES/0019-libmultipath-fix-false-removes-in-dmevents-polling-c.patch +++ /dev/null @@ -1,204 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Tue, 27 Nov 2018 22:50:57 -0600 -Subject: [PATCH] libmultipath: fix false removes in dmevents polling code - -dm_is_mpath() would return 0 if either a device was not a multipath -device or if the libdevmapper command failed. Because dm_is_mpath() -didn't distinguish between these situations, dm_get_events() could -assume that a device was not really a multipath device, when in fact it -was, and the libdevmapper command simply failed. This would cause the -dmevents polling waiter to stop monitoring the device. - -In reality, the call to dm_is_mpath() isn't necessary, because -dm_get_events() will already verify that the device name is on the list -of devices to wait for. However, if there are a large number of -non-multipath devices on the system, ignoring them can be useful. Thus, -if dm_is_mpath() successfully runs the libdevmapper command and verifies -that the device is not a multipath device, dm_get_events() should skip -it. But if the libdevmapper command fails, dm_get_events() should still -check the device list, to see if the device should be monitored. - -This commit makes dm_is_mpath() return -1 for situations where -the libdevmapper command failed, and makes dm_get_events() only ignore -the device on a return of 0. - -Signed-off-by: Benjamin Marzinski ---- - libmpathpersist/mpath_persist.c | 4 ++-- - libmultipath/devmapper.c | 41 +++++++++++++++++++++++---------- - multipath/main.c | 2 +- - multipathd/dmevents.c | 8 +++++-- - multipathd/main.c | 2 +- - 5 files changed, 39 insertions(+), 18 deletions(-) - -diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c -index 2ffe56e..7e8a676 100644 ---- a/libmpathpersist/mpath_persist.c -+++ b/libmpathpersist/mpath_persist.c -@@ -188,7 +188,7 @@ int mpath_persistent_reserve_in (int fd, int rq_servact, - - condlog(3, "alias = %s", alias); - map_present = dm_map_present(alias); -- if (map_present && !dm_is_mpath(alias)){ -+ if (map_present && dm_is_mpath(alias) != 1){ - condlog( 0, "%s: not a multipath device.", alias); - ret = MPATH_PR_DMMP_ERROR; - goto out; -@@ -283,7 +283,7 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope, - condlog(3, "alias = %s", alias); - map_present = dm_map_present(alias); - -- if (map_present && !dm_is_mpath(alias)){ -+ if (map_present && dm_is_mpath(alias) != 1){ - condlog(3, "%s: not a multipath device.", alias); - ret = MPATH_PR_DMMP_ERROR; - goto out; -diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c -index 0433b49..3294bd4 100644 ---- a/libmultipath/devmapper.c -+++ b/libmultipath/devmapper.c -@@ -692,9 +692,15 @@ out: - return r; - } - -+/* -+ * returns: -+ * 1 : is multipath device -+ * 0 : is not multipath device -+ * -1 : error -+ */ - int dm_is_mpath(const char *name) - { -- int r = 0; -+ int r = -1; - struct dm_task *dmt; - struct dm_info info; - uint64_t start, length; -@@ -703,33 +709,44 @@ int dm_is_mpath(const char *name) - const char *uuid; - - if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE))) -- return 0; -+ goto out; - - if (!dm_task_set_name(dmt, name)) -- goto out; -+ goto out_task; - - dm_task_no_open_count(dmt); - - if (!dm_task_run(dmt)) -- goto out; -+ goto out_task; - -- if (!dm_task_get_info(dmt, &info) || !info.exists) -- goto out; -+ if (!dm_task_get_info(dmt, &info)) -+ goto out_task; -+ -+ r = 0; -+ -+ if (!info.exists) -+ goto out_task; - - uuid = dm_task_get_uuid(dmt); - - if (!uuid || strncmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN) != 0) -- goto out; -+ goto out_task; - - /* Fetch 1st target */ -- dm_get_next_target(dmt, NULL, &start, &length, &target_type, ¶ms); -+ if (dm_get_next_target(dmt, NULL, &start, &length, &target_type, -+ ¶ms) != NULL) -+ /* multiple targets */ -+ goto out_task; - - if (!target_type || strcmp(target_type, TGT_MPATH) != 0) -- goto out; -+ goto out_task; - - r = 1; --out: -+out_task: - dm_task_destroy(dmt); -+out: -+ if (r < 0) -+ condlog(2, "%s: dm command failed in %s", name, __FUNCTION__); - return r; - } - -@@ -823,7 +840,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove, - unsigned long long mapsize; - char params[PARAMS_SIZE] = {0}; - -- if (!dm_is_mpath(mapname)) -+ if (dm_is_mpath(mapname) != 1) - return 0; /* nothing to do */ - - /* if the device currently has no partitions, do not -@@ -1087,7 +1104,7 @@ dm_get_maps (vector mp) - } - - do { -- if (!dm_is_mpath(names->name)) -+ if (dm_is_mpath(names->name) != 1) - goto next; - - mpp = dm_get_multipath(names->name); -diff --git a/multipath/main.c b/multipath/main.c -index ccb6091..2c4054d 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -321,7 +321,7 @@ static int check_usable_paths(struct config *conf, - goto out; - } - -- if (!dm_is_mpath(mapname)) { -+ if (dm_is_mpath(mapname) != 1) { - condlog(1, "%s is not a multipath map", devpath); - goto free; - } -diff --git a/multipathd/dmevents.c b/multipathd/dmevents.c -index 31e64a7..0034892 100644 ---- a/multipathd/dmevents.c -+++ b/multipathd/dmevents.c -@@ -168,7 +168,9 @@ static int dm_get_events(void) - while (names->dev) { - uint32_t event_nr; - -- if (!dm_is_mpath(names->name)) -+ /* Don't delete device if dm_is_mpath() fails without -+ * checking the device type */ -+ if (dm_is_mpath(names->name) == 0) - goto next; - - event_nr = dm_event_nr(names); -@@ -204,7 +206,9 @@ int watch_dmevents(char *name) - struct dev_event *dev_evt, *old_dev_evt; - int i; - -- if (!dm_is_mpath(name)) { -+ /* We know that this is a multipath device, so only fail if -+ * device-mapper tells us that we're wrong */ -+ if (dm_is_mpath(name) == 0) { - condlog(0, "%s: not a multipath device. can't watch events", - name); - return -1; -diff --git a/multipathd/main.c b/multipathd/main.c -index 4e2835d..82a298b 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -678,7 +678,7 @@ ev_add_map (char * dev, const char * alias, struct vectors * vecs) - int delayed_reconfig, reassign_maps; - struct config *conf; - -- if (!dm_is_mpath(alias)) { -+ if (dm_is_mpath(alias) != 1) { - condlog(4, "%s: not a multipath map", alias); - return 0; - } --- -2.17.2 - diff --git a/SOURCES/0020-BZ-1668693-disable-user_friendly_names-for-NetApp.patch b/SOURCES/0020-BZ-1668693-disable-user_friendly_names-for-NetApp.patch deleted file mode 100644 index 491a21d..0000000 --- a/SOURCES/0020-BZ-1668693-disable-user_friendly_names-for-NetApp.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 24 Jan 2019 14:09:23 -0600 -Subject: [PATCH] BZ 1668693: disable user_friendly_names for NetApp - -NetApp has tools that rely on devices using WWID names. To avoid -breaking these, NetApp devices should continue to use WWID names, even -if the default config is set to enable user_friendly_names. If users -want to use user_friendly_names on NetApp devices, the must specifically -override the device config. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/hwtable.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c -index d3a8d9b..8776411 100644 ---- a/libmultipath/hwtable.c -+++ b/libmultipath/hwtable.c -@@ -719,6 +719,7 @@ static struct hwentry default_hw[] = { - .flush_on_last_del = FLUSH_ENABLED, - .dev_loss = MAX_DEV_LOSS_TMO, - .prio_name = PRIO_ONTAP, -+ .user_friendly_names = USER_FRIENDLY_NAMES_OFF, - }, - { - /* --- -2.17.2 - diff --git a/SOURCES/0020-RH-don-t-start-without-a-config-file.patch b/SOURCES/0020-RH-don-t-start-without-a-config-file.patch new file mode 100644 index 0000000..d840c33 --- /dev/null +++ b/SOURCES/0020-RH-don-t-start-without-a-config-file.patch @@ -0,0 +1,106 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 15 Oct 2014 10:39:30 -0500 +Subject: [PATCH] RH: don't start without a config file + +If /etc/multipath.conf doesn't exist, don't start multipathd and blacklist +all devices when running multipath. A completely blank configuration file +is almost never what users want. Also, people may have the multipath +packages installed but don't want to use them. This patch provides a +simple way to disable multipath. Simply removing or renaming +/etc/multipath.conf will keep multipath from doing anything. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/config.c | 15 +++++++++++++++ + libmultipath/config.h | 1 + + multipath/multipath.rules | 1 + + multipathd/multipathd.8 | 2 ++ + multipathd/multipathd.service | 1 + + 5 files changed, 20 insertions(+) + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index 141f092..544d2fb 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -26,6 +26,7 @@ + #include "devmapper.h" + #include "mpath_cmd.h" + #include "propsel.h" ++#include "version.h" + + static int + hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2) +@@ -745,6 +746,20 @@ load_config (char * file) + goto out; + } + factorize_hwtable(conf->hwtable, builtin_hwtable_size, file); ++ } else { ++ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); ++ if (conf->blist_devnode == NULL) { ++ conf->blist_devnode = vector_alloc(); ++ if (!conf->blist_devnode) { ++ condlog(0, "cannot allocate blacklist\n"); ++ goto out; ++ } ++ } ++ if (store_ble(conf->blist_devnode, strdup(".*"), ++ ORIGIN_NO_CONFIG)) { ++ condlog(0, "cannot store default no-config blacklist\n"); ++ goto out; ++ } + } + + conf->processed_main_config = 1; +diff --git a/libmultipath/config.h b/libmultipath/config.h +index f5bf5b1..8803967 100644 +--- a/libmultipath/config.h ++++ b/libmultipath/config.h +@@ -9,6 +9,7 @@ + + #define ORIGIN_DEFAULT 0 + #define ORIGIN_CONFIG 1 ++#define ORIGIN_NO_CONFIG 2 + + /* + * In kernel, fast_io_fail == 0 means immediate failure on rport delete. +diff --git a/multipath/multipath.rules b/multipath/multipath.rules +index 9df11a9..0486bf7 100644 +--- a/multipath/multipath.rules ++++ b/multipath/multipath.rules +@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath" + ENV{nompath}=="?*", GOTO="end_mpath" + IMPORT{cmdline}="multipath" + ENV{multipath}=="off", GOTO="end_mpath" ++TEST!="/etc/multipath.conf", GOTO="end_mpath" + + ENV{DEVTYPE}!="partition", GOTO="test_dev" + IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH" +diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8 +index 94c3f97..ed13efd 100644 +--- a/multipathd/multipathd.8 ++++ b/multipathd/multipathd.8 +@@ -38,6 +38,8 @@ map regains its maximum performance and redundancy. + This daemon executes the external \fBmultipath\fR tool when events occur. + In turn, the multipath tool signals the multipathd daemon when it is done with + devmap reconfiguration, so that it can refresh its failed path list. ++ ++In this Linux distribution, multipathd does not run unless a /etc/multipath.conf file exists. + . + . + .\" ---------------------------------------------------------------------------- +diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service +index ba24983..17434ce 100644 +--- a/multipathd/multipathd.service ++++ b/multipathd/multipathd.service +@@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service + Before=iscsi.service iscsid.service lvm2-activation-early.service + Before=local-fs-pre.target blk-availability.service + After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service ++ConditionPathExists=/etc/multipath.conf + DefaultDependencies=no + Conflicts=shutdown.target + ConditionKernelCommandLine=!nompath +-- +2.17.2 + diff --git a/SOURCES/0021-BZ-1673167-Fix-miscounting-active-paths.patch b/SOURCES/0021-BZ-1673167-Fix-miscounting-active-paths.patch deleted file mode 100644 index 17fcb39..0000000 --- a/SOURCES/0021-BZ-1673167-Fix-miscounting-active-paths.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 18 Feb 2019 13:32:45 -0600 -Subject: [PATCH] BZ 1673167: Fix miscounting active paths - -When multipathd gets a change uevent, it calls pathinfo with DI_NOIO. -This sets the path state to the return value of path_offline(). If a -path is in the PATH_DOWN state but path_offline() returns PATH_UP, when -that path gets a change event, its state will get moved to PATH_UP -without either reinstating the path, or reloading the map. The next -call to check_path() will move the path back to PATH_DOWN. Since -check_path() simply increments and decrements nr_active instead of -calculating it based on the actual number of active paths, nr_active -will get decremented a second time for this failed path, potentially -putting the multipath device into recovery mode. - -To avoid this situation, pathinfo() will now only set pp->state with -DI_NOIO if DI_CHECKER is also set. This isn't set in uev_update_path() -to avoid changing the path state in this case. - -Signed-off-by: Benjamin Marzinski ---- - libmultipath/discovery.c | 11 ++++++----- - multipath/main.c | 2 +- - 2 files changed, 7 insertions(+), 6 deletions(-) - -diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c -index b267f07..5de087c 100644 ---- a/libmultipath/discovery.c -+++ b/libmultipath/discovery.c -@@ -1914,11 +1914,12 @@ int pathinfo(struct path *pp, struct config *conf, int mask) - if (path_state == PATH_REMOVED) - goto blank; - else if (mask & DI_NOIO) { -- /* -- * Avoid any IO on the device itself. -- * Behave like DI_CHECKER in the "path unavailable" case. -- */ -- pp->chkrstate = pp->state = path_state; -+ if (mask & DI_CHECKER) -+ /* -+ * Avoid any IO on the device itself. -+ * simply use the path_offline() return as its state -+ */ -+ pp->chkrstate = pp->state = path_state; - return PATHINFO_OK; - } - -diff --git a/multipath/main.c b/multipath/main.c -index 2c4054d..0545226 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -345,7 +345,7 @@ static int check_usable_paths(struct config *conf, - pp->udev = get_udev_device(pp->dev_t, DEV_DEVT); - if (pp->udev == NULL) - continue; -- if (pathinfo(pp, conf, DI_SYSFS|DI_NOIO) != PATHINFO_OK) -+ if (pathinfo(pp, conf, DI_SYSFS|DI_NOIO|DI_CHECKER) != PATHINFO_OK) - continue; - - if (pp->state == PATH_UP && --- -2.17.2 - diff --git a/SOURCES/0021-RH-use-rpm-optflags-if-present.patch b/SOURCES/0021-RH-use-rpm-optflags-if-present.patch new file mode 100644 index 0000000..4b41d9e --- /dev/null +++ b/SOURCES/0021-RH-use-rpm-optflags-if-present.patch @@ -0,0 +1,53 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Wed, 19 Apr 2017 06:10:01 -0500 +Subject: [PATCH] RH: use rpm optflags if present + +Use the passed in optflags when compiling as an RPM, and keep the +default flags as close as possible to the current fedora flags, while +still being generic. + +Signed-off-by: Benjamin Marzinski +--- + Makefile.inc | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +diff --git a/Makefile.inc b/Makefile.inc +index 2f0bcea..b98800a 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -83,15 +83,23 @@ TEST_CC_OPTION = $(shell \ + echo "$(2)"; \ + fi) + +-STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector) + ERROR_DISCARDED_QUALIFIERS := $(call TEST_CC_OPTION,-Werror=discarded-qualifiers,) +- +-OPTFLAGS = -O2 -g -pipe -Wall -Wextra -Wformat=2 -Werror=implicit-int \ +- -Werror=implicit-function-declaration -Werror=format-security \ +- -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered \ +- -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \ +- -Wp,-D_FORTIFY_SOURCE=2 $(STACKPROT) \ +- --param=ssp-buffer-size=4 ++ifndef RPM_OPT_FLAGS ++ STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector) ++ OPTFLAGS = -O2 -g -pipe -Wall -Werror=format-security \ ++ -Wp,-D_FORTIFY_SOURCE=2 -fexceptions \ ++ $(STACKPROT) --param=ssp-buffer-size=4 \ ++ -grecord-gcc-switches ++ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-hardened-cc1 && echo 1),1) ++ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 ++ endif ++else ++ OPTFLAGS = $(RPM_OPT_FLAGS) ++endif ++OPTFLAGS += -Wextra -Wstrict-prototypes -Wformat=2 -Werror=implicit-int \ ++ -Werror=implicit-function-declaration -Wno-sign-compare \ ++ -Wno-unused-parameter $(ERROR_DISCARDED_QUALIFIERS) \ ++ -Werror=cast-qual + + CFLAGS := $(OPTFLAGS) -DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \ + -MMD -MP $(CFLAGS) +-- +2.17.2 + diff --git a/SOURCES/0022-BZ-1673167-ignore-failed-wwid-recheck.patch b/SOURCES/0022-BZ-1673167-ignore-failed-wwid-recheck.patch deleted file mode 100644 index 2b4e0ff..0000000 --- a/SOURCES/0022-BZ-1673167-ignore-failed-wwid-recheck.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Wed, 20 Feb 2019 17:05:08 -0600 -Subject: [PATCH] BZ 1673167: ignore failed wwid recheck - -If disable_changed_wwids is set, when multipathd gets a change event on -a path, it verifies that the wwid hasn't changed in uev_update_path(). -If get_uid() failed, uev_update_path treated this as a wwid change to 0. -This could cause paths to suddenly be dropped due to an issue with -getting the wwid. Even if get_uid() failed because the path was down, -it no change uevent happend when it later became active, multipathd -would continue to ignore the path. - -Instead, multipathd should neither set nor clear wwid_changed if -get_uid() returned failure. - -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 82a298b..30eb8fe 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -1211,9 +1211,9 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) - goto out; - - strcpy(wwid, pp->wwid); -- get_uid(pp, pp->state, uev->udev); -+ rc = get_uid(pp, pp->state, uev->udev); - -- if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { -+ if (rc == 0 && strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { - condlog(0, "%s: path wwid changed from '%s' to '%s'. %s", - uev->kernel, wwid, pp->wwid, - (disable_changed_wwids ? "disallowing" : -@@ -1229,7 +1229,8 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) - goto out; - } - } else { -- pp->wwid_changed = 0; -+ if (rc == 0) -+ pp->wwid_changed = 0; - udev_device_unref(pp->udev); - pp->udev = udev_device_ref(uev->udev); - conf = get_multipath_config(); -@@ -1782,6 +1783,7 @@ int update_prio(struct path *pp, int refresh_all) - - int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh) - { -+ condlog(2, "%s: updating path groups for priority change", mpp->alias); - if (reload_map(vecs, mpp, refresh, 1)) - return 1; - --- -2.17.2 - diff --git a/SOURCES/0022-RH-add-mpathconf.patch b/SOURCES/0022-RH-add-mpathconf.patch new file mode 100644 index 0000000..afa2761 --- /dev/null +++ b/SOURCES/0022-RH-add-mpathconf.patch @@ -0,0 +1,667 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 16 Oct 2014 15:49:01 -0500 +Subject: [PATCH] RH: add mpathconf + +mpathconf is a program (largely based on lvmcomf) to help users +configure /etc/multipath.conf and enable or disable multipathing. It +has a couple of built-in options that can be set directly from the +command line. But, mostly it is used to get a multipath.conf file +with the OS defaults, and to enable and disable multipathing via +a single command. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/config.c | 2 + + multipath/Makefile | 5 + + multipath/mpathconf | 464 ++++++++++++++++++++++++++++++++++++++++++ + multipath/mpathconf.8 | 119 +++++++++++ + 4 files changed, 590 insertions(+) + create mode 100644 multipath/mpathconf + create mode 100644 multipath/mpathconf.8 + +diff --git a/libmultipath/config.c b/libmultipath/config.c +index 544d2fb..deb80c2 100644 +--- a/libmultipath/config.c ++++ b/libmultipath/config.c +@@ -748,6 +748,8 @@ load_config (char * file) + factorize_hwtable(conf->hwtable, builtin_hwtable_size, file); + } else { + condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); ++ condlog(0, "You can run \"/sbin/mpathconf --enable\" to create"); ++ condlog(0, "/etc/multipath.conf. See man mpathconf(8) for more details"); + if (conf->blist_devnode == NULL) { + conf->blist_devnode = vector_alloc(); + if (!conf->blist_devnode) { +diff --git a/multipath/Makefile b/multipath/Makefile +index b9bbb3c..e720c7f 100644 +--- a/multipath/Makefile ++++ b/multipath/Makefile +@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so + $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS) + $(GZIP) $(EXEC).8 > $(EXEC).8.gz + $(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz ++ $(GZIP) mpathconf.8 > mpathconf.8.gz + + install: + $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ ++ $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir) + $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules +@@ -29,13 +31,16 @@ install: + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir) ++ $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(man8dir) + + uninstall: + $(RM) $(DESTDIR)$(bindir)/$(EXEC) + $(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules + $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules ++ $(RM) $(DESTDIR)$(bindir)/mpathconf + $(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz + $(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz ++ $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz + + clean: dep_clean + $(RM) core *.o $(EXEC) *.gz +diff --git a/multipath/mpathconf b/multipath/mpathconf +new file mode 100644 +index 0000000..e839134 +--- /dev/null ++++ b/multipath/mpathconf +@@ -0,0 +1,464 @@ ++#!/bin/bash ++# ++# Copyright (C) 2010 Red Hat, Inc. All rights reserved. ++# ++# This file is part of the device-mapper-multipath package. ++# ++# This copyrighted material is made available to anyone wishing to use, ++# modify, copy, or redistribute it subject to the terms and conditions ++# of the GNU General Public License v.2. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software Foundation, ++# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++# ++# Simple editting of /etc/multipath.conf ++# This program was largely ripped off from lvmconf ++# ++ ++unset ENABLE FIND FRIENDLY MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST ++ ++DEFAULT_CONFIG="# device-mapper-multipath configuration file ++ ++# For a complete list of the default configuration values, run either: ++# # multipath -t ++# or ++# # multipathd show config ++ ++# For a list of configuration options with descriptions, see the ++# multipath.conf man page. ++ ++defaults { ++ user_friendly_names yes ++ find_multipaths yes ++} ++ ++blacklist_exceptions { ++ property \"(SCSI_IDENT_|ID_WWN)\" ++}" ++ ++CONFIGFILE="/etc/multipath.conf" ++OUTPUTFILE="/etc/multipath.conf" ++MULTIPATHDIR="/etc/multipath" ++TMPFILE="/etc/multipath/.multipath.conf.tmp" ++WWIDS=0 ++ ++function usage ++{ ++ echo "usage: $0 " ++ echo "" ++ echo "Commands:" ++ echo "Enable: --enable " ++ echo "Disable: --disable" ++ echo "Only allow certain wwids (instead of enable): --allow " ++ echo "Set user_friendly_names (Default y): --user_friendly_names " ++ echo "Set find_multipaths (Default y): --find_multipaths " ++ echo "Load the dm-multipath modules on enable (Default y): --with_module " ++ echo "start/stop/reload multipathd (Default n): --with_multipathd " ++ echo "select output file (Default /etc/multipath.conf): --outfile " ++ 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 ++ while [ -n "$1" -a -n "$2" ]; do ++ MAJOR=$(echo $1 | tr -d '(,') ++ MINOR=$(echo $2 | tr -d ')') ++ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null` ++ if [ -n "$UUID" ] ; then ++ set_dm_wwid $UUID ++ fi ++ shift 2 ++ done ++} ++ ++function set_dm_wwid ++{ ++ if [[ "$1" =~ ^part[[:digit:]]+-mpath- ]] ; then ++ add_wwid "${1##part*-mpath-}" ++ elif [[ "$1" =~ ^mpath- ]] ; then ++ add_wwid "${1##mpath-}" ++ else ++ get_dm_deps `dmsetup deps -u $1` ++ fi ++} ++ ++function set_wwid ++{ ++ UUID="" ++ if [[ "$1" =~ ^[[:digit:]]+:[[:digit:]]+$ ]] ; then ++ MAJOR=${1%%:*} ++ MINOR=${1##*:} ++ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null` ++ else ++ UUID=`dmsetup info -c --noheadings -o uuid $1 2> /dev/null` ++ fi ++ if [ -n "$UUID" ] ; then ++ set_dm_wwid $UUID ++ else ++ add_wwid "$1" ++ fi ++} ++ ++function parse_args ++{ ++ while [ -n "$1" ]; do ++ case $1 in ++ --enable) ++ ENABLE=1 ++ shift ++ ;; ++ --disable) ++ ENABLE=0 ++ shift ++ ;; ++ --allow) ++ ENABLE=2 ++ if [ -n "$2" ]; then ++ set_wwid $2 ++ shift 2 ++ else ++ usage ++ exit 1 ++ fi ++ ;; ++ --user_friendly_names) ++ if [ -n "$2" ]; then ++ FRIENDLY=$2 ++ shift 2 ++ else ++ usage ++ exit 1 ++ fi ++ ;; ++ --find_multipaths) ++ if [ -n "$2" ]; then ++ FIND=$2 ++ shift 2 ++ else ++ usage ++ exit 1 ++ fi ++ ;; ++ --with_module) ++ if [ -n "$2" ]; then ++ MODULE=$2 ++ shift 2 ++ else ++ usage ++ exit 1 ++ fi ++ ;; ++ --with_multipathd) ++ if [ -n "$2" ]; then ++ MULTIPATHD=$2 ++ shift 2 ++ else ++ usage ++ exit 1 ++ fi ++ ;; ++ --outfile) ++ if [ -n "$2" ]; then ++ OUTPUTFILE=$2 ++ HAVE_OUTFILE=1 ++ shift 2 ++ else ++ usage ++ exit 1 ++ fi ++ ;; ++ *) ++ usage ++ exit ++ esac ++ done ++} ++ ++function validate_args ++{ ++ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$MODULE" ]; then ++ echo "ignoring extra parameters on disable" ++ FRIENDLY="" ++ FIND="" ++ MODULE="" ++ fi ++ if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then ++ echo "--user_friendly_names must be either 'y' or 'n'" ++ exit 1 ++ fi ++ if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then ++ echo "--find_multipaths must be either 'y' or 'n'" ++ exit 1 ++ fi ++ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" ]; then ++ SHOW_STATUS=1 ++ fi ++ if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then ++ echo "--with_module must be either 'y' or 'n'" ++ exit 1 ++ fi ++ if [ -n "$MULTIPATHD" ] && [ "$MULTIPATHD" != "y" -a "$MULTIPATHD" != "n" ]; then ++ echo "--with_multipathd must be either 'y' or 'n'" ++ exit 1 ++ fi ++ if [ "$ENABLE" = 2 -a -z "$HAVE_OUTFILE" ]; then ++ echo "Because --allow makes changes that cannot be automatically reversed," ++ echo "you must set --outfile when you set --allow" ++ exit 1 ++ fi ++} ++ ++function add_blacklist_exceptions ++{ ++ INDEX=0 ++ while [ "$INDEX" -lt "$WWIDS" ] ; do ++ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\ ++ wwid '"\"${WWID_LIST[$INDEX]}\""' ++' $TMPFILE ++ ((INDEX++)) ++ done ++} ++ ++umask 0077 ++ ++parse_args "$@" ++ ++validate_args ++ ++if [ ! -d "$MULTIPATHDIR" ]; then ++ echo "/etc/multipath/ does not exist. failing" ++ exit 1 ++fi ++ ++rm $TMPFILE 2> /dev/null ++echo "$DEFAULT_CONFIG" > $TMPFILE ++if [ -f "$CONFIGFILE" ]; then ++ cp $CONFIGFILE $TMPFILE ++fi ++ ++if grep -q "^blacklist[[:space:]]*{" $TMPFILE ; then ++ HAVE_BLACKLIST=1 ++fi ++ ++if grep -q "^blacklist_exceptions[[:space:]]*{" $TMPFILE ; then ++ HAVE_EXCEPTIONS=1 ++fi ++ ++if grep -q "^defaults[[:space:]]*{" $TMPFILE ; then ++ HAVE_DEFAULTS=1 ++fi ++ ++if [ -z "$MODULE" -o "$MODULE" = "y" ]; then ++ if lsmod | grep -q "dm_multipath" ; then ++ HAVE_MODULE=1 ++ else ++ HAVE_MODULE=0 ++ fi ++fi ++ ++if [ "$MULTIPATHD" = "y" ]; then ++ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then ++ HAVE_MULTIPATHD=1 ++ else ++ HAVE_MULTIPATHD=0 ++ fi ++fi ++ ++if [ "$HAVE_BLACKLIST" = "1" ]; then ++ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then ++ HAVE_DISABLE=1 ++ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then ++ HAVE_DISABLE=0 ++ fi ++fi ++ ++if [ "$HAVE_BLACKLIST" = "1" ]; then ++ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then ++ HAVE_WWID_DISABLE=1 ++ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then ++ HAVE_WWID_DISABLE=0 ++ fi ++fi ++ ++if [ "$HAVE_DEFAULTS" = "1" ]; then ++ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then ++ HAVE_FIND=1 ++ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then ++ HAVE_FIND=0 ++ fi ++ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then ++ HAVE_FRIENDLY=1 ++ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then ++ HAVE_FRIENDLY=0 ++ fi ++fi ++ ++if [ -n "$SHOW_STATUS" ]; then ++ if [ -z "$HAVE_DISABLE" -o "$HAVE_DISABLE" = 0 ]; then ++ echo "multipath is enabled" ++ else ++ echo "multipath is disabled" ++ fi ++ if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then ++ echo "find_multipaths is disabled" ++ else ++ echo "find_multipaths is enabled" ++ fi ++ if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then ++ echo "user_friendly_names is disabled" ++ else ++ echo "user_friendly_names is enabled" ++ fi ++ if [ -n "$HAVE_MODULE" ]; then ++ if [ "$HAVE_MODULE" = 1 ]; then ++ echo "dm_multipath module is loaded" ++ else ++ echo "dm_multipath module is not loaded" ++ fi ++ fi ++ if [ -z "$HAVE_MULTIPATHD" ]; then ++ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then ++ HAVE_MULTIPATHD=1 ++ else ++ HAVE_MULTIPATHD=0 ++ fi ++ fi ++ if [ "$HAVE_MULTIPATHD" = 1 ]; then ++ echo "multipathd is running" ++ else ++ echo "multipathd is not running" ++ fi ++ exit 0 ++fi ++ ++if [ -z "$HAVE_BLACKLIST" ]; then ++ cat >> $TMPFILE <<- _EOF_ ++ ++blacklist { ++} ++_EOF_ ++fi ++ ++if [ -z "$HAVE_DEFAULTS" ]; then ++ cat >> $TMPFILE <<- _EOF_ ++ ++defaults { ++} ++_EOF_ ++fi ++ ++if [ "$ENABLE" = 2 ]; then ++ if [ "$HAVE_DISABLE" = 1 ]; then ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE ++ fi ++ if [ -z "$HAVE_WWID_DISABLE" ]; then ++ sed -i '/^blacklist[[:space:]]*{/ a\ ++ wwid ".*" ++' $TMPFILE ++ elif [ "$HAVE_WWID_DISABLE" = 0 ]; then ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE ++ fi ++ if [ "$HAVE_EXCEPTIONS" = 1 ]; then ++ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE ++ else ++ cat >> $TMPFILE <<- _EOF_ ++ ++blacklist_exceptions { ++} ++_EOF_ ++ fi ++ add_blacklist_exceptions ++elif [ "$ENABLE" = 1 ]; then ++ if [ "$HAVE_DISABLE" = 1 ]; then ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE ++ fi ++elif [ "$ENABLE" = 0 ]; then ++ if [ -z "$HAVE_DISABLE" ]; then ++ sed -i '/^blacklist[[:space:]]*{/ a\ ++ devnode ".*" ++' $TMPFILE ++ elif [ "$HAVE_DISABLE" = 0 ]; then ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE ++ fi ++fi ++ ++if [ "$FIND" = "n" ]; then ++ if [ "$HAVE_FIND" = 1 ]; then ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE ++ CHANGED_CONFIG=1 ++ fi ++elif [ "$FIND" = "y" ]; then ++ if [ -z "$HAVE_FIND" ]; then ++ sed -i '/^defaults[[:space:]]*{/ a\ ++ find_multipaths yes ++' $TMPFILE ++ CHANGED_CONFIG=1 ++ elif [ "$HAVE_FIND" = 0 ]; then ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE ++ CHANGED_CONFIG=1 ++ fi ++fi ++ ++if [ "$FRIENDLY" = "n" ]; then ++ if [ "$HAVE_FRIENDLY" = 1 ]; then ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE ++ CHANGED_CONFIG=1 ++ fi ++elif [ "$FRIENDLY" = "y" ]; then ++ if [ -z "$HAVE_FRIENDLY" ]; then ++ sed -i '/^defaults[[:space:]]*{/ a\ ++ user_friendly_names yes ++' $TMPFILE ++ CHANGED_CONFIG=1 ++ elif [ "$HAVE_FRIENDLY" = 0 ]; then ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE ++ CHANGED_CONFIG=1 ++ fi ++fi ++ ++if [ -f "$OUTPUTFILE" ]; then ++ cp $OUTPUTFILE $OUTPUTFILE.old ++ if [ $? != 0 ]; then ++ echo "failed to backup old config file, $OUTPUTFILE not updated" ++ exit 1 ++ fi ++fi ++ ++cp $TMPFILE $OUTPUTFILE ++if [ $? != 0 ]; then ++ echo "failed to copy new config file into place, check $OUTPUTFILE is still OK" ++ exit 1 ++fi ++ ++rm -f $TMPFILE ++ ++if [ "$ENABLE" = 1 ]; then ++ if [ "$HAVE_MODULE" = 0 ]; then ++ modprobe dm_multipath ++ fi ++ if [ "$HAVE_MULTIPATHD" = 0 ]; then ++ systemctl start multipathd.service ++ fi ++elif [ "$ENABLE" = 0 ]; then ++ if [ "$HAVE_MULTIPATHD" = 1 ]; then ++ systemctl stop multipathd.service ++ fi ++elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then ++ systemctl reload multipathd.service ++fi +diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8 +new file mode 100644 +index 0000000..5b7ae0c +--- /dev/null ++++ b/multipath/mpathconf.8 +@@ -0,0 +1,119 @@ ++.TH MPATHCONF 8 "June 2010" "" "Linux Administrator's Manual" ++.SH NAME ++mpathconf - A tool for configuring device-mapper-multipath ++.SH SYNOPSIS ++.B mpathconf ++.RB [\| commands \|] ++.RB [\| options \|] ++.SH DESCRIPTION ++.B mpathconf ++is a utility that creates or modifies ++.B /etc/multipath.conf. ++It can enable or disable multipathing and configure some common options. ++.B mpathconf ++can also load the ++.B dm_multipath ++module, start and stop the ++.B multipathd ++daemon, and configure the ++.B multipathd ++service to start automatically or not. If ++.B mpathconf ++is called with no commands, it will display the current configuration, but ++will not create of modify ++.B /etc/multipath.conf ++ ++The default options for mpathconf are ++.B --with_module ++The ++.B --with_multipathd ++option is not set by default. Enabling multipathing will load the ++.B dm_multipath ++module but it will not immediately start it. This is so ++that users can manually edit their config file if necessary, before starting ++.B multipathd. ++ ++If ++.B /etc/multipath.conf ++already exists, mpathconf will edit it. If it does not exist, mpathconf will ++create a default file with ++.B user_friendly_names ++and ++.B find_multipaths ++set. To disable these, use the ++.B --user_friendly_names n ++and ++.B --find_multipaths n ++options ++.SH COMMANDS ++.TP ++.B --enable ++Removes any line that blacklists all device nodes from the ++.B /etc/multipath.conf ++blacklist section. Also, creates ++.B /etc/multipath.conf ++if it doesn't exist. ++.TP ++.B --disable ++Adds a line that blacklists all device nodes to the ++.B /etc/multipath.conf ++blacklist section. If no blacklist section exists, it will create one. ++.TP ++.B --allow \fB\fP ++Modifies the \fB/etc/multipath/conf\fP blacklist to blacklist all ++wwids and the blacklist_exceptions to whitelist \fB\fP. \fB\fP ++can be in the form of MAJOR:MINOR, a wwid, or the name of a device-mapper ++device, either a multipath device, or any device on stacked on top of one or ++more multipath devices. This command can be used multiple times to allow ++multiple devices. \fBNOTE:\fP This action will create a configuration file that ++mpathconf will not be able to revert back to its previous state. Because ++of this, \fB--outfile\fP is required when using \fB--allow\fP. ++.TP ++.B --user_friendly_name \fP { \fBy\fP | \fBn\fP } ++If set to \fBy\fP, this adds the line ++.B user_friendly_names yes ++to the ++.B /etc/multipath.conf ++defaults section. If set to \fBn\fP, this removes the line, if present. This ++command can be used along with any other command. ++.TP ++.B --find_multipaths\fP { \fBy\fP | \fBn\fP } ++If set to \fBy\fP, this adds the line ++.B find_multipaths yes ++to the ++.B /etc/multipath.conf ++defaults section. If set to \fBn\fP, this removes the line, if present. This ++command can be used aldong with any other command. ++.TP ++.B --outfile \fB\fP ++Write the resulting multipath configuration to \fB\fP instead of ++\fB/etc/multipath.conf\fP. ++.SH OPTIONS ++.TP ++.B --with_module\fP { \fBy\fP | \fBn\fP } ++If set to \fBy\fP, this runs ++.B modprobe dm_multipath ++to install the multipath modules. This option only works with the ++.B --enable ++command. This option is set to \fBy\fP by default. ++.TP ++.B --with_multipathd { \fBy\fP | \fBn\fP } ++If set to \fBy\fP, this runs ++.B service multipathd start ++to start the multipathd daemon on \fB--enable\fP, ++.B service multipathd stop ++to stop the multipathd daemon on \fB--disable\fP, and ++.B service multipathd reload ++to reconfigure multipathd on \fB--user_frindly_names\fP and ++\fB--find_multipaths\fP. ++This option is set to \fBn\fP by default. ++.SH FILES ++.BR /etc/multipath.conf ++.SH "SEE ALSO" ++.BR multipath.conf (5), ++.BR modprobe (8), ++.BR multipath (8), ++.BR multipathd (8), ++.BR service (8), ++.SH AUTHOR ++Benjamin Marzinski +-- +2.17.2 + diff --git a/SOURCES/0023-BZ-1673167-fixup-wwid-recheck.patch b/SOURCES/0023-BZ-1673167-fixup-wwid-recheck.patch deleted file mode 100644 index efbcf86..0000000 --- a/SOURCES/0023-BZ-1673167-fixup-wwid-recheck.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Mon, 25 Feb 2019 21:55:37 -0600 -Subject: [PATCH] BZ 1673167: fixup wwid recheck - -When multipathd was ignoring the failed get_uid output, there was still -a way for the wwid to get set to 0. Fix that. - -Signed-off-by: Benjamin Marzinski ---- - multipathd/main.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/multipathd/main.c b/multipathd/main.c -index 30eb8fe..1dc53b2 100644 ---- a/multipathd/main.c -+++ b/multipathd/main.c -@@ -1211,9 +1211,10 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) - goto out; - - strcpy(wwid, pp->wwid); -- rc = get_uid(pp, pp->state, uev->udev); -+ get_uid(pp, pp->state, uev->udev); - -- if (rc == 0 && strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { -+ if (strlen(pp->wwid) && -+ strncmp(wwid, pp->wwid, WWID_SIZE) != 0) { - condlog(0, "%s: path wwid changed from '%s' to '%s'. %s", - uev->kernel, wwid, pp->wwid, - (disable_changed_wwids ? "disallowing" : -@@ -1229,8 +1230,10 @@ uev_update_path (struct uevent *uev, struct vectors * vecs) - goto out; - } - } else { -- if (rc == 0) -+ if (strlen(pp->wwid)) - pp->wwid_changed = 0; -+ else -+ strcpy(pp->wwid, wwid); - udev_device_unref(pp->udev); - pp->udev = udev_device_ref(uev->udev); - conf = get_multipath_config(); --- -2.17.2 - diff --git a/SOURCES/0023-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch b/SOURCES/0023-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch new file mode 100644 index 0000000..86bb2db --- /dev/null +++ b/SOURCES/0023-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch @@ -0,0 +1,169 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 17 Oct 2014 11:20:34 -0500 +Subject: [PATCH] RH: add wwids from kernel cmdline mpath.wwids with -A + +This patch adds another option to multipath, "-A", which reads +/proc/cmdline for mpath.wwid= options, and adds any wwids it finds +to /etc/multipath/wwids. While this isn't usually important during +normal operation, since these wwids should already be added, it can be +helpful during installation, to make sure that multipath can claim +devices as its own, before LVM or something else makes use of them. The +patch also execs "/sbin/multipath -A" before running multipathd in +multipathd.service + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/wwids.c | 44 +++++++++++++++++++++++++++++++++++ + libmultipath/wwids.h | 1 + + multipath/main.c | 10 ++++++-- + multipath/multipath.8 | 7 +++++- + multipathd/multipathd.service | 1 + + 5 files changed, 60 insertions(+), 3 deletions(-) + +diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c +index 53e7951..39e08cd 100644 +--- a/libmultipath/wwids.c ++++ b/libmultipath/wwids.c +@@ -443,3 +443,47 @@ int op ## _wwid(const char *wwid) \ + declare_failed_wwid_op(is_failed, false) + declare_failed_wwid_op(mark_failed, true) + declare_failed_wwid_op(unmark_failed, true) ++ ++int remember_cmdline_wwid(void) ++{ ++ FILE *f = NULL; ++ char buf[LINE_MAX], *next, *ptr; ++ int ret = 0; ++ ++ f = fopen("/proc/cmdline", "re"); ++ if (!f) { ++ condlog(0, "can't open /proc/cmdline : %s", strerror(errno)); ++ return -1; ++ } ++ ++ if (!fgets(buf, sizeof(buf), f)) { ++ if (ferror(f)) ++ condlog(0, "read of /proc/cmdline failed : %s", ++ strerror(errno)); ++ else ++ condlog(0, "couldn't read /proc/cmdline"); ++ fclose(f); ++ return -1; ++ } ++ fclose(f); ++ next = buf; ++ while((ptr = strstr(next, "mpath.wwid="))) { ++ ptr += 11; ++ next = strpbrk(ptr, " \t\n"); ++ if (next) { ++ *next = '\0'; ++ next++; ++ } ++ if (strlen(ptr)) { ++ if (remember_wwid(ptr) != 0) ++ ret = -1; ++ } ++ else { ++ condlog(0, "empty mpath.wwid kernel command line option"); ++ ret = -1; ++ } ++ if (!next) ++ break; ++ } ++ return ret; ++} +diff --git a/libmultipath/wwids.h b/libmultipath/wwids.h +index 0c6ee54..e32a0b0 100644 +--- a/libmultipath/wwids.h ++++ b/libmultipath/wwids.h +@@ -17,6 +17,7 @@ int remember_wwid(char *wwid); + int check_wwids_file(char *wwid, int write_wwid); + int remove_wwid(char *wwid); + int replace_wwids(vector mp); ++int remember_cmdline_wwid(void); + + enum { + WWID_IS_NOT_FAILED = 0, +diff --git a/multipath/main.c b/multipath/main.c +index 69141db..e7771c0 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -133,7 +133,7 @@ usage (char * progname) + { + fprintf (stderr, VERSION_STRING); + fprintf (stderr, "Usage:\n"); +- fprintf (stderr, " %s [-a|-c|-w|-W] [-d] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); ++ fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); + fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [-R num] [dev]\n", progname); + fprintf (stderr, " %s -F [-v lvl] [-R num]\n", progname); + fprintf (stderr, " %s [-t|-T]\n", progname); +@@ -147,6 +147,8 @@ usage (char * progname) + " -f flush a multipath device map\n" + " -F flush all multipath device maps\n" + " -a add a device wwid to the wwids file\n" ++ " -A add devices from kernel command line mpath.wwids\n" ++ " parameters to wwids file\n" + " -c check if a device should be a path in a multipath device\n" + " -C check if a multipath device has usable paths\n" + " -q allow queue_if_no_path when multipathd is not running\n" +@@ -870,7 +872,7 @@ main (int argc, char *argv[]) + exit(RTVL_FAIL); + multipath_conf = conf; + conf->retrigger_tries = 0; +- while ((arg = getopt(argc, argv, ":adcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":aAdcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) { + switch(arg) { + case 1: printf("optarg : %s\n",optarg); + break; +@@ -940,6 +942,10 @@ main (int argc, char *argv[]) + case 'T': + cmd = CMD_DUMP_CONFIG; + break; ++ case 'A': ++ if (remember_cmdline_wwid() != 0) ++ exit(RTVL_FAIL); ++ exit(RTVL_OK); + case 'h': + usage(argv[0]); + exit(RTVL_OK); +diff --git a/multipath/multipath.8 b/multipath/multipath.8 +index 9cdd05a..8befc45 100644 +--- a/multipath/multipath.8 ++++ b/multipath/multipath.8 +@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig. + .B multipath + .RB [\| \-v\ \c + .IR level \|] +-.B -W ++.RB [\| \-A | \-W \|] + . + .LP + .B multipath +@@ -145,6 +145,11 @@ device mapper, path checkers ...). + Add the WWID for the specified device to the WWIDs file. + . + .TP ++.B \-A ++Add the WWIDs from any kernel command line \fImpath.wwid\fR parameters to the ++WWIDs file. ++. ++.TP + .B \-w + Remove the WWID for the specified device from the WWIDs file. + . +diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service +index 17434ce..0fbcc46 100644 +--- a/multipathd/multipathd.service ++++ b/multipathd/multipathd.service +@@ -15,6 +15,7 @@ Type=notify + NotifyAccess=main + LimitCORE=infinity + ExecStartPre=-/sbin/modprobe -a scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm-multipath ++ExecStartPre=-/sbin/multipath -A + ExecStart=/sbin/multipathd -d -s + ExecReload=/sbin/multipathd reconfigure + TasksMax=infinity +-- +2.17.2 + diff --git a/SOURCES/0024-BZ-1723746-check-on-multipathd-without-starting-it.patch b/SOURCES/0024-BZ-1723746-check-on-multipathd-without-starting-it.patch deleted file mode 100644 index 47300fb..0000000 --- a/SOURCES/0024-BZ-1723746-check-on-multipathd-without-starting-it.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Benjamin Marzinski -Date: Thu, 18 Apr 2019 12:49:46 -0500 -Subject: [PATCH] BZ 1700451: check on multipathd without starting it - -When "multipath -u" is run, it checks if multipathd is running. -Currently it does this by trying to connect to the mutipathd socket. -This can cause problems during boot. The multipathd.socket systemd unit -file will cause "multipath -u" to wait until multipathd has been started -before continuing. If there is a lot of activity on the system, -multipathd may not start up immediately, causing block device -initialization to be delayed, potentially until after systemd times -waiting for the device. To avoid this, multipath now checks if -multipathd is running by reading /run/multipathd.pid and checking the -/proc//comm to verify that multipathd is really running with this -pid. This avoids forcing "multipath -u" to wait on multipathd starting -up. - -As an alternative to this patch, multipath could simply switch the order -of the calls to systemd_service_enabled() and mpath_connect(). This would -make multipath only try to connect with multipathd if it wasn't enabled in -systemd, so that it wouldn't autostart. - -Another alternative is to do away with multipathd.socket. Since multipathd -needs to always be running in order to get uevents, there isn't much value -in having it autoactivate when it gets an interactive command. - -Signed-off-by: Benjamin Marzinski ---- - multipath/main.c | 60 +++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 54 insertions(+), 6 deletions(-) - -diff --git a/multipath/main.c b/multipath/main.c -index 0545226..c2aa20d 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -850,6 +850,58 @@ out: - return r; - } - -+int is_multipathd_running(void) -+{ -+ FILE *f = NULL; -+ char buf[16]; -+ char path[PATH_MAX]; -+ int pid; -+ char *end; -+ -+ f = fopen(DEFAULT_PIDFILE, "r"); -+ if (!f) { -+ if (errno != ENOENT) -+ condlog(4, "can't open " DEFAULT_PIDFILE ": %s", -+ strerror(errno)); -+ return 0; -+ } -+ if (!fgets(buf, sizeof(buf), f)) { -+ if (ferror(f)) -+ condlog(4, "read of " DEFAULT_PIDFILE " failed: %s", -+ strerror(errno)); -+ fclose(f); -+ return 0; -+ } -+ fclose(f); -+ errno = 0; -+ strchop(buf); -+ pid = strtol(buf, &end, 10); -+ if (errno != 0 || pid <= 0 || *end != '\0') { -+ condlog(4, "invalid contents in " DEFAULT_PIDFILE ": '%s'", -+ buf); -+ return 0; -+ } -+ snprintf(path, sizeof(path), "/proc/%d/comm", pid); -+ f = fopen(path, "r"); -+ if (!f) { -+ if (errno != ENOENT) -+ condlog(4, "can't open %s: %s", path, strerror(errno)); -+ return 0; -+ } -+ if (!fgets(buf, sizeof(buf), f)) { -+ if (ferror(f)) -+ condlog(4, "read of %s failed: %s", path, -+ strerror(errno)); -+ fclose(f); -+ return 0; -+ } -+ fclose(f); -+ strchop(buf); -+ if (strcmp(buf, "multipathd") != 0) -+ return 0; -+ return 1; -+} -+ - int - main (int argc, char *argv[]) - { -@@ -1031,17 +1083,13 @@ main (int argc, char *argv[]) - } - if (cmd == CMD_VALID_PATH && - dev_type == DEV_UEVENT) { -- int fd; -- -- fd = mpath_connect(); -- if (fd == -1) { -+ if (!is_multipathd_running()) { - condlog(3, "%s: daemon is not running", dev); - if (!systemd_service_enabled(dev)) { - r = print_cmd_valid(1, NULL, conf); - goto out; - } -- } else -- mpath_disconnect(fd); -+ } - } - - if (cmd == CMD_REMOVE_WWID && !dev) { --- -2.17.2 - diff --git a/SOURCES/0024-RH-warn-on-invalid-regex-instead-of-failing.patch b/SOURCES/0024-RH-warn-on-invalid-regex-instead-of-failing.patch new file mode 100644 index 0000000..ded4ccb --- /dev/null +++ b/SOURCES/0024-RH-warn-on-invalid-regex-instead-of-failing.patch @@ -0,0 +1,121 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Mon, 6 Nov 2017 21:39:28 -0600 +Subject: [PATCH] RH: warn on invalid regex instead of failing + +multipath.conf used to allow "*" as a match everything regular expression, +instead of requiring ".*". Instead of erroring when the old style +regular expressions are used, it should print a warning and convert +them. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/dict.c | 27 +++++++++++++++++++++------ + libmultipath/parser.c | 13 +++++++++++++ + libmultipath/parser.h | 1 + + 3 files changed, 35 insertions(+), 6 deletions(-) + +diff --git a/libmultipath/dict.c b/libmultipath/dict.c +index 96815f8..3b1b652 100644 +--- a/libmultipath/dict.c ++++ b/libmultipath/dict.c +@@ -58,6 +58,21 @@ set_str(vector strvec, void *ptr) + return 0; + } + ++static int ++set_regex(vector strvec, void *ptr) ++{ ++ char **str_ptr = (char **)ptr; ++ ++ if (*str_ptr) ++ FREE(*str_ptr); ++ *str_ptr = set_regex_value(strvec); ++ ++ if (!*str_ptr) ++ return 1; ++ ++ return 0; ++} ++ + static int + set_yes_no(vector strvec, void *ptr) + { +@@ -1386,7 +1401,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \ + if (!conf->option) \ + return 1; \ + \ +- buff = set_value(strvec); \ ++ buff = set_regex_value(strvec); \ + if (!buff) \ + return 1; \ + \ +@@ -1402,7 +1417,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \ + if (!conf->option) \ + return 1; \ + \ +- buff = set_value(strvec); \ ++ buff = set_regex_value(strvec); \ + if (!buff) \ + return 1; \ + \ +@@ -1505,16 +1520,16 @@ device_handler(struct config *conf, vector strvec) + return 0; + } + +-declare_hw_handler(vendor, set_str) ++declare_hw_handler(vendor, set_regex) + declare_hw_snprint(vendor, print_str) + +-declare_hw_handler(product, set_str) ++declare_hw_handler(product, set_regex) + declare_hw_snprint(product, print_str) + +-declare_hw_handler(revision, set_str) ++declare_hw_handler(revision, set_regex) + declare_hw_snprint(revision, print_str) + +-declare_hw_handler(bl_product, set_str) ++declare_hw_handler(bl_product, set_regex) + declare_hw_snprint(bl_product, print_str) + + declare_hw_handler(hwhandler, set_str) +diff --git a/libmultipath/parser.c b/libmultipath/parser.c +index 92ef7cf..4289336 100644 +--- a/libmultipath/parser.c ++++ b/libmultipath/parser.c +@@ -384,6 +384,19 @@ set_value(vector strvec) + return alloc; + } + ++void * ++set_regex_value(vector strvec) ++{ ++ char *buff = set_value(strvec); ++ ++ if (buff && strcmp("*", buff) == 0) { ++ condlog(0, "Invalid regular expression \"*\" in multipath.conf. Using \".*\""); ++ FREE(buff); ++ return strdup(".*"); ++ } ++ return buff; ++} ++ + /* non-recursive configuration stream handler */ + static int kw_level = 0; + +diff --git a/libmultipath/parser.h b/libmultipath/parser.h +index 62906e9..b791705 100644 +--- a/libmultipath/parser.h ++++ b/libmultipath/parser.h +@@ -77,6 +77,7 @@ extern void dump_keywords(vector keydump, int level); + extern void free_keywords(vector keywords); + extern vector alloc_strvec(char *string); + extern void *set_value(vector strvec); ++extern void *set_regex_value(vector strvec); + extern int process_file(struct config *conf, char *conf_file); + extern struct keyword * find_keyword(vector keywords, vector v, char * name); + int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, +-- +2.17.2 + diff --git a/SOURCES/0025-BZ-1723746-test-socket-connection-in-non-blocking-mo.patch b/SOURCES/0025-BZ-1723746-test-socket-connection-in-non-blocking-mo.patch deleted file mode 100644 index b1dd2ab..0000000 --- a/SOURCES/0025-BZ-1723746-test-socket-connection-in-non-blocking-mo.patch +++ /dev/null @@ -1,223 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Martin Wilck -Date: Wed, 24 Apr 2019 11:07:59 +0200 -Subject: [PATCH] BZ 1700451: test socket connection in non-blocking mode - -Since commit d7188fcd "multipathd: start daemon after udev trigger", -multipathd startup is delayed during boot until after "udev settle" -terminates. But "multipath -u" is run by udev workers for storage devices, -and attempts to connect to the multipathd socket. This causes a start job -for multipathd to be scheduled by systemd, but that job won't be started -until "udev settle" finishes. This is not a problem on systems with 129 or -less storage units, because the connect() call of "multipath -u" will -succeed anyway. But on larger systems, the listen backlog of the systemd -socket can be exceeded, which causes connect() calls for the socket to -block until multipathd starts up and begins calling accept(). This creates -a deadlock situation, because "multipath -u" (called by udev workers) -blocks, and thus "udev settle" doesn't finish, delaying multipathd -startup. This situation then persists until either the workers or "udev -settle" time out. In the former case, path devices might be misclassified -as non-multipath devices by "multipath -u". - -Fix this by using a non-blocking socket fd for connect() and interpret the -errno appropriately. - -This patch reverts most of the changes from commit 8cdf6661 "multipath: -check on multipathd without starting it". Instead, "multipath -u" does -access the socket and start multipath again (which is what we want IMO), -but it is now able to detect and handle the "full backlog" situation. - -Signed-off-by: Martin Wilck - -V2: - -Use same error reporting convention in __mpath_connect() as in -mpath_connect() (Hannes Reinecke). We can't easily change the latter, -because it's part of the "public" libmpathcmd API. - -Signed-off-by: Benjamin Marzinski ---- - libmpathcmd/mpath_cmd.c | 24 +++++++++++++- - libmpathcmd/mpath_cmd.h | 15 +++++++++ - multipath/main.c | 70 +++++++++++++---------------------------- - 3 files changed, 60 insertions(+), 49 deletions(-) - -diff --git a/libmpathcmd/mpath_cmd.c b/libmpathcmd/mpath_cmd.c -index 61e6a98..28b2b45 100644 ---- a/libmpathcmd/mpath_cmd.c -+++ b/libmpathcmd/mpath_cmd.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - #include "mpath_cmd.h" - -@@ -93,10 +94,11 @@ static size_t write_all(int fd, const void *buf, size_t len) - /* - * connect to a unix domain socket - */ --int mpath_connect(void) -+int __mpath_connect(int nonblocking) - { - int fd, len; - struct sockaddr_un addr; -+ int flags = 0; - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_LOCAL; -@@ -108,14 +110,34 @@ int mpath_connect(void) - if (fd == -1) - return -1; - -+ if (nonblocking) { -+ flags = fcntl(fd, F_GETFL, 0); -+ if (flags != -1) -+ (void)fcntl(fd, F_SETFL, flags|O_NONBLOCK); -+ } -+ - if (connect(fd, (struct sockaddr *)&addr, len) == -1) { -+ int err = errno; -+ - close(fd); -+ errno = err; - return -1; - } - -+ if (nonblocking && flags != -1) -+ (void)fcntl(fd, F_SETFL, flags); -+ - return fd; - } - -+/* -+ * connect to a unix domain socket -+ */ -+int mpath_connect(void) -+{ -+ return __mpath_connect(0); -+} -+ - int mpath_disconnect(int fd) - { - return close(fd); -diff --git a/libmpathcmd/mpath_cmd.h b/libmpathcmd/mpath_cmd.h -index df9d938..aa2850b 100644 ---- a/libmpathcmd/mpath_cmd.h -+++ b/libmpathcmd/mpath_cmd.h -@@ -28,6 +28,21 @@ extern "C" { - #define DEFAULT_REPLY_TIMEOUT 4000 - - -+/* -+ * DESCRIPTION: -+ * Same as mpath_connect() (see below) except for the "nonblocking" -+ * parameter. -+ * If "nonblocking" is set, connects in non-blocking mode. This is -+ * useful to avoid blocking if the listening socket's backlog is -+ * exceeded. In this case, errno will be set to EAGAIN. -+ * In case of success, the returned file descriptor is in in blocking -+ * mode, even if "nonblocking" was true. -+ * -+ * RETURNS: -+ * A file descriptor on success. -1 on failure (with errno set). -+ */ -+int __mpath_connect(int nonblocking); -+ - /* - * DESCRIPTION: - * Connect to the running multipathd daemon. On systems with the -diff --git a/multipath/main.c b/multipath/main.c -index c2aa20d..6f2e64b 100644 ---- a/multipath/main.c -+++ b/multipath/main.c -@@ -850,55 +850,29 @@ out: - return r; - } - --int is_multipathd_running(void) -+static int test_multipathd_socket(void) - { -- FILE *f = NULL; -- char buf[16]; -- char path[PATH_MAX]; -- int pid; -- char *end; -+ int fd; -+ /* -+ * "multipath -u" may be run before the daemon is started. In this -+ * case, systemd might own the socket but might delay multipathd -+ * startup until some other unit (udev settle!) has finished -+ * starting. With many LUNs, the listen backlog may be exceeded, which -+ * would cause connect() to block. This causes udev workers calling -+ * "multipath -u" to hang, and thus creates a deadlock, until "udev -+ * settle" times out. To avoid this, call connect() in non-blocking -+ * mode here, and take EAGAIN as indication for a filled-up systemd -+ * backlog. -+ */ - -- f = fopen(DEFAULT_PIDFILE, "r"); -- if (!f) { -- if (errno != ENOENT) -- condlog(4, "can't open " DEFAULT_PIDFILE ": %s", -- strerror(errno)); -- return 0; -- } -- if (!fgets(buf, sizeof(buf), f)) { -- if (ferror(f)) -- condlog(4, "read of " DEFAULT_PIDFILE " failed: %s", -- strerror(errno)); -- fclose(f); -- return 0; -- } -- fclose(f); -- errno = 0; -- strchop(buf); -- pid = strtol(buf, &end, 10); -- if (errno != 0 || pid <= 0 || *end != '\0') { -- condlog(4, "invalid contents in " DEFAULT_PIDFILE ": '%s'", -- buf); -- return 0; -- } -- snprintf(path, sizeof(path), "/proc/%d/comm", pid); -- f = fopen(path, "r"); -- if (!f) { -- if (errno != ENOENT) -- condlog(4, "can't open %s: %s", path, strerror(errno)); -- return 0; -- } -- if (!fgets(buf, sizeof(buf), f)) { -- if (ferror(f)) -- condlog(4, "read of %s failed: %s", path, -- strerror(errno)); -- fclose(f); -- return 0; -- } -- fclose(f); -- strchop(buf); -- if (strcmp(buf, "multipathd") != 0) -- return 0; -+ fd = __mpath_connect(1); -+ if (fd == -1) { -+ if (errno == EAGAIN) -+ condlog(3, "daemon backlog exceeded"); -+ else -+ return 0; -+ } else -+ close(fd); - return 1; - } - -@@ -1083,7 +1057,7 @@ main (int argc, char *argv[]) - } - if (cmd == CMD_VALID_PATH && - dev_type == DEV_UEVENT) { -- if (!is_multipathd_running()) { -+ if (!test_multipathd_socket()) { - condlog(3, "%s: daemon is not running", dev); - if (!systemd_service_enabled(dev)) { - r = print_cmd_valid(1, NULL, conf); --- -2.17.2 - diff --git a/SOURCES/0025-RH-reset-default-find_mutipaths-value-to-off.patch b/SOURCES/0025-RH-reset-default-find_mutipaths-value-to-off.patch new file mode 100644 index 0000000..2f6bbe9 --- /dev/null +++ b/SOURCES/0025-RH-reset-default-find_mutipaths-value-to-off.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 7 Jun 2018 17:43:52 -0500 +Subject: [PATCH] RH: reset default find_mutipaths value to off + +Upstream has changed to default find_multipaths to "strict". For now +Redhat will retain the previous default of "off". + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/defaults.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h +index 6576939..2ad6308 100644 +--- a/libmultipath/defaults.h ++++ b/libmultipath/defaults.h +@@ -17,7 +17,7 @@ + #define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF + #define DEFAULT_VERBOSITY 2 + #define DEFAULT_REASSIGN_MAPS 0 +-#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_STRICT ++#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_OFF + #define DEFAULT_FAST_IO_FAIL 5 + #define DEFAULT_DEV_LOSS_TMO 600 + #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON +-- +2.17.2 + diff --git a/SOURCES/0026-RH-Fix-nvme-compilation-warning.patch b/SOURCES/0026-RH-Fix-nvme-compilation-warning.patch new file mode 100644 index 0000000..6de061a --- /dev/null +++ b/SOURCES/0026-RH-Fix-nvme-compilation-warning.patch @@ -0,0 +1,26 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 25 Jan 2019 14:54:56 -0600 +Subject: [PATCH] RH: Fix nvme compilation warning + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/nvme/argconfig.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/nvme/argconfig.h b/libmultipath/nvme/argconfig.h +index adb192b..bfd10ef 100644 +--- a/libmultipath/nvme/argconfig.h ++++ b/libmultipath/nvme/argconfig.h +@@ -76,7 +76,7 @@ struct argconfig_commandline_options { + extern "C" { + #endif + +-typedef void argconfig_help_func(); ++typedef void argconfig_help_func(void); + void argconfig_append_usage(const char *str); + void argconfig_print_help(const char *program_desc, + const struct argconfig_commandline_options *options); +-- +2.17.2 + diff --git a/SOURCES/0027-Fix-systemd-version-detection.patch b/SOURCES/0027-Fix-systemd-version-detection.patch new file mode 100644 index 0000000..7414638 --- /dev/null +++ b/SOURCES/0027-Fix-systemd-version-detection.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Igor Gnatenko +Date: Tue, 26 Mar 2019 16:34:32 -0500 +Subject: [PATCH] Fix systemd version detection + +Signed-off-by: Igor Gnatenko +Signed-off-by: Benjamin Marzinski +--- + Makefile.inc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.inc b/Makefile.inc +index b98800a..da49852 100644 +--- a/Makefile.inc ++++ b/Makefile.inc +@@ -37,7 +37,7 @@ endif + + ifndef SYSTEMD + ifeq ($(shell systemctl --version > /dev/null 2>&1 && echo 1), 1) +- SYSTEMD = $(shell systemctl --version 2> /dev/null | sed -n 's/systemd \([0-9]*\)/\1/p') ++ SYSTEMD = $(shell systemctl --version 2> /dev/null | sed -n 's/systemd \([0-9]*\).*/\1/p') + endif + endif + +-- +2.17.2 + diff --git a/SOURCES/0028-RH-attempt-to-get-ANA-info-via-sysfs-first.patch b/SOURCES/0028-RH-attempt-to-get-ANA-info-via-sysfs-first.patch new file mode 100644 index 0000000..36954ad --- /dev/null +++ b/SOURCES/0028-RH-attempt-to-get-ANA-info-via-sysfs-first.patch @@ -0,0 +1,87 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 11 Apr 2019 13:25:42 -0500 +Subject: [PATCH] RH: attempt to get ANA info via sysfs first + +When the ANA prioritizer is run, first see if the "ana_state" sysfs file +exists, and if it does, try to read the state from there. If that fails, +fallback to using an ioctl. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/prioritizers/ana.c | 31 +++++++++++++++++++++++++++++-- + 1 file changed, 29 insertions(+), 2 deletions(-) + +diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c +index 990d935..d84571b 100644 +--- a/libmultipath/prioritizers/ana.c ++++ b/libmultipath/prioritizers/ana.c +@@ -24,6 +24,7 @@ + #include "prio.h" + #include "util.h" + #include "structs.h" ++#include "sysfs.h" + + enum { + ANA_ERR_GETCTRL_FAILED = 1, +@@ -36,6 +37,7 @@ enum { + ANA_ERR_GETNS_FAILED, + ANA_ERR_NO_MEMORY, + ANA_ERR_NO_INFORMATION, ++ ANA_ERR_INVALID_STATE, + }; + + static const char *ana_errmsg[] = { +@@ -49,6 +51,7 @@ static const char *ana_errmsg[] = { + [ANA_ERR_GETNS_FAILED] = "couldn't get namespace info", + [ANA_ERR_NO_MEMORY] = "out of memory", + [ANA_ERR_NO_INFORMATION] = "invalid fd", ++ [ANA_ERR_INVALID_STATE] = "invalid state", + }; + + static const char *anas_string[] = { +@@ -106,6 +109,27 @@ static int get_ana_state(__u32 nsid, __u32 anagrpid, void *ana_log, + return -ANA_ERR_GETANAS_NOTFOUND; + } + ++int get_ana_info_sysfs(struct path *pp) ++{ ++ char state[32]; ++ ++ if (!pp->udev || sysfs_attr_get_value(pp->udev, "ana_state", state, ++ sizeof(state)) <= 0) ++ return -ANA_ERR_NO_INFORMATION; ++ ++ if (strcmp(state, "optimized") == 0) ++ return NVME_ANA_OPTIMIZED; ++ if (strcmp(state, "non-optimized") == 0) ++ return NVME_ANA_NONOPTIMIZED; ++ if (strcmp(state, "inaccessible") == 0) ++ return NVME_ANA_INACCESSIBLE; ++ if (strcmp(state, "persistent-loss") == 0) ++ return NVME_ANA_PERSISTENT_LOSS; ++ if (strcmp(state, "change") == 0) ++ return NVME_ANA_CHANGE; ++ return -ANA_ERR_INVALID_STATE; ++} ++ + int get_ana_info(struct path * pp, unsigned int timeout) + { + int rc; +@@ -208,8 +232,11 @@ int getprio(struct path *pp, char *args, unsigned int timeout) + + if (pp->fd < 0) + rc = -ANA_ERR_NO_INFORMATION; +- else +- rc = get_ana_info(pp, timeout); ++ else { ++ rc = get_ana_info_sysfs(pp); ++ if (rc < 0) ++ rc = get_ana_info(pp, timeout); ++ } + + switch (rc) { + case NVME_ANA_OPTIMIZED: +-- +2.17.2 + diff --git a/SOURCES/0029-BZ-1700451-check-on-multipathd-without-starting-it.patch b/SOURCES/0029-BZ-1700451-check-on-multipathd-without-starting-it.patch new file mode 100644 index 0000000..e2e57c7 --- /dev/null +++ b/SOURCES/0029-BZ-1700451-check-on-multipathd-without-starting-it.patch @@ -0,0 +1,118 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 18 Apr 2019 12:49:46 -0500 +Subject: [PATCH] BZ 1700451: check on multipathd without starting it + +When "multipath -u" is run, it checks if multipathd is running. +Currently it does this by trying to connect to the mutipathd socket. +This can cause problems during boot. The multipathd.socket systemd unit +file will cause "multipath -u" to wait until multipathd has been started +before continuing. If there is a lot of activity on the system, +multipathd may not start up immediately, causing block device +initialization to be delayed, potentially until after systemd times +waiting for the device. To avoid this, multipath now checks if +multipathd is running by reading /run/multipathd.pid and checking the +/proc//comm to verify that multipathd is really running with this +pid. This avoids forcing "multipath -u" to wait on multipathd starting +up. + +As an alternative to this patch, multipath could simply switch the order +of the calls to systemd_service_enabled() and mpath_connect(). This would +make multipath only try to connect with multipathd if it wasn't enabled in +systemd, so that it wouldn't autostart. + +Another alternative is to do away with multipathd.socket. Since multipathd +needs to always be running in order to get uevents, there isn't much value +in having it autoactivate when it gets an interactive command. + +Signed-off-by: Benjamin Marzinski +--- + multipath/main.c | 60 +++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 54 insertions(+), 6 deletions(-) + +diff --git a/multipath/main.c b/multipath/main.c +index e7771c0..632ce4d 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -852,6 +852,58 @@ out: + return r; + } + ++int is_multipathd_running(void) ++{ ++ FILE *f = NULL; ++ char buf[16]; ++ char path[PATH_MAX]; ++ int pid; ++ char *end; ++ ++ f = fopen(DEFAULT_PIDFILE, "r"); ++ if (!f) { ++ if (errno != ENOENT) ++ condlog(4, "can't open " DEFAULT_PIDFILE ": %s", ++ strerror(errno)); ++ return 0; ++ } ++ if (!fgets(buf, sizeof(buf), f)) { ++ if (ferror(f)) ++ condlog(4, "read of " DEFAULT_PIDFILE " failed: %s", ++ strerror(errno)); ++ fclose(f); ++ return 0; ++ } ++ fclose(f); ++ errno = 0; ++ strchop(buf); ++ pid = strtol(buf, &end, 10); ++ if (errno != 0 || pid <= 0 || *end != '\0') { ++ condlog(4, "invalid contents in " DEFAULT_PIDFILE ": '%s'", ++ buf); ++ return 0; ++ } ++ snprintf(path, sizeof(path), "/proc/%d/comm", pid); ++ f = fopen(path, "r"); ++ if (!f) { ++ if (errno != ENOENT) ++ condlog(4, "can't open %s: %s", path, strerror(errno)); ++ return 0; ++ } ++ if (!fgets(buf, sizeof(buf), f)) { ++ if (ferror(f)) ++ condlog(4, "read of %s failed: %s", path, ++ strerror(errno)); ++ fclose(f); ++ return 0; ++ } ++ fclose(f); ++ strchop(buf); ++ if (strcmp(buf, "multipathd") != 0) ++ return 0; ++ return 1; ++} ++ + int + main (int argc, char *argv[]) + { +@@ -1034,17 +1086,13 @@ main (int argc, char *argv[]) + } + if (cmd == CMD_VALID_PATH && + dev_type == DEV_UEVENT) { +- int fd; +- +- fd = mpath_connect(); +- if (fd == -1) { ++ if (!is_multipathd_running()) { + condlog(3, "%s: daemon is not running", dev); + if (!systemd_service_enabled(dev)) { + r = print_cmd_valid(RTVL_NO, NULL, conf); + goto out; + } +- } else +- mpath_disconnect(fd); ++ } + } + + if (cmd == CMD_REMOVE_WWID && !dev) { +-- +2.17.2 + diff --git a/SOURCES/0030-BZ-1700451-test-socket-connection-in-non-blocking-mo.patch b/SOURCES/0030-BZ-1700451-test-socket-connection-in-non-blocking-mo.patch new file mode 100644 index 0000000..36bed26 --- /dev/null +++ b/SOURCES/0030-BZ-1700451-test-socket-connection-in-non-blocking-mo.patch @@ -0,0 +1,223 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Wed, 24 Apr 2019 11:07:59 +0200 +Subject: [PATCH] BZ 1700451: test socket connection in non-blocking mode + +Since commit d7188fcd "multipathd: start daemon after udev trigger", +multipathd startup is delayed during boot until after "udev settle" +terminates. But "multipath -u" is run by udev workers for storage devices, +and attempts to connect to the multipathd socket. This causes a start job +for multipathd to be scheduled by systemd, but that job won't be started +until "udev settle" finishes. This is not a problem on systems with 129 or +less storage units, because the connect() call of "multipath -u" will +succeed anyway. But on larger systems, the listen backlog of the systemd +socket can be exceeded, which causes connect() calls for the socket to +block until multipathd starts up and begins calling accept(). This creates +a deadlock situation, because "multipath -u" (called by udev workers) +blocks, and thus "udev settle" doesn't finish, delaying multipathd +startup. This situation then persists until either the workers or "udev +settle" time out. In the former case, path devices might be misclassified +as non-multipath devices by "multipath -u". + +Fix this by using a non-blocking socket fd for connect() and interpret the +errno appropriately. + +This patch reverts most of the changes from commit 8cdf6661 "multipath: +check on multipathd without starting it". Instead, "multipath -u" does +access the socket and start multipath again (which is what we want IMO), +but it is now able to detect and handle the "full backlog" situation. + +Signed-off-by: Martin Wilck + +V2: + +Use same error reporting convention in __mpath_connect() as in +mpath_connect() (Hannes Reinecke). We can't easily change the latter, +because it's part of the "public" libmpathcmd API. + +Signed-off-by: Benjamin Marzinski +--- + libmpathcmd/mpath_cmd.c | 24 +++++++++++++- + libmpathcmd/mpath_cmd.h | 15 +++++++++ + multipath/main.c | 70 +++++++++++++---------------------------- + 3 files changed, 60 insertions(+), 49 deletions(-) + +diff --git a/libmpathcmd/mpath_cmd.c b/libmpathcmd/mpath_cmd.c +index df4ca54..b681311 100644 +--- a/libmpathcmd/mpath_cmd.c ++++ b/libmpathcmd/mpath_cmd.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + #include "mpath_cmd.h" + +@@ -93,10 +94,11 @@ static size_t write_all(int fd, const void *buf, size_t len) + /* + * connect to a unix domain socket + */ +-int mpath_connect(void) ++int __mpath_connect(int nonblocking) + { + int fd, len; + struct sockaddr_un addr; ++ int flags = 0; + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_LOCAL; +@@ -108,14 +110,34 @@ int mpath_connect(void) + if (fd == -1) + return -1; + ++ if (nonblocking) { ++ flags = fcntl(fd, F_GETFL, 0); ++ if (flags != -1) ++ (void)fcntl(fd, F_SETFL, flags|O_NONBLOCK); ++ } ++ + if (connect(fd, (struct sockaddr *)&addr, len) == -1) { ++ int err = errno; ++ + close(fd); ++ errno = err; + return -1; + } + ++ if (nonblocking && flags != -1) ++ (void)fcntl(fd, F_SETFL, flags); ++ + return fd; + } + ++/* ++ * connect to a unix domain socket ++ */ ++int mpath_connect(void) ++{ ++ return __mpath_connect(0); ++} ++ + int mpath_disconnect(int fd) + { + return close(fd); +diff --git a/libmpathcmd/mpath_cmd.h b/libmpathcmd/mpath_cmd.h +index 15aeb06..ccfd35f 100644 +--- a/libmpathcmd/mpath_cmd.h ++++ b/libmpathcmd/mpath_cmd.h +@@ -34,6 +34,21 @@ extern "C" { + #define DEFAULT_REPLY_TIMEOUT 4000 + + ++/* ++ * DESCRIPTION: ++ * Same as mpath_connect() (see below) except for the "nonblocking" ++ * parameter. ++ * If "nonblocking" is set, connects in non-blocking mode. This is ++ * useful to avoid blocking if the listening socket's backlog is ++ * exceeded. In this case, errno will be set to EAGAIN. ++ * In case of success, the returned file descriptor is in in blocking ++ * mode, even if "nonblocking" was true. ++ * ++ * RETURNS: ++ * A file descriptor on success. -1 on failure (with errno set). ++ */ ++int __mpath_connect(int nonblocking); ++ + /* + * DESCRIPTION: + * Connect to the running multipathd daemon. On systems with the +diff --git a/multipath/main.c b/multipath/main.c +index 632ce4d..3fb6699 100644 +--- a/multipath/main.c ++++ b/multipath/main.c +@@ -852,55 +852,29 @@ out: + return r; + } + +-int is_multipathd_running(void) ++static int test_multipathd_socket(void) + { +- FILE *f = NULL; +- char buf[16]; +- char path[PATH_MAX]; +- int pid; +- char *end; ++ int fd; ++ /* ++ * "multipath -u" may be run before the daemon is started. In this ++ * case, systemd might own the socket but might delay multipathd ++ * startup until some other unit (udev settle!) has finished ++ * starting. With many LUNs, the listen backlog may be exceeded, which ++ * would cause connect() to block. This causes udev workers calling ++ * "multipath -u" to hang, and thus creates a deadlock, until "udev ++ * settle" times out. To avoid this, call connect() in non-blocking ++ * mode here, and take EAGAIN as indication for a filled-up systemd ++ * backlog. ++ */ + +- f = fopen(DEFAULT_PIDFILE, "r"); +- if (!f) { +- if (errno != ENOENT) +- condlog(4, "can't open " DEFAULT_PIDFILE ": %s", +- strerror(errno)); +- return 0; +- } +- if (!fgets(buf, sizeof(buf), f)) { +- if (ferror(f)) +- condlog(4, "read of " DEFAULT_PIDFILE " failed: %s", +- strerror(errno)); +- fclose(f); +- return 0; +- } +- fclose(f); +- errno = 0; +- strchop(buf); +- pid = strtol(buf, &end, 10); +- if (errno != 0 || pid <= 0 || *end != '\0') { +- condlog(4, "invalid contents in " DEFAULT_PIDFILE ": '%s'", +- buf); +- return 0; +- } +- snprintf(path, sizeof(path), "/proc/%d/comm", pid); +- f = fopen(path, "r"); +- if (!f) { +- if (errno != ENOENT) +- condlog(4, "can't open %s: %s", path, strerror(errno)); +- return 0; +- } +- if (!fgets(buf, sizeof(buf), f)) { +- if (ferror(f)) +- condlog(4, "read of %s failed: %s", path, +- strerror(errno)); +- fclose(f); +- return 0; +- } +- fclose(f); +- strchop(buf); +- if (strcmp(buf, "multipathd") != 0) +- return 0; ++ fd = __mpath_connect(1); ++ if (fd == -1) { ++ if (errno == EAGAIN) ++ condlog(3, "daemon backlog exceeded"); ++ else ++ return 0; ++ } else ++ close(fd); + return 1; + } + +@@ -1086,7 +1060,7 @@ main (int argc, char *argv[]) + } + if (cmd == CMD_VALID_PATH && + dev_type == DEV_UEVENT) { +- if (!is_multipathd_running()) { ++ if (!test_multipathd_socket()) { + condlog(3, "%s: daemon is not running", dev); + if (!systemd_service_enabled(dev)) { + r = print_cmd_valid(RTVL_NO, NULL, conf); +-- +2.17.2 + diff --git a/SOURCES/0031-libmultipath-handle-clock_gettime-failures-in-tur-ch.patch b/SOURCES/0031-libmultipath-handle-clock_gettime-failures-in-tur-ch.patch new file mode 100644 index 0000000..cb3aa70 --- /dev/null +++ b/SOURCES/0031-libmultipath-handle-clock_gettime-failures-in-tur-ch.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 16 May 2019 12:41:33 -0500 +Subject: [PATCH] libmultipath: handle clock_gettime failures in tur checker + +If clock_gettime() fails, and multipathd can't figure out when it should +time out, it should just default to assuming that it has already timed +out. Found by coverity. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/checkers/tur.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c +index 6b08dbb..717353e 100644 +--- a/libmultipath/checkers/tur.c ++++ b/libmultipath/checkers/tur.c +@@ -290,7 +290,12 @@ static void *tur_thread(void *ctx) + + static void tur_timeout(struct timespec *tsp) + { +- clock_gettime(CLOCK_MONOTONIC, tsp); ++ if (clock_gettime(CLOCK_MONOTONIC, tsp) != 0) { ++ /* can't get time. clear tsp to not wait */ ++ tsp->tv_sec = 0; ++ tsp->tv_nsec = 0; ++ return; ++ } + tsp->tv_nsec += 1000 * 1000; /* 1 millisecond */ + normalize_timespec(tsp); + } +@@ -300,8 +305,12 @@ static void tur_set_async_timeout(struct checker *c) + struct tur_checker_context *ct = c->context; + struct timespec now; + +- clock_gettime(CLOCK_MONOTONIC, &now); +- ct->time = now.tv_sec + c->timeout; ++ if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) ++ /* can't get time. clear time to always timeout on ++ * next path check */ ++ ct->time = 0; ++ else ++ ct->time = now.tv_sec + c->timeout; + } + + static int tur_check_async_timeout(struct checker *c) +@@ -309,7 +318,9 @@ static int tur_check_async_timeout(struct checker *c) + struct tur_checker_context *ct = c->context; + struct timespec now; + +- clock_gettime(CLOCK_MONOTONIC, &now); ++ if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) ++ /* can't get time. assume we've timed out */ ++ return 1; + return (now.tv_sec > ct->time); + } + +-- +2.17.2 + diff --git a/SOURCES/0032-kpartx-fail-if-dup-of-dasd-file-descriptor-fails.patch b/SOURCES/0032-kpartx-fail-if-dup-of-dasd-file-descriptor-fails.patch new file mode 100644 index 0000000..4b25518 --- /dev/null +++ b/SOURCES/0032-kpartx-fail-if-dup-of-dasd-file-descriptor-fails.patch @@ -0,0 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 16 May 2019 12:55:16 -0500 +Subject: [PATCH] kpartx: fail if dup() of dasd file descriptor fails + +If kpartx fails to create a copy of the dasd file descriptor, it should +fail, instead of treating the error value as a valid fd. Found by +coverity. + +Signed-off-by: Benjamin Marzinski +--- + kpartx/dasd.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/kpartx/dasd.c b/kpartx/dasd.c +index 61b609a..d95d8ca 100644 +--- a/kpartx/dasd.c ++++ b/kpartx/dasd.c +@@ -138,6 +138,8 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns) + return -1; + } else { + fd_dasd = dup(fd); ++ if (fd_dasd < 0) ++ return -1; + } + + if (ioctl(fd_dasd, BIODASDINFO, (unsigned long)&info) != 0) { +-- +2.17.2 + diff --git a/SOURCES/0033-multipathd-fix-REALLOC_REPLY-with-max-length-reply.patch b/SOURCES/0033-multipathd-fix-REALLOC_REPLY-with-max-length-reply.patch new file mode 100644 index 0000000..aeede71 --- /dev/null +++ b/SOURCES/0033-multipathd-fix-REALLOC_REPLY-with-max-length-reply.patch @@ -0,0 +1,49 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 16 May 2019 13:31:35 -0500 +Subject: [PATCH] multipathd: fix REALLOC_REPLY with max length reply + +Commit cd5a9797e added code to REALLOC_REPLY() that intended to stop +growing the reply buffer after it reached a maximum size. However this +coded didn't stop the realloc() from happening. Worse, if the realloci() +failed, multipathd would double free the reply buffer. Found by +Coverity. + +Fixes: cd5a9797e "libmpathcmd(coverity): limit reply length" +Signed-off-by: Benjamin Marzinski +--- + multipathd/cli.h | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/multipathd/cli.h b/multipathd/cli.h +index f3fa077..32dcffa 100644 +--- a/multipathd/cli.h ++++ b/multipathd/cli.h +@@ -100,15 +100,16 @@ enum { + if (m >= MAX_REPLY_LEN) { \ + condlog(1, "Warning: max reply length exceeded"); \ + free(tmp); \ +- r = NULL; \ ++ (r) = NULL; \ ++ } else { \ ++ (r) = REALLOC((r), (m) * 2); \ ++ if ((r)) { \ ++ memset((r) + (m), 0, (m)); \ ++ (m) *= 2; \ ++ } \ ++ else \ ++ free(tmp); \ + } \ +- (r) = REALLOC((r), (m) * 2); \ +- if ((r)) { \ +- memset((r) + (m), 0, (m)); \ +- (m) *= 2; \ +- } \ +- else \ +- free(tmp); \ + } \ + } while (0) + +-- +2.17.2 + diff --git a/SOURCES/0034-multipathd-handle-NULL-return-from-genhelp_handler.patch b/SOURCES/0034-multipathd-handle-NULL-return-from-genhelp_handler.patch new file mode 100644 index 0000000..5cdb6f5 --- /dev/null +++ b/SOURCES/0034-multipathd-handle-NULL-return-from-genhelp_handler.patch @@ -0,0 +1,43 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Thu, 16 May 2019 15:44:20 -0500 +Subject: [PATCH] multipathd: handle NULL return from genhelp_handler + +If parse_cmd() wasn't checking if genhelp_handler() returned NULL. It +was simply assuming that it got a string. Instead, it should just return +and error. Found by Coverity. + +Signed-off-by: Benjamin Marzinski +--- + multipathd/cli.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/multipathd/cli.c b/multipathd/cli.c +index ca176a9..17795b6 100644 +--- a/multipathd/cli.c ++++ b/multipathd/cli.c +@@ -467,6 +467,8 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data, int timeout ) + + if (r) { + *reply = genhelp_handler(cmd, r); ++ if (*reply == NULL) ++ return EINVAL; + *len = strlen(*reply) + 1; + return 0; + } +@@ -474,9 +476,11 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data, int timeout ) + h = find_handler(fingerprint(cmdvec)); + + if (!h || !h->fn) { ++ free_keys(cmdvec); + *reply = genhelp_handler(cmd, EINVAL); ++ if (*reply == NULL) ++ return EINVAL; + *len = strlen(*reply) + 1; +- free_keys(cmdvec); + return 0; + } + +-- +2.17.2 + diff --git a/SOURCES/0035-BZ-1700911-hwtable-add-Lenovo-DE-series.patch b/SOURCES/0035-BZ-1700911-hwtable-add-Lenovo-DE-series.patch new file mode 100644 index 0000000..b761baf --- /dev/null +++ b/SOURCES/0035-BZ-1700911-hwtable-add-Lenovo-DE-series.patch @@ -0,0 +1,50 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Wilck +Date: Mon, 18 Mar 2019 12:24:45 +0100 +Subject: [PATCH] BZ 1700911: hwtable: add Lenovo DE series + +I got this from Steven. + +Cc: Steve.Schremmer@netapp.com +Cc: NetApp RDAC team +Cc: xose.vazquez@gmail.com +Signed-off-by: Martin Wilck +Signed-off-by: Benjamin Marzinski +--- + libmultipath/hwtable.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c +index 8776411..f13591d 100644 +--- a/libmultipath/hwtable.c ++++ b/libmultipath/hwtable.c +@@ -701,6 +701,26 @@ static struct hwentry default_hw[] = { + .no_path_retry = (300 / DEFAULT_CHECKINT), + .prio_name = PRIO_ALUA, + }, ++ /* ++ * Lenovo ++ */ ++ { ++ /* ++ * DE Series ++ * ++ * Maintainer: ng-eseries-upstream-maintainers@netapp.com ++ */ ++ .vendor = "LENOVO", ++ .product = "DE_Series", ++ .bl_product = "Universal Xport", ++ .pgpolicy = GROUP_BY_PRIO, ++ .checker_name = RDAC, ++ .features = "2 pg_init_retries 50", ++ .hwhandler = "1 rdac", ++ .prio_name = PRIO_RDAC, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .no_path_retry = 30, ++ }, + /* + * NetApp + */ +-- +2.17.2 + diff --git a/SOURCES/0036-libmultipath-make-vector_foreach_slot_backwards-work.patch b/SOURCES/0036-libmultipath-make-vector_foreach_slot_backwards-work.patch new file mode 100644 index 0000000..adf1f4f --- /dev/null +++ b/SOURCES/0036-libmultipath-make-vector_foreach_slot_backwards-work.patch @@ -0,0 +1,31 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Benjamin Marzinski +Date: Fri, 24 May 2019 17:30:07 -0500 +Subject: [PATCH] libmultipath: make vector_foreach_slot_backwards work as + expected + +All of the code that uses vector_foreach_slot_backwards() treats "i" as +the index of the entry "p", but the way it was coded, that wasn't the +case. "i" was the number of the entry counting from 1, not 0. + +Signed-off-by: Benjamin Marzinski +--- + libmultipath/vector.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/libmultipath/vector.h b/libmultipath/vector.h +index 41d2b89..344dffd 100644 +--- a/libmultipath/vector.h ++++ b/libmultipath/vector.h +@@ -40,7 +40,7 @@ typedef struct _vector *vector; + #define vector_foreach_slot_after(v,p,i) \ + for (; (v) && i < VECTOR_SIZE(v) && ((p) = (v)->slot[i]); i++) + #define vector_foreach_slot_backwards(v,p,i) \ +- for (i = VECTOR_SIZE(v); i > 0 && ((p) = (v)->slot[i-1]); i--) ++ for (i = VECTOR_SIZE(v) - 1; (int)i >= 0 && ((p) = (v)->slot[i]); i--) + + #define identity(x) (x) + /* +-- +2.17.2 + diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec index d047062..85e1c7e 100644 --- a/SPECS/device-mapper-multipath.spec +++ b/SPECS/device-mapper-multipath.spec @@ -1,41 +1,52 @@ Summary: Tools to manage multipath devices using device-mapper Name: device-mapper-multipath -Version: 0.7.8 -Release: 7%{?dist}.2 +Version: 0.8.0 +Release: 5%{?dist} License: GPLv2 Group: System Environment/Base URL: http://christophe.varoqui.free.fr/ # The source for this package was pulled from upstream's git repo. Use the # following command to generate the tarball -#curl "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=refs/tags/0.7.8;sf=tgz" -o multipath-tools-0.7.8.tgz -Source0: multipath-tools-0.7.8.tgz +#curl "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=refs/tags/0.8.0;sf=tgz" -o multipath-tools-0.8.0.tgz +Source0: multipath-tools-0.8.0.tgz Source1: multipath.conf -Patch0001: 0001-multipath-tweak-logging-style.patch -Patch0002: 0002-multipathd-check-for-NULL-udevice-in-cli_add_path.patch -Patch0003: 0003-libmultipath-remove-max_fds-code-duplication.patch -Patch0004: 0004-multipathd-set-return-code-for-multipathd-commands.patch -Patch0005: 0005-mpathpersist-fix-registration-rollback-issue.patch -Patch0006: 0006-libmultipath-timeout-on-unresponsive-tur-thread.patch -Patch0007: 0007-RH-fixup-udev-rules-for-redhat.patch -Patch0008: 0008-RH-Remove-the-property-blacklist-exception-builtin.patch -Patch0009: 0009-RH-don-t-start-without-a-config-file.patch -Patch0010: 0010-RH-use-rpm-optflags-if-present.patch -Patch0011: 0011-RH-add-mpathconf.patch -Patch0012: 0012-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch -Patch0013: 0013-RH-warn-on-invalid-regex-instead-of-failing.patch -Patch0014: 0014-RH-reset-default-find_mutipaths-value-to-off.patch -Patch0015: 0015-libmultipath-free-allocated-value-in-set_int.patch -Patch0016: 0016-kpartx-fix-new-memory-leak-in-dm_find_part.patch -Patch0017: 0017-BZ-1648397-fix-mpp-hwe-handling-when-paths-are-freed.patch -Patch0018: 0018-libmultipath-cleanup-pthread_cleanup_pop-call.patch -Patch0019: 0019-libmultipath-fix-false-removes-in-dmevents-polling-c.patch -Patch0020: 0020-BZ-1668693-disable-user_friendly_names-for-NetApp.patch -Patch0021: 0021-BZ-1673167-Fix-miscounting-active-paths.patch -Patch0022: 0022-BZ-1673167-ignore-failed-wwid-recheck.patch -Patch0023: 0023-BZ-1673167-fixup-wwid-recheck.patch -Patch0024: 0024-BZ-1723746-check-on-multipathd-without-starting-it.patch -Patch0025: 0025-BZ-1723746-test-socket-connection-in-non-blocking-mo.patch +Patch0001: 0001-BZ-1668693-disable-user_friendly_names-for-NetApp.patch +Patch0002: 0002-libmultipath-handle-existing-paths-in-marginal_path-.patch +Patch0003: 0003-multipathd-cleanup-marginal-paths-checking-timers.patch +Patch0004: 0004-libmultipath-fix-marginal-paths-queueing-errors.patch +Patch0005: 0005-libmultipath-fix-marginal_paths-nr_active-check.patch +Patch0006: 0006-multipathd-Fix-miscounting-active-paths.patch +Patch0007: 0007-multipathd-ignore-failed-wwid-recheck.patch +Patch0008: 0008-libmutipath-continue-to-use-old-state-on-PATH_PENDIN.patch +Patch0009: 0009-multipathd-use-update_path_groups-instead-of-reload_.patch +Patch0010: 0010-multipath.conf-add-missing-options-to-man-page.patch +Patch0011: 0011-libmultipath-add-get_uid-fallback-code-for-NVMe-devi.patch +Patch0012: 0012-libmulitpath-cleanup-uid_fallback-code.patch +Patch0013: 0013-multipathd-handle-changed-wwids-by-removal-and-addit.patch +Patch0014: 0014-multipathd-remove-wwid_changed-path-attribute.patch +Patch0015: 0015-multipathd-ignore-disable_changed_wwids.patch +Patch0016: 0016-multipathd-Don-t-use-fallback-code-after-getting-wwi.patch +Patch0017: 0017-libmultipath-silence-dm_is_mpath-error-messages.patch +Patch0018: 0018-RH-fixup-udev-rules-for-redhat.patch +Patch0019: 0019-RH-Remove-the-property-blacklist-exception-builtin.patch +Patch0020: 0020-RH-don-t-start-without-a-config-file.patch +Patch0021: 0021-RH-use-rpm-optflags-if-present.patch +Patch0022: 0022-RH-add-mpathconf.patch +Patch0023: 0023-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch +Patch0024: 0024-RH-warn-on-invalid-regex-instead-of-failing.patch +Patch0025: 0025-RH-reset-default-find_mutipaths-value-to-off.patch +Patch0026: 0026-RH-Fix-nvme-compilation-warning.patch +Patch0027: 0027-Fix-systemd-version-detection.patch +Patch0028: 0028-RH-attempt-to-get-ANA-info-via-sysfs-first.patch +Patch0029: 0029-BZ-1700451-check-on-multipathd-without-starting-it.patch +Patch0030: 0030-BZ-1700451-test-socket-connection-in-non-blocking-mo.patch +Patch0031: 0031-libmultipath-handle-clock_gettime-failures-in-tur-ch.patch +Patch0032: 0032-kpartx-fail-if-dup-of-dasd-file-descriptor-fails.patch +Patch0033: 0033-multipathd-fix-REALLOC_REPLY-with-max-length-reply.patch +Patch0034: 0034-multipathd-handle-NULL-return-from-genhelp_handler.patch +Patch0035: 0035-BZ-1700911-hwtable-add-Lenovo-DE-series.patch +Patch0036: 0036-libmultipath-make-vector_foreach_slot_backwards-work.patch # runtime Requires: %{name}-libs = %{version}-%{release} @@ -113,33 +124,7 @@ This package contains the files needed to develop applications that use device-mapper-multipath's libdmmp C API library %prep -%setup -q -n multipath-tools-0.7.8 -%patch0001 -p1 -%patch0002 -p1 -%patch0003 -p1 -%patch0004 -p1 -%patch0005 -p1 -%patch0006 -p1 -%patch0007 -p1 -%patch0008 -p1 -%patch0009 -p1 -%patch0010 -p1 -%patch0011 -p1 -%patch0012 -p1 -%patch0013 -p1 -%patch0014 -p1 -%patch0015 -p1 -%patch0016 -p1 -%patch0017 -p1 -%patch0018 -p1 -%patch0019 -p1 -%patch0020 -p1 -%patch0021 -p1 -%patch0022 -p1 -%patch0023 -p1 -%patch0024 -p1 -%patch0025 -p1 -cp %{SOURCE1} . +%autosetup -n multipath-tools-0.8.0 -p1 cp %{SOURCE1} . %build @@ -263,15 +248,65 @@ fi %{_pkgconfdir}/libdmmp.pc %changelog -* Mon Jul 1 2019 Benjamin Marzinski 0.7.8-7.2 -- Fix spec file -- Related: bz #1723746 - -* Tue Jun 25 2019 Benjamin Marzinski 0.7.8-7.1 -- Add 0024-BZ-1723746-check-on-multipathd-without-starting-it.patch -- Add 0025-BZ-1723746-test-socket-connection-in-non-blocking-mo.patch -- Update CI testing -- Resolves: bz #1723746 +* Mon Jun 3 2019 Benjamin Marzinski 0.8.0-5 +- Bump release number for test fix commit 0b68e623 +- Related: bz #1666322 + +* Tue May 28 2019 Benjamin Marzinski 0.8.0-4 +- Add 0035-BZ-1700911-hwtable-add-Lenovo-DE-series.patch +- Add 0036-libmultipath-make-vector_foreach_slot_backwards-work.patch + * Fix for bz #1713459 +- Fixes for bz #1666322 and #1669097 were included in 0.8.0 upstream + code +- Resolves: bz #1666322, #1669097, #1700911, #1713459 + +* Thu May 16 2019 Benjamin Marzinski 0.8.0-3 +- Add 0031-libmultipath-handle-clock_gettime-failures-in-tur-ch.patch +- Add 0032-kpartx-fail-if-dup-of-dasd-file-descriptor-fails.patch +- Add 0033-multipathd-fix-REALLOC_REPLY-with-max-length-reply.patch +- Add 0034-multipathd-handle-NULL-return-from-genhelp_handler.patch + * The above 4 patches have been submitted upstream +- Related: bz #1498546 + +* Tue Apr 30 2019 Benjamin Marzinski 0.8.0-2 +- Add 0029-BZ-1700451-check-on-multipathd-without-starting-it.patch +- Add 0030-BZ-1700451-test-socket-connection-in-non-blocking-mo.patch + * the "multipath -u" call in 62-multipath.rules should no longer hang + on multipathd startup. +- Resolves: bz #1700451 + +* Mon Apr 8 2019 Benjamin Marzinski 0.8.0-1 +- Update Source to upstream version 0.8.0 + * Previous patches 0001-0006 & 0015-0019 are included in this commit +- Rename files + * Previous patches 0007-0014 are now 0018-0025 + * Previous patches 0020-0023 are now 0001, 0006 & 0007 +- Add 0002-libmultipath-handle-existing-paths-in-marginal_path-.patch +- Add 0003-multipathd-cleanup-marginal-paths-checking-timers.patch +- Add 0004-libmultipath-fix-marginal-paths-queueing-errors.patch +- Add 0005-libmultipath-fix-marginal_paths-nr_active-check.patch +- Add 0008-libmutipath-continue-to-use-old-state-on-PATH_PENDIN.patch +- Add 0009-multipathd-use-update_path_groups-instead-of-reload_.patch +- Add 0010-multipath.conf-add-missing-options-to-man-page.patch +- Add 0011-libmultipath-add-get_uid-fallback-code-for-NVMe-devi.patch +- Add 0012-libmulitpath-cleanup-uid_fallback-code.patch +- Add 0013-multipathd-handle-changed-wwids-by-removal-and-addit.patch + * Multipath will now automatically remove and re-add paths if + their wwid changes +- Add 0014-multipathd-remove-wwid_changed-path-attribute.patch +- Add 0015-multipathd-ignore-disable_changed_wwids.patch + * Since paths are now getting removed and re-added there is + no need to disable them. +- Add 0016-multipathd-Don-t-use-fallback-code-after-getting-wwi.patch +- Add 0017-libmultipath-silence-dm_is_mpath-error-messages.patch +- Add 0026-RH-Fix-nvme-compilation-warning.patch +- Add 0027-Fix-systemd-version-detection.patch + * The above 16 patches have been submitted upstream +- Add 0028-RH-attempt-to-get-ANA-info-via-sysfs-first.patch + * Red Hat has a sysfs method to access the ANA state, which isn't + upstream, and will not be. This will probably go away in the + future. +- Resolves: bz #1498546 * Mon Feb 25 2019 Benjamin Marzinski 0.7.8-7 - Add 0023-BZ-1673167-fixup-wwid-recheck.patch