Compare commits

..

No commits in common. "rawhide" and "f38" have entirely different histories.

46 changed files with 2297 additions and 1087 deletions

8
.gitignore vendored
View file

@ -27,11 +27,3 @@ multipath-tools-091027.tar.gz
/multipath-tools-0.9.0.tgz
/multipath-tools-0.9.3.tgz
/multipath-tools-0.9.4.tgz
/multipath-tools-0.9.5.tgz
/multipath-tools-0.9.6.tgz
/multipath-tools-0.9.7.tgz
/multipath-tools-0.9.8.tgz
/multipath-tools-0.9.9.tgz
/multipath-tools-0.10.0.tgz
/multipath-tools-0.11.1.tgz
/multipath-tools-0.13.0.tgz

View file

@ -0,0 +1,159 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 20 Dec 2022 17:41:10 -0600
Subject: [PATCH] multipathd: make pr registration consistent
multipathd was inconsistent on what it did with persistent reservations
when a multipath device was created. If a multipath device with a
configured reservation key was created during configure(), multipathd
would try to read the registered keys using an active path. If it saw a
matching key, it would set the prflag, but not attempt to register the
key on any of the other paths. This means that if a new path had
appeared while multipathd was not running, it wouldn't register the key
on this path.
If the multipath device was created during ev_add_path(), multipathd
would used the added path to check if there was a matching key and if
there was, register the key only on the added path and then set the
prflag. This could be problematic if the device was created with
multiple paths, for instance because find_mutipaths was set to "yes" and
a second path just appeared. In this case, if the device happened to be
only registered on the second path, it would not get registered on the
first path.
If the multipath device was added to multipathd during a call to
ev_add_map(), multipathd wouldn't set the prflag or register the key on
any paths.
After a device was created with the prflag set, if a new path appeared
before the creation uevent, and multipathd was forced to delay adding
it, when it finally updated the multipath device, the key would be
registered on all paths, fixing any paths missed during creation.
However, if a new path appeared after the creation uevent, the key would
only be registered on that new path. Any paths that were missed on
creation would stay missed.
persistent key registration needs to be handled consistently. This
patch does so by making sure that however a multipath device is added to
multipathd, it will check to see if the configured key is registered. If
it is, multipathd will set the prflag and register the key on all the
currently active paths.
When a new path is added, multipathd will use it to check for active
keys, as before. But if it finds a matching key and prflag isn't
currently set, it will register the key on all paths.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipathd/main.c | 43 +++++++++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 1e1b254f..f7212d7b 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -586,13 +586,26 @@ flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
return false;
}
+static void
+pr_register_active_paths(struct multipath *mpp)
+{
+ unsigned int i, j;
+ struct path *pp;
+ struct pathgroup *pgp;
+
+ vector_foreach_slot (mpp->pg, pgp, i) {
+ vector_foreach_slot (pgp->paths, pp, j) {
+ if ((pp->state == PATH_UP) || (pp->state == PATH_GHOST))
+ mpath_pr_event_handle(pp);
+ }
+ }
+}
+
static int
update_map (struct multipath *mpp, struct vectors *vecs, int new_map)
{
int retries = 3;
char *params __attribute__((cleanup(cleanup_charp))) = NULL;
- struct path *pp;
- int i;
retry:
condlog(4, "%s: updating new map", mpp->alias);
@@ -609,15 +622,6 @@ retry:
mpp->action = ACT_RELOAD;
- if (mpp->prflag) {
- vector_foreach_slot(mpp->paths, pp, i) {
- if ((pp->state == PATH_UP) || (pp->state == PATH_GHOST)) {
- /* persistent reservation check*/
- mpath_pr_event_handle(pp);
- }
- }
- }
-
if (setup_map(mpp, &params, vecs)) {
condlog(0, "%s: failed to setup new map in update", mpp->alias);
retries = -1;
@@ -643,6 +647,11 @@ fail:
sync_map_state(mpp);
+ if (!mpp->prflag)
+ update_map_pr(mpp);
+ if (mpp->prflag)
+ pr_register_active_paths(mpp);
+
if (retries < 0)
condlog(0, "%s: failed reload in new map update", mpp->alias);
return 0;
@@ -1191,6 +1200,7 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
int start_waiter = 0;
int ret;
int ro;
+ unsigned char prflag = 0;
/*
* need path UID to go any further
@@ -1234,6 +1244,8 @@ rescan:
verify_paths(mpp);
mpp->action = ACT_RELOAD;
+ prflag = mpp->prflag;
+ mpath_pr_event_handle(pp);
} else {
if (!should_multipath(pp, vecs->pathvec, vecs->mpvec)) {
orphan_path(pp, "only one path");
@@ -1252,9 +1264,6 @@ rescan:
goto fail; /* leave path added to pathvec */
}
- /* persistent reservation check*/
- mpath_pr_event_handle(pp);
-
/* ro check - if new path is ro, force map to be ro as well */
ro = sysfs_get_ro(pp);
if (ro == 1)
@@ -1319,6 +1328,10 @@ rescan:
sync_map_state(mpp);
if (retries >= 0) {
+ if (start_waiter)
+ update_map_pr(mpp);
+ if (mpp->prflag && !prflag)
+ pr_register_active_paths(mpp);
condlog(2, "%s [%s]: path added to devmap %s",
pp->dev, pp->dev_t, mpp->alias);
return 0;
@@ -2852,6 +2865,8 @@ configure (struct vectors * vecs, enum force_reload_types reload_type)
if (remember_wwid(mpp->wwid) == 1)
trigger_paths_udev_change(mpp, true);
update_map_pr(mpp);
+ if (mpp->prflag)
+ pr_register_active_paths(mpp);
}
/*

View file

@ -0,0 +1,166 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 20 Dec 2022 17:41:11 -0600
Subject: [PATCH] libmultipath: make prflag an enum
In preparation for a future patch, make prflag an enum, and change the
reply of cli_getprstatus() to a string.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmpathpersist/mpath_persist_int.c | 2 +-
libmultipath/structs.h | 8 +++++++-
multipathd/cli_handlers.c | 17 +++++++++--------
multipathd/main.c | 14 +++++++-------
4 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
index 6924b379..a84d9474 100644
--- a/libmpathpersist/mpath_persist_int.c
+++ b/libmpathpersist/mpath_persist_int.c
@@ -783,7 +783,7 @@ int update_map_pr(struct multipath *mpp)
if (isFound)
{
- mpp->prflag = 1;
+ mpp->prflag = PRFLAG_SET;
condlog(2, "%s: prflag flag set.", mpp->alias );
}
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index 9e2c1ab0..f2265300 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -375,6 +375,12 @@ struct path {
typedef int (pgpolicyfn) (struct multipath *, vector);
+
+enum prflag_value {
+ PRFLAG_UNSET,
+ PRFLAG_SET,
+};
+
struct multipath {
char wwid[WWID_SIZE];
char alias_old[WWID_SIZE];
@@ -449,7 +455,7 @@ struct multipath {
int prkey_source;
struct be64 reservation_key;
uint8_t sa_flags;
- unsigned char prflag;
+ int prflag;
int all_tg_pt;
struct gen_multipath generic_mp;
bool fpin_must_reload;
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index e65fb75c..7ee2729f 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -1277,6 +1277,10 @@ cli_shutdown (void * v, struct strbuf *reply, void * data)
static int
cli_getprstatus (void * v, struct strbuf *reply, void * data)
{
+ static const char * const prflag_str[] = {
+ [PRFLAG_UNSET] = "unset\n",
+ [PRFLAG_SET] = "set\n",
+ };
struct multipath * mpp;
struct vectors * vecs = (struct vectors *)data;
char * param = get_keyparam(v, KEY_MAP);
@@ -1287,10 +1291,7 @@ cli_getprstatus (void * v, struct strbuf *reply, void * data)
if (!mpp)
return 1;
- condlog(3, "%s: prflag = %u", param, (unsigned int)mpp->prflag);
-
- if (print_strbuf(reply, "%d", mpp->prflag) < 0)
- return 1;
+ append_strbuf_str(reply, prflag_str[mpp->prflag]);
condlog(3, "%s: reply = %s", param, get_strbuf_str(reply));
@@ -1310,8 +1311,8 @@ cli_setprstatus(void * v, struct strbuf *reply, void * data)
if (!mpp)
return 1;
- if (!mpp->prflag) {
- mpp->prflag = 1;
+ if (mpp->prflag != PRFLAG_SET) {
+ mpp->prflag = PRFLAG_SET;
condlog(2, "%s: prflag set", param);
}
@@ -1332,8 +1333,8 @@ cli_unsetprstatus(void * v, struct strbuf *reply, void * data)
if (!mpp)
return 1;
- if (mpp->prflag) {
- mpp->prflag = 0;
+ if (mpp->prflag != PRFLAG_UNSET) {
+ mpp->prflag = PRFLAG_UNSET;
condlog(2, "%s: prflag unset", param);
}
diff --git a/multipathd/main.c b/multipathd/main.c
index f7212d7b..722235c7 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -647,9 +647,9 @@ fail:
sync_map_state(mpp);
- if (!mpp->prflag)
+ if (mpp->prflag == PRFLAG_UNSET)
update_map_pr(mpp);
- if (mpp->prflag)
+ if (mpp->prflag == PRFLAG_SET)
pr_register_active_paths(mpp);
if (retries < 0)
@@ -1200,7 +1200,7 @@ ev_add_path (struct path * pp, struct vectors * vecs, int need_do_map)
int start_waiter = 0;
int ret;
int ro;
- unsigned char prflag = 0;
+ unsigned char prflag = PRFLAG_UNSET;
/*
* need path UID to go any further
@@ -1330,7 +1330,7 @@ rescan:
if (retries >= 0) {
if (start_waiter)
update_map_pr(mpp);
- if (mpp->prflag && !prflag)
+ if (mpp->prflag == PRFLAG_SET && prflag == PRFLAG_UNSET)
pr_register_active_paths(mpp);
condlog(2, "%s [%s]: path added to devmap %s",
pp->dev, pp->dev_t, mpp->alias);
@@ -2492,7 +2492,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
}
if (newstate == PATH_UP || newstate == PATH_GHOST) {
- if (pp->mpp->prflag) {
+ if (pp->mpp->prflag == PRFLAG_SET) {
/*
* Check Persistent Reservation.
*/
@@ -2865,7 +2865,7 @@ configure (struct vectors * vecs, enum force_reload_types reload_type)
if (remember_wwid(mpp->wwid) == 1)
trigger_paths_udev_change(mpp, true);
update_map_pr(mpp);
- if (mpp->prflag)
+ if (mpp->prflag == PRFLAG_SET)
pr_register_active_paths(mpp);
}
@@ -3840,7 +3840,7 @@ void * mpath_pr_event_handler_fn (void * pathp )
{
condlog(0,"%s: Reservation registration failed. Error: %d", pp->dev, ret);
}
- mpp->prflag = 1;
+ mpp->prflag = PRFLAG_SET;
free(param);
out:

View file

@ -0,0 +1,152 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 20 Dec 2022 17:41:12 -0600
Subject: [PATCH] multipathd: handle no active paths in update_map_pr
When a multipath device is first created, if it has a reservation key
configured, update_map_pr() will check for a matching key on the active
paths. If there were no active paths to check with, multipathd was
leaving mpp->prflag in PRFLAG_UNSET, as if there were no matching keys.
It's possible that when update_map_pr() is called, all the paths will be
in the PATH_PENDING state because the checkers haven't completed yet. In
this case, multipathd was treating the device as having no registered
keys without ever checking.
To solve this, multipath devices now start with prflag = PRFLAG_UNKNOWN.
It will remain in this state until multipathd actually tries to get the
registered keys down a path. If the map is in this state, it will check
newly active paths, and if it finds a matching key, it will register
the key down all active paths.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmpathpersist/mpath_persist_int.c | 8 ++++++++
libmultipath/structs.h | 1 +
multipathd/cli_handlers.c | 1 +
multipathd/main.c | 19 ++++++++++++++-----
4 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
index a84d9474..8b52b746 100644
--- a/libmpathpersist/mpath_persist_int.c
+++ b/libmpathpersist/mpath_persist_int.c
@@ -738,6 +738,7 @@ int update_map_pr(struct multipath *mpp)
if (!get_be64(mpp->reservation_key))
{
/* Nothing to do. Assuming pr mgmt feature is disabled*/
+ mpp->prflag = PRFLAG_UNSET;
condlog(4, "%s: reservation_key not set in multipath.conf",
mpp->alias);
return MPATH_PR_SUCCESS;
@@ -749,6 +750,13 @@ int update_map_pr(struct multipath *mpp)
condlog(0,"%s : failed to alloc resp in update_map_pr", mpp->alias);
return MPATH_PR_OTHER;
}
+ if (count_active_paths(mpp) == 0)
+ {
+ condlog(0,"%s: No available paths to check pr status",
+ mpp->alias);
+ return MPATH_PR_OTHER;
+ }
+ mpp->prflag = PRFLAG_UNSET;
ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy);
if (ret != MPATH_PR_SUCCESS )
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index f2265300..e2294323 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -377,6 +377,7 @@ typedef int (pgpolicyfn) (struct multipath *, vector);
enum prflag_value {
+ PRFLAG_UNKNOWN,
PRFLAG_UNSET,
PRFLAG_SET,
};
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 7ee2729f..ec5db1b8 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -1278,6 +1278,7 @@ static int
cli_getprstatus (void * v, struct strbuf *reply, void * data)
{
static const char * const prflag_str[] = {
+ [PRFLAG_UNKNOWN] = "unknown\n",
[PRFLAG_UNSET] = "unset\n",
[PRFLAG_SET] = "set\n",
};
diff --git a/multipathd/main.c b/multipathd/main.c
index 722235c7..bdeffe76 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -647,7 +647,7 @@ fail:
sync_map_state(mpp);
- if (mpp->prflag == PRFLAG_UNSET)
+ if (mpp->prflag != PRFLAG_SET)
update_map_pr(mpp);
if (mpp->prflag == PRFLAG_SET)
pr_register_active_paths(mpp);
@@ -1330,7 +1330,7 @@ rescan:
if (retries >= 0) {
if (start_waiter)
update_map_pr(mpp);
- if (mpp->prflag == PRFLAG_SET && prflag == PRFLAG_UNSET)
+ if (mpp->prflag == PRFLAG_SET && prflag != PRFLAG_SET)
pr_register_active_paths(mpp);
condlog(2, "%s [%s]: path added to devmap %s",
pp->dev, pp->dev_t, mpp->alias);
@@ -2492,13 +2492,17 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
}
if (newstate == PATH_UP || newstate == PATH_GHOST) {
- if (pp->mpp->prflag == PRFLAG_SET) {
+ if (pp->mpp->prflag != PRFLAG_UNSET) {
+ int prflag = pp->mpp->prflag;
/*
* Check Persistent Reservation.
*/
condlog(2, "%s: checking persistent "
"reservation registration", pp->dev);
mpath_pr_event_handle(pp);
+ if (pp->mpp->prflag == PRFLAG_SET &&
+ prflag != PRFLAG_SET)
+ pr_register_active_paths(pp->mpp);
}
}
@@ -3788,6 +3792,7 @@ void * mpath_pr_event_handler_fn (void * pathp )
goto out;
}
+ mpp->prflag = PRFLAG_UNSET;
ret = prin_do_scsi_ioctl(pp->dev, MPATH_PRIN_RKEY_SA, resp, 0);
if (ret != MPATH_PR_SUCCESS )
{
@@ -3858,12 +3863,12 @@ int mpath_pr_event_handle(struct path *pp)
struct multipath * mpp;
if (pp->bus != SYSFS_BUS_SCSI)
- return 0;
+ goto no_pr;
mpp = pp->mpp;
if (!get_be64(mpp->reservation_key))
- return -1;
+ goto no_pr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@@ -3876,4 +3881,8 @@ int mpath_pr_event_handle(struct path *pp)
pthread_attr_destroy(&attr);
rc = pthread_join(thread, NULL);
return 0;
+
+no_pr:
+ pp->mpp->prflag = PRFLAG_UNSET;
+ return 0;
}

View file

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 20 Dec 2022 17:41:13 -0600
Subject: [PATCH] multipathd: add missing newline to cli_del_map reply
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
multipathd/cli_handlers.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index ec5db1b8..44bf43df 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -760,7 +760,7 @@ cli_del_map (void * v, struct strbuf *reply, void * data)
}
rc = ev_remove_map(param, alias, minor, vecs);
if (rc == 2)
- append_strbuf_str(reply, "delayed");
+ append_strbuf_str(reply, "delayed\n");
free(alias);
return rc;

View file

@ -1,67 +0,0 @@
From bf46f8029998498045bb055415ba3ff515c79eaa Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
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 <bmarzins@redhat.com>
---
Makefile.inc | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index ead89030..03aee175 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -102,17 +102,29 @@ SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo
MODPROBE_UNIT := $(shell test "0$(SYSTEMD)" -lt 245 2>/dev/null || \
echo "modprobe@dm_multipath.service")
-OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
+ifndef RPM_OPT_FLAGS
+ OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 \
+ -Wall $(FORTIFY_OPT) -fexceptions -grecord-gcc-switches \
+ -fasynchronous-unwind-tables
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-hardened-cc1 && echo 1),1)
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1
+ endif
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-annobin-cc1 && echo 1),1)
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1
+ endif
+else
+ OPTFLAGS := $(RPM_OPT_FLAGS) --param=ssp-buffer-size=4
+endif
# Set WARN_ONLY=1 to avoid compilation erroring out due to warnings. Useful during development.
WARN_ONLY :=
ERROR := $(if $(WARN_ONLY),,error=)
WERROR := $(if $(WARN_ONLY),,-Werror)
-WARNFLAGS := $(WERROR) -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -W$(ERROR)implicit-int \
+WARNFLAGS := $(WERROR) -Wextra -Wformat=2 $(WFORMATOVERFLOW) -W$(ERROR)implicit-int \
-W$(ERROR)implicit-function-declaration -W$(ERROR)format-security \
- $(WNOCLOBBERED) -W$(ERROR)cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS)
+ $(WNOCLOBBERED) -W$(ERROR)cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -Wstrict-prototypes
-CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
+CPPFLAGS := $(CPPFLAGS) $(D_URCU_VERSION) \
-D_FILE_OFFSET_BITS=64 \
-DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(TGTDIR)$(plugindir)\" \
-DRUNTIME_DIR=\"$(runtimedir)\" -DCONFIG_DIR=\"$(TGTDIR)$(configdir)\" \
@@ -121,12 +133,11 @@ CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) $(D_URCU_VERSION) \
-DABSTRACT_SOCKET=\"$(abstract_socket)\" -DPATHNAME_SOCKET=\"$(pathname_socket)\" \
-DWSTRINGOP_TRUNCATION=$(if $(WSTRINGOP_TRUNCATION),1,0) \
-MMD -MP
-CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
- -fexceptions
+CFLAGS := -std=$(C_STD) $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
BIN_CFLAGS := -fPIE -DPIE
LIB_CFLAGS := -fPIC
SHARED_FLAGS := -shared
-LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs
+LDFLAGS := $(LDFLAGS) $(RPM_LD_FLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs
BIN_LDFLAGS := -pie
# Source code directories. Don't modify.

View file

@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 20 Dec 2022 17:41:14 -0600
Subject: [PATCH] libmultipath: skip extra vector work in remove_maps
Instead of repeatedly removing the first vector element, and shifting
the rest to fill in, call remove_map() without a vector, so it just
frees the devices. The vector will be completely cleaned up by
vector_free() immediately afterwards.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/structs_vec.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 5a618767..f3fdc5a6 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -392,10 +392,8 @@ remove_maps(struct vectors * vecs)
if (!vecs)
return;
- vector_foreach_slot (vecs->mpvec, mpp, i) {
- remove_map(mpp, vecs->pathvec, vecs->mpvec);
- i--;
- }
+ vector_foreach_slot (vecs->mpvec, mpp, i)
+ remove_map(mpp, vecs->pathvec, NULL);
vector_free(vecs->mpvec);
vecs->mpvec = NULL;

View file

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 20 Dec 2022 17:41:15 -0600
Subject: [PATCH] libmultipath: orphan paths if coalesce_paths frees newmp
If coalesce_paths() is called without a mpvec, it will free all the
multipath devices on newmp at the end. This will clear pp->mpp from the
path, but it doesn't completely unitialize them. cli_add_map() can call
coalsce_paths() this way, when adding a device that doesn't currently
exist. cli_add_map() first creates the device in the kernel, and then
calls ev_add_map() to add it to multipathd. If something goes wrong in
ev_add_map(), the paths will still be initialized, even though they're
orphans.
Fix this by calling remove_map() to orphan the paths that belong to
the multipath devices being deleted by coalesce_paths().
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index e551047a..e689f8a7 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1273,8 +1273,11 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
ret = CP_OK;
out:
free(size_mismatch_seen);
- if (!mpvec)
- free_multipathvec(newmp, KEEP_PATHS);
+ if (!mpvec) {
+ vector_foreach_slot (newmp, mpp, i)
+ remove_map(mpp, vecs->pathvec, NULL);
+ vector_free(newmp);
+ }
return ret;
}

View file

@ -0,0 +1,609 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Wed, 9 Nov 2022 21:20:58 +0100
Subject: [PATCH] libmultipath: is_path_valid(): check if device is in use
To check whether we will be able to add a given device can be part
of a multipath map, we have two tests in check_path_valid():
released_to_systemd() and the O_EXCL test. The former isn't helpful
if "multipath -u" is called for the first time for a given device,
and the latter is only used in the "find_multipaths smart" case, because
actively opening the device with O_EXCL, even for a very short time, is prone
to races with other processes.
It turns out that this may cause issues in some scenarios. We saw problems in
once case where "find_multipaths greedy" was used with a single
non-multipahted root disk and a very large number of multipath LUNs.
The root disk would first be classified as multipath device. multipathd
would try to create a map, fail (because the disk was mounted) and
trigger another uevent. But because of the very large number of multipath
devices, this event was queued up behind thousands of other events, and
the root device timed out eventually.
While a simple workaround for the given problem would be proper blacklisting
or using a different find_multipaths mode, I am proposing a different
solution here. An additional test is added in is_path_valid() which
checks whether the given device is currently in use by 1. sysfs holders,
2. mounts (from /proc/self/mountinfo) or 3. swaps (from /proc/swaps). 2.
and 3. are similar to systemd's device detection after switching root.
This must not only be done for the device itself, but also for all its
partitions. For mountinfo and swaps, libmount is utilized.
With this patch, "multipath -u" will make devices with mounted or otherwise
used partitions available to systemd early, without waiting for multipathd
to fail setting up the map and re-triggering an uevent. This should avoid
the issue described above even without blacklisting. The downside of it
is a longer runtime of "multipath -u" for almost all devices, in particular
for real multipath devices. The runtime required for the new checks was in the
order of 0.1ms-1ms in my tests. Moreover, there is a certain risk that devices may
wrongly classified as non-multipath because of transient mounts or holders
created by other processes.
To make this code compile on older distributions, we need some additional
checks in create-config.mk.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
.github/workflows/build-and-unittest.yaml | 2 +-
create-config.mk | 11 +-
libmpathutil/libmpathutil.version | 6 +
libmpathutil/util.c | 12 +
libmpathutil/util.h | 2 +
libmultipath/Makefile | 2 +-
libmultipath/alias.c | 11 -
libmultipath/valid.c | 270 ++++++++++++++++++++++
tests/Makefile | 2 +-
tests/valid.c | 48 ++++
10 files changed, 351 insertions(+), 15 deletions(-)
diff --git a/.github/workflows/build-and-unittest.yaml b/.github/workflows/build-and-unittest.yaml
index abf17bf0..9e6c0e89 100644
--- a/.github/workflows/build-and-unittest.yaml
+++ b/.github/workflows/build-and-unittest.yaml
@@ -31,7 +31,7 @@ jobs:
sudo apt-get install --yes gcc
make perl-base pkg-config valgrind
libdevmapper-dev libreadline-dev libaio-dev libsystemd-dev
- libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev
+ libudev-dev libjson-c-dev liburcu-dev libcmocka-dev libedit-dev libmount-dev
- name: build
run: make -Orecurse -j$(grep -c ^processor /proc/cpuinfo) READLINE=${{ matrix.rl }}
- name: test
diff --git a/create-config.mk b/create-config.mk
index 2a95ec56..f128375f 100644
--- a/create-config.mk
+++ b/create-config.mk
@@ -23,7 +23,7 @@ check_cmd = $(shell \
# Check whether a function with name $1 has been declared in header file $2.
check_func = $(shell \
- if grep -Eq "^[^[:blank:]]+[[:blank:]]+$1[[:blank:]]*(.*)*" "$2"; then \
+ if grep -Eq "^(extern[[:blank:]]+)?[^[:blank:]]+[[:blank:]]+$1[[:blank:]]*(.*)*" "$2"; then \
found=1; \
status="yes"; \
else \
@@ -104,6 +104,15 @@ ifneq ($(call check_var,ELS_DTAG_LNK_INTEGRITY,$(kernel_incdir)/scsi/fc/fc_els.h
FPIN_SUPPORT = 1
endif
+libmount_h := $(shell $(PKGCONFIG) --variable=includedir mount)/libmount/libmount.h
+ifneq ($(call check_func,mnt_unref_cache,$(libmount_h)),0)
+ DEFINES += LIBMOUNT_HAS_MNT_UNREF_CACHE
+endif
+
+ifneq ($(call check_func,mnt_table_parse_swaps,$(libmount_h)),0)
+ DEFINES += LIBMOUNT_SUPPORTS_SWAP
+endif
+
ifneq ($(call check_file,$(kernel_incdir)/linux/nvme_ioctl.h),0)
ANA_SUPPORT := 1
endif
diff --git a/libmpathutil/libmpathutil.version b/libmpathutil/libmpathutil.version
index 1238fc93..dd007be4 100644
--- a/libmpathutil/libmpathutil.version
+++ b/libmpathutil/libmpathutil.version
@@ -133,3 +133,9 @@ LIBMPATHUTIL_1.1 {
global:
cleanup_fd_ptr;
} LIBMPATHUTIL_1.0;
+
+LIBMPATHUTIL_1.2 {
+global:
+ cleanup_vector_free;
+ cleanup_fclose;
+} LIBMPATHUTIL_1.0;
diff --git a/libmpathutil/util.c b/libmpathutil/util.c
index 9662e1ed..92f25a50 100644
--- a/libmpathutil/util.c
+++ b/libmpathutil/util.c
@@ -386,6 +386,18 @@ void cleanup_mutex(void *arg)
pthread_mutex_unlock(arg);
}
+void cleanup_vector_free(void *arg)
+{
+ if (arg)
+ vector_free((vector)arg);
+}
+
+void cleanup_fclose(void *p)
+{
+ if (p)
+ fclose(p);
+}
+
struct bitfield *alloc_bitfield(unsigned int maxbit)
{
unsigned int n;
diff --git a/libmpathutil/util.h b/libmpathutil/util.h
index 75e20fd8..99a471d0 100644
--- a/libmpathutil/util.h
+++ b/libmpathutil/util.h
@@ -48,6 +48,8 @@ int should_exit(void);
void cleanup_fd_ptr(void *arg);
void cleanup_free_ptr(void *arg);
void cleanup_mutex(void *arg);
+void cleanup_vector_free(void *arg);
+void cleanup_fclose(void *p);
struct scandir_result {
struct dirent **di;
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
index 3df851e2..61aa611f 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
@@ -7,7 +7,7 @@ DEVLIB := libmultipath.so
CPPFLAGS += -I$(mpathutildir) -I$(mpathcmddir) -I$(nvmedir) -D_GNU_SOURCE $(SYSTEMD_CPPFLAGS)
CFLAGS += $(LIB_CFLAGS)
LIBDEPS += -lpthread -ldl -ldevmapper -ludev -L$(mpathutildir) -lmpathutil -L$(mpathcmddir) -lmpathcmd \
- -lurcu -laio $(SYSTEMD_LIBDEPS)
+ -lmount -lurcu -laio $(SYSTEMD_LIBDEPS)
# object files referencing MULTIPATH_DIR or CONFIG_DIR
# they need to be recompiled for unit tests
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 05201224..c0139a2e 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -667,11 +667,6 @@ static int _check_bindings_file(const struct config *conf, FILE *file,
return rc;
}
-static void cleanup_fclose(void *p)
-{
- fclose(p);
-}
-
static int alias_compar(const void *p1, const void *p2)
{
const char *alias1 = (*(struct mpentry * const *)p1)->alias;
@@ -684,12 +679,6 @@ static int alias_compar(const void *p1, const void *p2)
return alias1 ? -1 : alias2 ? 1 : 0;
}
-static void cleanup_vector_free(void *arg)
-{
- if (arg)
- vector_free((vector)arg);
-}
-
/*
* check_alias_settings(): test for inconsistent alias configuration
*
diff --git a/libmultipath/valid.c b/libmultipath/valid.c
index a6aa9215..d4dae3ed 100644
--- a/libmultipath/valid.c
+++ b/libmultipath/valid.c
@@ -17,6 +17,8 @@
#include <stddef.h>
#include <errno.h>
#include <libudev.h>
+#include <dirent.h>
+#include <libmount/libmount.h>
#include "vector.h"
#include "config.h"
@@ -30,12 +32,271 @@
#include "mpath_cmd.h"
#include "valid.h"
+static int subdir_filter(const struct dirent *ent)
+{
+ unsigned int j;
+ static char const *const skip[] = {
+ ".",
+ "..",
+ "holders",
+ "integrity",
+ "mq",
+ "power",
+ "queue",
+ "slaves",
+ "trace",
+ };
+
+ if (ent->d_type != DT_DIR)
+ return 0;
+
+ for (j = 0; j < ARRAY_SIZE(skip); j++)
+ if (!strcmp(skip[j], ent->d_name))
+ return 0;
+ return 1;
+}
+
+static int read_partitions(const char *syspath, vector parts)
+{
+ struct scandir_result sr = { .n = 0 };
+ char path[PATH_MAX], *last;
+ char *prop;
+ int i;
+
+ strlcpy(path, syspath, sizeof(path));
+ sr.n = scandir(path, &sr.di, subdir_filter, NULL);
+ if (sr.n == -1)
+ return -errno;
+
+ pthread_cleanup_push_cast(free_scandir_result, &sr);
+
+ /* parts[0] is the whole disk */
+ if ((prop = strdup(strrchr(path, '/') + 1)) != NULL) {
+ if (vector_alloc_slot(parts))
+ vector_set_slot(parts, prop);
+ else
+ free(prop);
+ }
+
+ last = path + strlen(path);
+ for (i = 0; i < sr.n; i++) {
+ struct stat st;
+
+ /* only add dirs that have the "partition" attribute */
+ snprintf(last, sizeof(path) - (last - path), "/%s/partition",
+ sr.di[i]->d_name);
+
+ if (stat(path, &st) == 0 &&
+ (prop = strdup(sr.di[i]->d_name)) != NULL) {
+ if (vector_alloc_slot(parts))
+ vector_set_slot(parts, prop);
+ else
+ free(prop);
+ }
+ }
+
+ pthread_cleanup_pop(1);
+ return 0;
+}
+
+static int no_dots(const struct dirent *ent)
+{
+ const char *name = ent->d_name;
+
+ if (name[0] == '.' &&
+ (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
+ return 0;
+ return 1;
+}
+
+static int check_holders(const char *syspath)
+{
+ struct scandir_result __attribute__((cleanup(free_scandir_result)))
+ sr = { .n = 0 };
+
+ sr.n = scandir(syspath, &sr.di, no_dots, NULL);
+ if (sr.n > 0)
+ condlog(4, "%s: found holders under %s", __func__, syspath);
+ return sr.n;
+}
+
+static int check_all_holders(const struct _vector *parts)
+{
+ char syspath[PATH_MAX];
+ const char *sysname;
+ unsigned int j;
+
+ if (VECTOR_SIZE(parts) == 0)
+ return 0;
+
+ if (safe_sprintf(syspath, "/sys/class/block/%s/holders",
+ (const char *)VECTOR_SLOT(parts, 0)))
+ return -EOVERFLOW;
+
+ if (check_holders(syspath) > 0)
+ return 1;
+
+ j = 1;
+ vector_foreach_slot_after(parts, sysname, j) {
+ if (safe_sprintf(syspath, "/sys/class/block/%s/%s/holders",
+ (const char *)VECTOR_SLOT(parts, 0), sysname))
+ return -EOVERFLOW;
+ if (check_holders(syspath) > 0)
+ return 1;
+ }
+ return 0;
+}
+
+static void cleanup_table(void *arg)
+{
+ if (arg)
+ mnt_free_table((struct libmnt_table *)arg);
+}
+
+static void cleanup_cache(void *arg)
+{
+ if (arg)
+#ifdef LIBMOUNT_HAS_MNT_UNREF_CACHE
+ mnt_unref_cache((struct libmnt_cache *)arg);
+#else
+ mnt_free_cache((struct libmnt_cache *)arg);
+#endif
+}
+
+/*
+ * Passed a vector of partitions and a libmount table,
+ * check if any of the partitions in the vector is referenced in the table.
+ * Note that mnt_table_find_srcpath() also resolves mounts by symlinks.
+ */
+static int check_mnt_table(const struct _vector *parts,
+ struct libmnt_table *tbl,
+ const char *table_name)
+{
+ unsigned int i;
+ const char *sysname;
+ char devpath[PATH_MAX];
+
+ vector_foreach_slot(parts, sysname, i) {
+ if (!safe_sprintf(devpath, "/dev/%s", sysname) &&
+ mnt_table_find_srcpath(tbl, devpath,
+ MNT_ITER_FORWARD) != NULL) {
+ condlog(4, "%s: found %s in %s", __func__,
+ sysname, table_name);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int check_mountinfo(const struct _vector *parts)
+{
+ static const char mountinfo[] = "/proc/self/mountinfo";
+ struct libmnt_table *tbl;
+ struct libmnt_cache *cache;
+ FILE *stream;
+ int used = 0, ret;
+
+ tbl = mnt_new_table();
+ if (!tbl )
+ return -errno;
+
+ pthread_cleanup_push(cleanup_table, tbl);
+ cache = mnt_new_cache();
+ if (cache) {
+ pthread_cleanup_push(cleanup_cache, cache);
+ if (mnt_table_set_cache(tbl, cache) == 0) {
+ stream = fopen(mountinfo, "r");
+ if (stream != NULL) {
+ pthread_cleanup_push(cleanup_fclose, stream);
+ ret = mnt_table_parse_stream(tbl, stream, mountinfo);
+ pthread_cleanup_pop(1);
+
+ if (ret == 0)
+ used = check_mnt_table(parts, tbl,
+ "mountinfo");
+ }
+ }
+ pthread_cleanup_pop(1);
+ }
+ pthread_cleanup_pop(1);
+ return used;
+}
+
+#ifdef LIBMOUNT_SUPPORTS_SWAP
+static int check_swaps(const struct _vector *parts)
+{
+ struct libmnt_table *tbl;
+ struct libmnt_cache *cache;
+ int used = 0, ret;
+
+ tbl = mnt_new_table();
+ if (!tbl )
+ return -errno;
+
+ pthread_cleanup_push(cleanup_table, tbl);
+ cache = mnt_new_cache();
+ if (cache) {
+ pthread_cleanup_push(cleanup_cache, cache);
+ if (mnt_table_set_cache(tbl, cache) == 0) {
+ ret = mnt_table_parse_swaps(tbl, NULL);
+ if (ret == 0)
+ used = check_mnt_table(parts, tbl, "swaps");
+ }
+ pthread_cleanup_pop(1);
+ }
+ pthread_cleanup_pop(1);
+ return used;
+}
+#else
+static int check_swaps(const struct _vector *parts __attribute__((unused)))
+{
+ return 0;
+}
+#endif
+
+
+/*
+ * Given a block device, check if the device itself or any of its
+ * partitions is in use
+ * - by sysfs holders (e.g. LVM)
+ * - mounted according to /proc/self/mountinfo
+ * - used as swap
+ */
+static int is_device_in_use(struct udev_device *udevice)
+{
+ const char *syspath;
+ vector parts;
+ int used = 0, ret;
+
+ syspath = udev_device_get_syspath(udevice);
+ if (!syspath)
+ return -ENOMEM;
+
+ parts = vector_alloc();
+ if (!parts)
+ return -ENOMEM;
+
+ pthread_cleanup_push_cast(free_strvec, parts);
+ if ((ret = read_partitions(syspath, parts)) == 0)
+ used = check_all_holders(parts) > 0 ||
+ check_mountinfo(parts) > 0 ||
+ check_swaps(parts) > 0;
+ pthread_cleanup_pop(1);
+
+ if (ret < 0)
+ return ret;
+
+ condlog(3, "%s: %s is %sin use", __func__, syspath, used ? "" : "not ");
+ return used;
+}
+
int
is_path_valid(const char *name, struct config *conf, struct path *pp,
bool check_multipathd)
{
int r;
int fd;
+ const char *prop;
if (!pp || !name || !conf)
return PATH_IS_ERROR;
@@ -80,6 +341,10 @@ is_path_valid(const char *name, struct config *conf, struct path *pp,
if (!pp->udev)
return PATH_IS_ERROR;
+ prop = udev_device_get_property_value(pp->udev, "DEVTYPE");
+ if (prop == NULL || strcmp(prop, "disk"))
+ return PATH_IS_NOT_VALID;
+
r = pathinfo(pp, conf, DI_SYSFS | DI_WWID | DI_BLACKLIST);
if (r == PATHINFO_SKIPPED)
return PATH_IS_NOT_VALID;
@@ -96,6 +361,11 @@ is_path_valid(const char *name, struct config *conf, struct path *pp,
return PATH_IS_ERROR;
}
+ if ((conf->find_multipaths == FIND_MULTIPATHS_GREEDY ||
+ conf->find_multipaths == FIND_MULTIPATHS_SMART) &&
+ is_device_in_use(pp->udev) > 0)
+ return PATH_IS_NOT_VALID;
+
if (conf->find_multipaths == FIND_MULTIPATHS_GREEDY)
return PATH_IS_VALID;
diff --git a/tests/Makefile b/tests/Makefile
index 860338b2..1648ab9d 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -55,7 +55,7 @@ vpd-test_LIBDEPS := -ludev -lpthread -ldl
alias-test_TESTDEPS := test-log.o
alias-test_LIBDEPS := -lpthread -ldl
valid-test_OBJDEPS := $(multipathdir)/valid.o $(multipathdir)/discovery.o
-valid-test_LIBDEPS := -ludev -lpthread -ldl
+valid-test_LIBDEPS := -lmount -ludev -lpthread -ldl
devt-test_LIBDEPS := -ludev
mpathvalid-test_LIBDEPS := -ludev -lpthread -ldl
mpathvalid-test_OBJDEPS := $(mpathvaliddir)/mpath_valid.o
diff --git a/tests/valid.c b/tests/valid.c
index 398b771e..70329324 100644
--- a/tests/valid.c
+++ b/tests/valid.c
@@ -83,6 +83,13 @@ struct udev_device *__wrap_udev_device_new_from_subsystem_sysname(struct udev *u
return NULL;
}
+/* For devtype check */
+const char *__wrap_udev_device_get_property_value(struct udev_device *udev_device, const char *property)
+{
+ check_expected(property);
+ return mock_ptr_type(char *);
+}
+
/* For the "hidden" check in pathinfo() */
const char *__wrap_udev_device_get_sysattr_value(struct udev_device *udev_device,
const char *sysattr)
@@ -97,6 +104,12 @@ int __wrap_add_foreign(struct udev_device *udev_device)
return mock_type(int);
}
+/* For is_device_used() */
+const char *__wrap_udev_device_get_sysname(struct udev_device *udev_device)
+{
+ return mock_ptr_type(char *);
+}
+
/* called from pathinfo() */
int __wrap_filter_devnode(struct config *conf, const struct _vector *elist,
const char *vendor, const char * product, const char *dev)
@@ -165,6 +178,11 @@ int __wrap_is_failed_wwid(const char *wwid)
return ret;
}
+const char *__wrap_udev_device_get_syspath(struct udev_device *udevice)
+{
+ return mock_ptr_type(char *);
+}
+
int __wrap_check_wwids_file(char *wwid, int write_wwid)
{
bool passed = mock_type(bool);
@@ -225,6 +243,8 @@ static void setup_passing(char *name, char *wwid, unsigned int check_multipathd,
will_return(__wrap_udev_device_new_from_subsystem_sysname, true);
will_return(__wrap_udev_device_new_from_subsystem_sysname,
name);
+ expect_string(__wrap_udev_device_get_property_value, property, "DEVTYPE");
+ will_return(__wrap_udev_device_get_property_value, "disk");
if (stage == STAGE_GET_UDEV_DEVICE)
return;
if (stage == STAGE_PATHINFO_REAL) {
@@ -250,6 +270,10 @@ static void setup_passing(char *name, char *wwid, unsigned int check_multipathd,
return;
will_return(__wrap_is_failed_wwid, WWID_IS_NOT_FAILED);
will_return(__wrap_is_failed_wwid, wwid);
+ /* avoid real is_device_in_use() check */
+ if (conf.find_multipaths == FIND_MULTIPATHS_GREEDY ||
+ conf.find_multipaths == FIND_MULTIPATHS_SMART)
+ will_return(__wrap_udev_device_get_syspath, NULL);
if (stage == STAGE_IS_FAILED)
return;
will_return(__wrap_check_wwids_file, false);
@@ -347,6 +371,30 @@ static void test_check_multipathd(void **state)
assert_int_equal(is_path_valid(name, &conf, &pp, true),
PATH_IS_ERROR);
assert_string_equal(pp.dev, name);
+
+ /* test pass because connect succeeded. succeed getting udev. Wrong DEVTYPE */
+ memset(&pp, 0, sizeof(pp));
+ setup_passing(name, NULL, CHECK_MPATHD_RUNNING, STAGE_CHECK_MULTIPATHD);
+ will_return(__wrap_udev_device_new_from_subsystem_sysname, true);
+ will_return(__wrap_udev_device_new_from_subsystem_sysname,
+ name);
+ expect_string(__wrap_udev_device_get_property_value, property, "DEVTYPE");
+ will_return(__wrap_udev_device_get_property_value, "partition");
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
+ PATH_IS_NOT_VALID);
+ assert_string_equal(pp.dev, name);
+
+ /* test pass because connect succeeded. succeed getting udev. Bad DEVTYPE */
+ memset(&pp, 0, sizeof(pp));
+ setup_passing(name, NULL, CHECK_MPATHD_RUNNING, STAGE_CHECK_MULTIPATHD);
+ will_return(__wrap_udev_device_new_from_subsystem_sysname, true);
+ will_return(__wrap_udev_device_new_from_subsystem_sysname,
+ name);
+ expect_string(__wrap_udev_device_get_property_value, property, "DEVTYPE");
+ will_return(__wrap_udev_device_get_property_value, NULL);
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
+ PATH_IS_NOT_VALID);
+ assert_string_equal(pp.dev, name);
}
static void test_pathinfo(void **state)

View file

@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 2 Jan 2023 12:39:36 +0100
Subject: [PATCH] libmpathpersist: use conf->timeout for updating persistent
reservations
On systems with many LUNs, multipathd may fail to respond within the
default timeout to a "setprkey" command because the vecs lock is held
by the path checker. Honor the globally configured uxsock timeout in
libmpathpersist.
Reported-by: boposki (github.com/opensvc/multipath-tools/pull/58)
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathpersist/mpath_updatepr.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/libmpathpersist/mpath_updatepr.c b/libmpathpersist/mpath_updatepr.c
index 4529a82b..36bd777e 100644
--- a/libmpathpersist/mpath_updatepr.c
+++ b/libmpathpersist/mpath_updatepr.c
@@ -14,6 +14,9 @@
#include <mpath_persist.h>
#include "debug.h"
#include "mpath_cmd.h"
+#include "vector.h"
+#include "globals.h"
+#include "config.h"
#include "uxsock.h"
#include "mpathpr.h"
@@ -24,6 +27,12 @@ static int do_update_pr(char *alias, char *cmd, char *key)
char str[256];
char *reply;
int ret = 0;
+ int timeout;
+ struct config *conf;
+
+ conf = get_multipath_config();
+ timeout = conf->uxsock_timeout;
+ put_multipath_config(conf);
fd = mpath_connect();
if (fd == -1) {
@@ -41,7 +50,7 @@ static int do_update_pr(char *alias, char *cmd, char *key)
mpath_disconnect(fd);
return -1;
}
- ret = recv_packet(fd, &reply, DEFAULT_REPLY_TIMEOUT);
+ ret = recv_packet(fd, &reply, timeout);
if (ret < 0) {
condlog(2, "%s: message=%s recv error=%d", alias, str, errno);
ret = -1;

View file

@ -0,0 +1,77 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Wed, 30 Nov 2022 21:07:45 +0100
Subject: [PATCH] libmultipath: pathinfo: don't fail for devices lacking
INQUIRY properties
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Some SAS devices (e.g. Seagate factory recertified 'white label' drives) may
come with the Vendor field blank. This causes Multipath to fail to
complete the discovery of those devices.
Such devices violate the SCSI Spec. From the SPC-6, §6.7.2:
"The T10 VENDOR IDENTIFICATION field contains eight bytes of left-aligned
ASCII data (see 4.3.1) identifying the manufacturer of the logical unit. The
T10 vendor identification shall be one assigned by INCITS.".
But as we don't identify WWIDs by vendor and product, we don't need to discard
these devices right away. We can go ahead fingers crossed, and hope that the
the other VPD pages for the device are correct.
We obviously can't look up reasonable device properties for such devices in
our hwtable. It would be up to the user to deal with that.
Reported by: Allyn Malventano (github.com/opensvc/multipath-tools/issues/56)
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index d9ee2cb9..67ac0e6d 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1472,6 +1472,7 @@ scsi_sysfs_pathinfo (struct path *pp, const struct _vector *hwtable)
{
struct udev_device *parent;
const char *attr_path = NULL;
+ static const char unknown[] = "UNKNOWN";
parent = pp->udev;
while (parent) {
@@ -1492,19 +1493,22 @@ scsi_sysfs_pathinfo (struct path *pp, const struct _vector *hwtable)
if (!attr_path || pp->sg_id.host_no == -1)
return PATHINFO_FAILED;
- if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE) <= 0)
- return PATHINFO_FAILED;;
-
+ if (sysfs_get_vendor(parent, pp->vendor_id, SCSI_VENDOR_SIZE) <= 0) {
+ condlog(1, "%s: broken device without vendor ID", pp->dev);
+ strlcpy(pp->vendor_id, unknown, SCSI_VENDOR_SIZE);
+ }
condlog(3, "%s: vendor = %s", pp->dev, pp->vendor_id);
- if (sysfs_get_model(parent, pp->product_id, PATH_PRODUCT_SIZE) <= 0)
- return PATHINFO_FAILED;;
-
+ if (sysfs_get_model(parent, pp->product_id, PATH_PRODUCT_SIZE) <= 0) {
+ condlog(1, "%s: broken device without product ID", pp->dev);
+ strlcpy(pp->product_id, unknown, PATH_PRODUCT_SIZE);
+ }
condlog(3, "%s: product = %s", pp->dev, pp->product_id);
- if (sysfs_get_rev(parent, pp->rev, PATH_REV_SIZE) < 0)
- return PATHINFO_FAILED;;
-
+ if (sysfs_get_rev(parent, pp->rev, PATH_REV_SIZE) < 0) {
+ condlog(2, "%s: broken device without revision", pp->dev);
+ strlcpy(pp->rev, unknown, PATH_REV_SIZE);
+ }
condlog(3, "%s: rev = %s", pp->dev, pp->rev);
/*

View file

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Wed, 25 Jan 2023 11:35:38 +0100
Subject: [PATCH] libmultipath: bump ABI version to 18.0.0
Commit 6b81153 ("libmultipath: make prflag an enum") changed
the size and member offsets of struct multipath.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/libmultipath.version | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index faef2a2d..015623cc 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -43,7 +43,7 @@ LIBMPATHCOMMON_1.0.0 {
put_multipath_config;
};
-LIBMULTIPATH_17.0.0 {
+LIBMULTIPATH_18.0.0 {
global:
/* symbols referenced by multipath and multipathd */
add_foreign;

View file

@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 31 Jan 2023 13:34:18 -0600
Subject: [PATCH] libmultipath: use select_reload_action in select_action
Since we have a function to set the action to reload, use it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index e689f8a7..050b984a 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -729,9 +729,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
if (force_reload) {
mpp->force_udev_reload = 1;
- mpp->action = ACT_RELOAD;
- condlog(3, "%s: set ACT_RELOAD (forced by user)",
- mpp->alias);
+ select_reload_action(mpp, "forced by user");
return;
}
if (cmpp->size != mpp->size) {
@@ -744,9 +742,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
if (!is_udev_ready(cmpp) && count_active_paths(mpp) > 0) {
mpp->force_udev_reload = 1;
- mpp->action = ACT_RELOAD;
- condlog(3, "%s: set ACT_RELOAD (udev incomplete)",
- mpp->alias);
+ select_reload_action(mpp, "udev incomplete");
return;
}

View file

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 31 Jan 2023 13:34:19 -0600
Subject: [PATCH] libmultipath: select resize action even if reload is forced
The ACT_RESIZE action is the same as the ACT_RELOAD action, except that
it flushes outstanding IO because the device size is changing and
the new size might be too small for some of the outstanding IO. If we've
detected a size change, and a forced reload is requested, we still need
to flush the IO because the reload will change the device size.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 050b984a..6811e661 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -727,11 +727,6 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
return;
}
- if (force_reload) {
- mpp->force_udev_reload = 1;
- select_reload_action(mpp, "forced by user");
- return;
- }
if (cmpp->size != mpp->size) {
mpp->force_udev_reload = 1;
mpp->action = ACT_RESIZE;
@@ -740,6 +735,12 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
return;
}
+ if (force_reload) {
+ mpp->force_udev_reload = 1;
+ select_reload_action(mpp, "forced by user");
+ return;
+ }
+
if (!is_udev_ready(cmpp) && count_active_paths(mpp) > 0) {
mpp->force_udev_reload = 1;
select_reload_action(mpp, "udev incomplete");

View file

@ -1,186 +0,0 @@
From 2ef5bd86052ba0b22f4d3a16e69cdf268d90a53a Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 7 Jul 2023 15:25:59 -0500
Subject: [PATCH] RH: Add mpathcleanup
mpathcleanup is a program that will remove a multipath device as well as
all of the scsi path devices that make it up.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/Makefile | 2 +
multipath/mpathcleanup | 145 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 147 insertions(+)
create mode 100755 multipath/mpathcleanup
diff --git a/multipath/Makefile b/multipath/Makefile
index 3dc241cc..47e82234 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -25,6 +25,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
+ $(Q)$(INSTALL_PROGRAM) -m 755 mpathcleanup $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir)
@@ -49,6 +50,7 @@ endif
uninstall:
$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf
+ $(Q)$(RM) $(DESTDIR)$(bindir)/mpathcleanup
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
diff --git a/multipath/mpathcleanup b/multipath/mpathcleanup
new file mode 100755
index 00000000..6fd921e4
--- /dev/null
+++ b/multipath/mpathcleanup
@@ -0,0 +1,145 @@
+#!/bin/bash
+#
+# Copyright (C) 2023 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
+
+unset PROGRAM FLUSH DEVICE DEVNAME MAJOR MINOR PATHDEVS PATHDEV HAVE_MULTIPATHD QUEUEING
+
+function usage
+{
+ echo "usage: $PROGRAM [-h] [--flush] <device>"
+ echo ""
+ echo "remove a multipath device and its scsi path devices"
+ echo ""
+ echo "options:"
+ echo " -h, --help show this help message and exit"
+ echo " --flush disable queuing on the multipath device and"
+ echo " flush the path devices before removing"
+}
+
+function parse_args
+{
+ while [ -n "$1" ]; do
+ case $1 in
+ --flush)
+ FLUSH=1
+ shift
+ ;;
+ --help | -h)
+ usage
+ exit 1
+ ;;
+ *)
+ if [ -n "$DEVICE" ]; then
+ usage
+ exit 1
+ fi
+ DEVICE=$1
+ shift
+ ;;
+ esac
+ done
+}
+
+function validate_device
+{
+ if [ -z "$DEVICE" ]; then
+ usage
+ exit 1
+ fi
+ if [[ "$DEVICE" =~ ^[[:digit:]]+:[[:digit:]]+$ ]]; then
+ MAJOR=${DEVICE%%:*}
+ MINOR=${DEVICE##*:}
+ DEVNAME=`dmsetup ls --target multipath | grep "($MAJOR, $MINOR)$" | awk '{print $1}'`
+ else
+ DEVNAME=`dmsetup ls --target multipath | awk '{print $1}' | grep "^$DEVICE$"`
+ fi
+ if [ -z "$DEVNAME" ]; then
+ DEVNAME=`multipath -v 1 -l $DEVICE 2>/dev/null`
+ if [ -z "$DEVNAME" ]; then
+ echo "$DEVICE is not a multipath device"
+ exit 1
+ fi
+ # verify that this is not a native nvme multipath device
+ dmsetup ls --target multipath | awk '{print $1}' | grep -q "^$DEVNAME$"
+ if test $? -eq 1; then
+ echo "$DEVICE is not a device-mapper multipath device"
+ exit 1
+ fi
+ fi
+ if [ -z "$MINOR" ]; then
+ MINOR=`dmsetup info -c --noheadings -o minor $DEVNAME`
+ fi
+}
+
+function get_paths
+{
+ PATHDEVS=`ls /sys/block/dm-$MINOR/slaves`
+ for PATHDEV in $PATHDEVS; do
+ if [[ ! "$PATHDEV" =~ ^sd[a-z]+$ ]]; then
+ echo "$PATHDEV is not a scsi device. $PROGRAM only works with scsi devices"
+ exit 1
+ fi
+ done
+}
+
+function remove_devs
+{
+ pidof multipathd > /dev/null
+ HAVE_MULTIPATHD=$?
+ multipath -v2 -l "$DEVNAME" | grep features | grep -q queue_if_no_path
+ QUEUEING=$?
+ if [ -n "$FLUSH" ] && [ "$QUEUEING" -eq 0 ]; then
+ if test $HAVE_MULTIPATHD -eq 0; then
+ multipathd disablequeueing map "$DEVNAME" > /dev/null
+ else
+ dmsetup message "$DEVNAME" 0 fail_if_no_path
+ fi
+ sleep 1
+ fi
+ if test $HAVE_MULTIPATHD -eq 0; then
+ multipath -f "$DEVNAME"
+ else
+ multipathd -Df "$DEVNAME"
+ fi
+ if test $? -eq 1; then
+ echo "$DEVICE cannot be removed"
+ exit 1
+ fi
+ for PATHDEV in $PATHDEVS; do
+ if [ -n "$FLUSH" ]; then
+ blockdev --flushbufs /dev/"$PATHDEV"
+ fi
+ echo 1 > /sys/block/"$PATHDEV"/device/delete
+ done
+}
+
+function verify_removal
+{
+ multipath -v 1 -d $DEVNAME | grep -q "^$DEVNAME$"
+ if test $? -eq 0; then
+ echo "$DEVICE removed but path devices still exist"
+ exit 1
+ fi
+ multipath -v 1 -l $DEVNAME | grep -q "^$DEVNAME$"
+ if test $? -eq 0; then
+ echo "$DEVICE removal succeeded, but device still exists"
+ exit 1
+ fi
+}
+
+PROGRAM="$0"
+parse_args "$@"
+validate_device
+get_paths
+remove_devs
+verify_removal

View file

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 31 Jan 2023 13:34:20 -0600
Subject: [PATCH] libmultipath: cleanup ACT_CREATE code in select_action
Combine the two separate blocks that set ACT_CREATE into one.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 38 +++++++++++++++++---------------------
1 file changed, 17 insertions(+), 21 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 6811e661..e870e0f6 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -686,33 +686,29 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
if (mpp->need_reload || (cmpp && cmpp->need_reload))
force_reload = 1;
- if (!cmpp_by_name) {
- if (cmpp) {
- condlog(2, "%s: rename %s to %s", mpp->wwid,
- cmpp->alias, mpp->alias);
- strlcpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
- mpp->action = ACT_RENAME;
- if (force_reload) {
- mpp->force_udev_reload = 1;
- mpp->action = ACT_FORCERENAME;
- }
- return;
+ if (!cmpp) {
+ if (cmpp_by_name) {
+ condlog(1, "%s: can't use alias \"%s\" used by %s, falling back to WWID",
+ mpp->wwid, mpp->alias, cmpp_by_name->wwid);
+ /* We can do this because wwid wasn't found */
+ free(mpp->alias);
+ mpp->alias = strdup(mpp->wwid);
}
mpp->action = ACT_CREATE;
- condlog(3, "%s: set ACT_CREATE (map does not exist)",
- mpp->alias);
+ condlog(3, "%s: set ACT_CREATE (map does not exist%s)",
+ mpp->alias, cmpp_by_name ? ", name changed" : "");
return;
}
- if (!cmpp) {
- condlog(1, "%s: can't use alias \"%s\" used by %s, falling back to WWID",
- mpp->wwid, mpp->alias, cmpp_by_name->wwid);
- /* We can do this because wwid wasn't found */
- free(mpp->alias);
- mpp->alias = strdup(mpp->wwid);
- mpp->action = ACT_CREATE;
- condlog(3, "%s: set ACT_CREATE (map does not exist, name changed)",
+ if (!cmpp_by_name) {
+ condlog(2, "%s: rename %s to %s", mpp->wwid, cmpp->alias,
mpp->alias);
+ strlcpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
+ mpp->action = ACT_RENAME;
+ if (force_reload) {
+ mpp->force_udev_reload = 1;
+ mpp->action = ACT_FORCERENAME;
+ }
return;
}

View file

@ -0,0 +1,186 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 31 Jan 2023 13:34:21 -0600
Subject: [PATCH] libmultipath: keep renames from stopping other multipath
actions
If select_action() is called and a multipath device needs to be renamed,
the code currently checks if force_reload is set, and if so, does the
reload after the rename. But if force_reload isn't set, only the rename
happens, regardless of what other actions are needed. This can happen if
multipathd starts up and a device needs both a reload and a rename.
Make multipath check for resize, reload, and switch pathgroup along with
rename, and do both if necessary.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
---
libmultipath/configure.c | 62 +++++++++++++++++-----------------------
libmultipath/configure.h | 4 ++-
2 files changed, 30 insertions(+), 36 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index e870e0f6..4a1c28bb 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -670,7 +670,8 @@ static bool is_udev_ready(struct multipath *cmpp)
static void
select_reload_action(struct multipath *mpp, const char *reason)
{
- mpp->action = ACT_RELOAD;
+ mpp->action = mpp->action == ACT_RENAME ? ACT_RELOAD_RENAME :
+ ACT_RELOAD;
condlog(3, "%s: set ACT_RELOAD (%s)", mpp->alias, reason);
}
@@ -681,6 +682,7 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
struct multipath * cmpp_by_name;
char * mpp_feat, * cmpp_feat;
+ mpp->action = ACT_NOTHING;
cmpp = find_mp_by_wwid(curmp, mpp->wwid);
cmpp_by_name = find_mp_by_alias(curmp, mpp->alias);
if (mpp->need_reload || (cmpp && cmpp->need_reload))
@@ -705,14 +707,8 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
mpp->alias);
strlcpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
mpp->action = ACT_RENAME;
- if (force_reload) {
- mpp->force_udev_reload = 1;
- mpp->action = ACT_FORCERENAME;
- }
- return;
- }
-
- if (cmpp != cmpp_by_name) {
+ /* don't return here. Check for other needed actions */
+ } else if (cmpp != cmpp_by_name) {
condlog(2, "%s: unable to rename %s to %s (%s is used by %s)",
mpp->wwid, cmpp->alias, mpp->alias,
mpp->alias, cmpp_by_name->wwid);
@@ -720,12 +716,13 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
free(mpp->alias);
mpp->alias = strdup(cmpp->alias);
mpp->action = ACT_IMPOSSIBLE;
- return;
+ /* don't return here. Check for other needed actions */
}
if (cmpp->size != mpp->size) {
mpp->force_udev_reload = 1;
- mpp->action = ACT_RESIZE;
+ mpp->action = mpp->action == ACT_RENAME ? ACT_RESIZE_RENAME :
+ ACT_RESIZE;
condlog(3, "%s: set ACT_RESIZE (size change)",
mpp->alias);
return;
@@ -801,14 +798,14 @@ void select_action (struct multipath *mpp, const struct _vector *curmp,
return;
}
if (cmpp->nextpg != mpp->bestpg) {
- mpp->action = ACT_SWITCHPG;
+ mpp->action = mpp->action == ACT_RENAME ? ACT_SWITCHPG_RENAME :
+ ACT_SWITCHPG;
condlog(3, "%s: set ACT_SWITCHPG (next path group change)",
mpp->alias);
return;
}
- mpp->action = ACT_NOTHING;
- condlog(3, "%s: set ACT_NOTHING (map unchanged)",
- mpp->alias);
+ if (mpp->action == ACT_NOTHING)
+ condlog(3, "%s: set ACT_NOTHING (map unchanged)", mpp->alias);
return;
}
@@ -909,6 +906,17 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
}
}
+ if (mpp->action == ACT_RENAME || mpp->action == ACT_SWITCHPG_RENAME ||
+ mpp->action == ACT_RELOAD_RENAME ||
+ mpp->action == ACT_RESIZE_RENAME) {
+ conf = get_multipath_config();
+ pthread_cleanup_push(put_multipath_config, conf);
+ r = dm_rename(mpp->alias_old, mpp->alias,
+ conf->partition_delim, mpp->skip_kpartx);
+ pthread_cleanup_pop(1);
+ if (r == DOMAP_FAIL)
+ return r;
+ }
switch (mpp->action) {
case ACT_REJECT:
case ACT_NOTHING:
@@ -916,6 +924,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
return DOMAP_EXIST;
case ACT_SWITCHPG:
+ case ACT_SWITCHPG_RENAME:
dm_switchgroup(mpp->alias, mpp->bestpg);
/*
* we may have avoided reinstating paths because there where in
@@ -942,6 +951,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
break;
case ACT_RELOAD:
+ case ACT_RELOAD_RENAME:
sysfs_set_max_sectors_kb(mpp, 1);
if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP))
mpp->ghost_delay_tick = 0;
@@ -949,6 +959,7 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
break;
case ACT_RESIZE:
+ case ACT_RESIZE_RENAME:
sysfs_set_max_sectors_kb(mpp, 1);
if (mpp->ghost_delay_tick > 0 && pathcount(mpp, PATH_UP))
mpp->ghost_delay_tick = 0;
@@ -956,29 +967,10 @@ int domap(struct multipath *mpp, char *params, int is_daemon)
break;
case ACT_RENAME:
- conf = get_multipath_config();
- pthread_cleanup_push(put_multipath_config, conf);
- r = dm_rename(mpp->alias_old, mpp->alias,
- conf->partition_delim, mpp->skip_kpartx);
- pthread_cleanup_pop(1);
- break;
-
- case ACT_FORCERENAME:
- conf = get_multipath_config();
- pthread_cleanup_push(put_multipath_config, conf);
- r = dm_rename(mpp->alias_old, mpp->alias,
- conf->partition_delim, mpp->skip_kpartx);
- pthread_cleanup_pop(1);
- if (r) {
- sysfs_set_max_sectors_kb(mpp, 1);
- if (mpp->ghost_delay_tick > 0 &&
- pathcount(mpp, PATH_UP))
- mpp->ghost_delay_tick = 0;
- r = dm_addmap_reload(mpp, params, 0);
- }
break;
default:
+ r = DOMAP_FAIL;
break;
}
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
index 2bf73e65..9d935db3 100644
--- a/libmultipath/configure.h
+++ b/libmultipath/configure.h
@@ -18,9 +18,11 @@ enum actions {
ACT_RENAME,
ACT_CREATE,
ACT_RESIZE,
- ACT_FORCERENAME,
+ ACT_RELOAD_RENAME,
ACT_DRY_RUN,
ACT_IMPOSSIBLE,
+ ACT_RESIZE_RENAME,
+ ACT_SWITCHPG_RENAME,
};
/*

View file

@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Thu, 2 Feb 2023 09:20:35 +0100
Subject: [PATCH] libmpathpersist: fix resource leak in update_map_pr()
The "no available paths" case would leak the memory resp points to.
Found by coverity.
Fixes: 50e2c16 ("multipathd: handle no active paths in update_map_pr")
Signed-off-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathpersist/mpath_persist_int.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/libmpathpersist/mpath_persist_int.c b/libmpathpersist/mpath_persist_int.c
index 8b52b746..178c2f54 100644
--- a/libmpathpersist/mpath_persist_int.c
+++ b/libmpathpersist/mpath_persist_int.c
@@ -733,7 +733,7 @@ int update_map_pr(struct multipath *mpp)
int noisy=0;
struct prin_resp *resp;
unsigned int i;
- int ret, isFound;
+ int ret = MPATH_PR_OTHER, isFound;
if (!get_be64(mpp->reservation_key))
{
@@ -754,7 +754,7 @@ int update_map_pr(struct multipath *mpp)
{
condlog(0,"%s: No available paths to check pr status",
mpp->alias);
- return MPATH_PR_OTHER;
+ goto out;
}
mpp->prflag = PRFLAG_UNSET;
ret = mpath_prin_activepath(mpp, MPATH_PRIN_RKEY_SA, resp, noisy);
@@ -762,15 +762,15 @@ int update_map_pr(struct multipath *mpp)
if (ret != MPATH_PR_SUCCESS )
{
condlog(0,"%s : pr in read keys service action failed Error=%d", mpp->alias, ret);
- free(resp);
- return ret;
+ goto out;
}
+ ret = MPATH_PR_SUCCESS;
+
if (resp->prin_descriptor.prin_readkeys.additional_length == 0 )
{
condlog(3,"%s: No key found. Device may not be registered. ", mpp->alias);
- free(resp);
- return MPATH_PR_SUCCESS;
+ goto out;
}
condlog(2, "%s: Multipath reservation_key: 0x%" PRIx64 " ", mpp->alias,
@@ -795,6 +795,7 @@ int update_map_pr(struct multipath *mpp)
condlog(2, "%s: prflag flag set.", mpp->alias );
}
+out:
free(resp);
- return MPATH_PR_SUCCESS;
+ return ret;
}

View file

@ -1,4 +1,4 @@
From 64a07df23affd21842fdc604887276e62e5b41de Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 13 Apr 2017 07:22:23 -0500
Subject: [PATCH] RH: fixup udev rules for redhat
@ -9,55 +9,58 @@ different naming scheme for partitions than SuSE.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 2 +-
kpartx/kpartx.rules.in | 2 +-
multipath/Makefile | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
Makefile.inc | 4 ++--
kpartx/kpartx.rules | 2 +-
multipath/Makefile | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 9e3dc466..ead89030 100644
index 2e25d2ea..540e1dfc 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -34,7 +34,7 @@ endif
@@ -34,9 +34,9 @@ endif
# Paths. All these can be overridden on the "make" command line.
prefix :=
# Prefix for binaries
-exec_prefix := $(prefix)
+exec_prefix := $(prefix)/usr
# Prefix for non-essential libraries (libdmmp)
usr_prefix := $(if $(prefix),$(prefix),/usr)
# Prefix for configuration files (multipath.conf)
diff --git a/kpartx/kpartx.rules.in b/kpartx/kpartx.rules.in
index 9d879609..2049eb8f 100644
--- a/kpartx/kpartx.rules.in
+++ b/kpartx/kpartx.rules.in
-usr_prefix := $(prefix)
+usr_prefix := $(prefix)/usr
# Where to install systemd-related files. systemd is usually installed under /usr
# Note: some systemd installations use separate "prefix" and "rootprefix".
# In this case, override only unitdir to use systemd's "rootprefix" instead of $(systemd_prefix)
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index 1969dee0..d2b28233 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -39,6 +39,6 @@ LABEL="mpath_kpartx_end"
GOTO="kpartx_end"
LABEL="run_kpartx"
-RUN+="@BINDIR@/kpartx -un -p -part /dev/$name"
+RUN+="@BINDIR@/kpartx -un /dev/$name"
-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 67fb5e62..2ea9e528 100644
index 73db991a..b3c2cc81 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -27,7 +27,7 @@ install:
@@ -24,7 +24,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir)
- $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/56-multipath.rules
+ $(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir)
$(Q)$(INSTALL_PROGRAM) -m 644 modules-load.conf $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(tmpfilesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8
@@ -50,7 +50,7 @@ uninstall:
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules
@@ -44,7 +44,7 @@ uninstall:
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf
- $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5
$(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf

View file

@ -1,4 +1,4 @@
From f7be16ac9fce97585a4552d49f3d3c54a93c9c17 Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 2 Jul 2014 12:49:53 -0500
Subject: [PATCH] RH: Remove the property blacklist exception builtin
@ -13,25 +13,26 @@ it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 5 ++---
multipath/multipath.conf.5.in | 11 ++++++-----
tests/blacklist.c | 7 ++-----
3 files changed, 10 insertions(+), 13 deletions(-)
libmultipath/blacklist.c | 6 ++----
multipath/multipath.conf.5 | 11 ++++++-----
tests/blacklist.c | 7 ++-----
3 files changed, 10 insertions(+), 14 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 17e1b54a..10d13e98 100644
index 8d15d2ea..eff690fd 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -230,8 +230,6 @@ setup_default_blist (struct config * conf)
ORIGIN_DEFAULT))
return 1;
}
@@ -201,9 +201,6 @@ setup_default_blist (struct config * conf)
if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z]|nvme[0-9])", ORIGIN_DEFAULT))
return 1;
- if (store_ble(conf->elist_property, "(SCSI_IDENT_|ID_WWN)", ORIGIN_DEFAULT))
- return 1;
-
vector_foreach_slot (conf->hwtable, hwe, i) {
if (hwe->bl_product) {
@@ -438,7 +436,8 @@ filter_property(const struct config *conf, struct udev_device *udev,
if (find_blacklist_device(conf->blist_device,
@@ -409,7 +406,8 @@ filter_property(const struct config *conf, struct udev_device *udev,
*uid_attribute != '\0';
bool uid_attr_seen = false;
@ -41,11 +42,11 @@ index 17e1b54a..10d13e98 100644
udev_list_entry_foreach(list_entry,
udev_device_get_properties_list_entry(udev)) {
diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
index 3c9ae097..ba291e11 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -1470,9 +1470,14 @@ keywords. Both are regular expressions. For a full description of these keywords
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index b4dccd1b..284282c6 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1367,9 +1367,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,
@ -61,7 +62,7 @@ index 3c9ae097..ba291e11 100644
.
.RS
.PP
@@ -1483,10 +1488,6 @@ Blacklisting by missing properties is only applied to devices which do have the
@@ -1380,10 +1385,6 @@ Blacklisting by missing properties is only applied to devices which do have the
property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR)
set. Previously, it was applied to every device, possibly causing devices to be
blacklisted because of temporary I/O error conditions.
@ -73,10 +74,10 @@ index 3c9ae097..ba291e11 100644
.TP
.B protocol
diff --git a/tests/blacklist.c b/tests/blacklist.c
index ab3da619..52ae03e0 100644
index 882aa3a1..6a22b660 100644
--- a/tests/blacklist.c
+++ b/tests/blacklist.c
@@ -371,9 +371,8 @@ static void test_property_missing(void **state)
@@ -375,9 +375,8 @@ static void test_property_missing(void **state)
{
static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } };
conf.blist_property = blist_property_wwn;
@ -87,7 +88,7 @@ index ab3da619..52ae03e0 100644
assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"),
MATCH_NOTHING);
assert_int_equal(filter_property(&conf, &udev, 3, ""),
@@ -465,9 +464,7 @@ static void test_filter_path_missing1(void **state)
@@ -469,9 +468,7 @@ static void test_filter_path_missing1(void **state)
conf.blist_device = blist_device_foo_bar;
conf.blist_protocol = blist_protocol_fcp;
conf.blist_wwid = blist_wwid_xyzzy;

View file

@ -1,4 +1,4 @@
From 5613e07ce9cabf2fdc402f6f102cc54bd1059800 Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 15 Oct 2014 10:39:30 -0500
Subject: [PATCH] RH: don't start without a config file
@ -12,20 +12,19 @@ simple way to disable multipath. Simply removing or renaming
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 13 +++++++++++++
libmultipath/config.h | 1 +
multipath/main.c | 6 ++++++
multipath/multipath.rules.in | 1 +
multipathd/multipathd.8.in | 2 ++
multipathd/multipathd.service.in | 1 +
multipathd/multipathd.socket.in | 1 +
7 files changed, 25 insertions(+)
libmultipath/config.c | 13 +++++++++++++
libmultipath/config.h | 1 +
multipath/multipath.rules.in | 1 +
multipathd/multipathd.8 | 2 ++
multipathd/multipathd.service | 1 +
multipathd/multipathd.socket | 1 +
6 files changed, 19 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 8b424d18..b8317f4d 100644
index 5c5c0726..183b319d 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -937,6 +937,19 @@ int init_config__ (const char *file, struct config *conf)
@@ -966,6 +966,19 @@ int _init_config (const char *file, struct config *conf)
}
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
validate_pctable(conf->overrides, 0, file);
@ -46,7 +45,7 @@ index 8b424d18..b8317f4d 100644
conf->processed_main_config = 1;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 5b4ebf8c..2302eacc 100644
index 87947469..0dc89c16 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -10,6 +10,7 @@
@ -57,37 +56,8 @@ index 5b4ebf8c..2302eacc 100644
enum devtypes {
DEV_NONE,
diff --git a/multipath/main.c b/multipath/main.c
index f2adcdeb..31012874 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -834,11 +834,14 @@ main (int argc, char *argv[])
char *dev = NULL;
struct config *conf;
bool enable_foreign = false;
+ bool have_config;
+ struct stat buf;
libmultipath_init();
if (atexit(dm_lib_exit) || atexit(libmultipath_exit))
condlog(1, "failed to register cleanup handler for libmultipath: %m");
logsink = LOGSINK_STDERR_WITH_TIME;
+ have_config = (stat(DEFAULT_CONFIGFILE, &buf) == 0);
if (init_config(DEFAULT_CONFIGFILE))
exit(RTVL_FAIL);
if (atexit(uninit_config))
@@ -1092,6 +1095,9 @@ main (int argc, char *argv[])
while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY)
condlog(3, "restart multipath configuration process");
+ if (!have_config && r == RTVL_OK &&
+ (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG))
+ r = RTVL_FAIL;
out:
put_multipath_config(conf);
if (dev)
diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in
index 2ac1972f..cc248231 100644
index 8d3cf33a..5c4447a2 100644
--- a/multipath/multipath.rules.in
+++ b/multipath/multipath.rules.in
@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath"
@ -98,11 +68,11 @@ index 2ac1972f..cc248231 100644
ENV{DEVTYPE}!="partition", GOTO="test_dev"
IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH"
diff --git a/multipathd/multipathd.8.in b/multipathd/multipathd.8.in
index 8815e099..342e363e 100644
--- a/multipathd/multipathd.8.in
+++ b/multipathd/multipathd.8.in
@@ -49,6 +49,8 @@ map regains its maximum performance and redundancy.
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index bdf102eb..a16a0bd5 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -48,6 +48,8 @@ map regains its maximum performance and redundancy.
With the \fB-k\fR option, \fBmultipathd\fR acts as a client utility that
sends commands to a running instance of the multipathd daemon (see
\fBCOMMANDS\fR below).
@ -111,22 +81,22 @@ index 8815e099..342e363e 100644
.
.
.\" ----------------------------------------------------------------------------
diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in
index eb58943c..ab166435 100644
--- a/multipathd/multipathd.service.in
+++ b/multipathd/multipathd.service.in
@@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket multipathd-queueing.service @MODPROBE_UNIT@
After=systemd-udevd-kernel.socket @MODPROBE_UNIT@
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index aec62dbb..d76f94f9 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket
After=systemd-udevd-kernel.socket
After=multipathd.socket systemd-remount-fs.service
Before=initrd-cleanup.service
+ConditionPathExists=/etc/multipath.conf
DefaultDependencies=no
Conflicts=shutdown.target
Conflicts=initrd-cleanup.service
diff --git a/multipathd/multipathd.socket.in b/multipathd/multipathd.socket.in
index 11002fce..5ed24757 100644
--- a/multipathd/multipathd.socket.in
+++ b/multipathd/multipathd.socket.in
diff --git a/multipathd/multipathd.socket b/multipathd/multipathd.socket
index c777e5e3..3c20a2ff 100644
--- a/multipathd/multipathd.socket
+++ b/multipathd/multipathd.socket
@@ -1,6 +1,7 @@
[Unit]
Description=multipathd control socket

View file

@ -1,4 +1,4 @@
From 283b5dd645663a2cf16f2813581772d7a84db6ad Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 25 Jan 2019 14:54:56 -0600
Subject: [PATCH] RH: Fix nvme function missing argument
@ -12,10 +12,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/nvme/argconfig.h b/libmultipath/nvme/argconfig.h
index b3caa7be..f91504c9 100644
index adb192b6..bfd10ef8 100644
--- a/libmultipath/nvme/argconfig.h
+++ b/libmultipath/nvme/argconfig.h
@@ -63,7 +63,7 @@ struct argconfig_commandline_options {
@@ -76,7 +76,7 @@ struct argconfig_commandline_options {
extern "C" {
#endif

View file

@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
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 <bmarzins@redhat.com>
---
Makefile.inc | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 540e1dfc..748911e2 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -78,11 +78,23 @@ ORIG_LDFLAGS := $(LDFLAGS)
SYSTEMD_CPPFLAGS := $(if $(SYSTEMD),-DUSE_SYSTEMD=$(SYSTEMD))
SYSTEMD_LIBDEPS := $(if $(SYSTEMD),$(if $(shell test $(SYSTEMD) -gt 209 && echo 1),-lsystemd,-lsystemd-daemon))
-OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
-WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \
+ifndef RPM_OPT_FLAGS
+ OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4 \
+ -Wall $(FORTIFY_OPT) -fexceptions -grecord-gcc-switches \
+ -fasynchronous-unwind-tables
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-hardened-cc1 && echo 1),1)
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1
+ endif
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-annobin-cc1 && echo 1),1)
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1
+ endif
+else
+ OPTFLAGS := $(RPM_OPT_FLAGS) --param=ssp-buffer-size=4
+endif
+WARNFLAGS := -Werror -Wextra -Wformat=2 $(WFORMATOVERFLOW) -Werror=implicit-int \
-Werror=implicit-function-declaration -Werror=format-security \
- $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS)
-CPPFLAGS := $(FORTIFY_OPT) $(CPPFLAGS) \
+ $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) $(W_URCU_TYPE_LIMITS) -Wstrict-prototypes
+CPPFLAGS := $(CPPFLAGS) \
-DBIN_DIR=\"$(bindir)\" -DMULTIPATH_DIR=\"$(plugindir)\" \
-DRUNTIME_DIR=\"$(runtimedir)\" \
-DCONFIG_DIR=\"$(configdir)\" -DEXTRAVERSION=\"$(EXTRAVERSION)\" -MMD -MP
@@ -90,7 +102,7 @@ CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe
BIN_CFLAGS := -fPIE -DPIE
LIB_CFLAGS := -fPIC
SHARED_FLAGS := -shared
-LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs
+LDFLAGS := $(LDFLAGS) $(RPM_LD_FLAGS) -Wl,-z,relro -Wl,-z,now -Wl,-z,defs
BIN_LDFLAGS := -pie
# Source code directories. Don't modify.

View file

@ -1,4 +1,4 @@
From 29e5c6d6e2177e73d1be2ed2af66c1007487bf60 Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 16 Oct 2014 15:49:01 -0500
Subject: [PATCH] RH: add mpathconf
@ -10,47 +10,21 @@ 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.
Co-authored-by: Paul Donohue <git@PaulSD.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
.github/actions/spelling/expect.txt | 3 +
libmultipath/config.c | 2 +
multipath/Makefile | 4 +
multipath/mpathconf | 658 ++++++++++++++++++++++++++++
multipath/mpathconf.8 | 151 +++++++
5 files changed, 818 insertions(+)
libmultipath/config.c | 2 +
multipath/Makefile | 4 +
multipath/mpathconf | 658 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf.8 | 151 ++++++++++
4 files changed, 815 insertions(+)
create mode 100644 multipath/mpathconf
create mode 100644 multipath/mpathconf.8
diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt
index a5856bcc..5c9113ba 100644
--- a/.github/actions/spelling/expect.txt
+++ b/.github/actions/spelling/expect.txt
@@ -131,9 +131,11 @@ Marzinski
misdetection
mpath
mpathb
+mpathconf
mpathpersist
mpathvalid
msecs
+multipathable
multipathc
multipathd
multipathed
@@ -154,6 +156,7 @@ ontap
OOM
opensvc
OPTFLAGS
+outfile
paramp
partx
pathgroup
diff --git a/libmultipath/config.c b/libmultipath/config.c
index b8317f4d..0bbaa981 100644
index 183b319d..01f36a4f 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -939,6 +939,8 @@ int init_config__ (const char *file, struct config *conf)
@@ -968,6 +968,8 @@ int _init_config (const char *file, struct config *conf)
validate_pctable(conf->overrides, 0, file);
} else {
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
@ -60,43 +34,42 @@ index b8317f4d..0bbaa981 100644
conf->blist_devnode = vector_alloc();
if (!conf->blist_devnode) {
diff --git a/multipath/Makefile b/multipath/Makefile
index 2ea9e528..3dc241cc 100644
index b3c2cc81..413294ef 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,6 +24,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
@@ -22,6 +22,7 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
install:
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(Q)$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+ $(Q)$(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(Q)$(INSTALL_PROGRAM) -m 644 99-z-dm-mpath-late.rules $(DESTDIR)$(udevrulesdir)
@@ -32,6 +33,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)$(udevrulesdir)/62-multipath.rules
@@ -31,6 +32,7 @@ install:
$(Q)$(INSTALL_PROGRAM) -m 644 tmpfiles.conf $(DESTDIR)$(tmpfilesdir)/multipath.conf
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man8
$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)/man8
+ $(Q)$(INSTALL_PROGRAM) -m 644 mpathconf.8 $(DESTDIR)$(mandir)/man8
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)/man5
$(Q)$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(mandir)/man5
$(Q)$(INSTALL_PROGRAM) -d $(DESTDIR)$(modulesloaddir)
@@ -46,12 +48,14 @@ endif
ifneq ($(SCSI_DH_MODULES_PRELOAD),)
@@ -41,11 +43,13 @@ endif
uninstall:
$(Q)$(RM) $(DESTDIR)$(bindir)/$(EXEC)
+ $(Q)$(RM) $(DESTDIR)$(bindir)/mpathconf
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(Q)$(RM) $(DESTDIR)$(udevrulesdir)/99-z-dm-mpath-late.rules
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/multipath.conf
$(Q)$(RM) $(DESTDIR)$(modulesloaddir)/scsi_dh.conf
$(Q)$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(Q)$(RM) $(DESTDIR)$(mandir)/man8/$(EXEC).8
+ $(Q)$(RM) $(DESTDIR)$(mandir)/man8/mpathconf.8
$(Q)$(RM) $(DESTDIR)$(mandir)/man5/$(EXEC).conf.5
$(Q)$(RM) $(DESTDIR)$(tmpfilesdir)/multipath.conf
clean: dep_clean
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 00000000..ce430075
index 00000000..319664b1
--- /dev/null
+++ b/multipath/mpathconf
@@ -0,0 +1,658 @@
@ -133,7 +106,7 @@ index 00000000..ce430075
+
+defaults {
+ user_friendly_names yes
+ find_multipaths on
+ find_multipaths yes
+}"
+
+CONFIGFILE="/etc/multipath.conf"
@ -151,7 +124,7 @@ index 00000000..ce430075
+ echo "Disable: --disable"
+ echo "Only allow certain wwids (instead of enable): --allow <WWID>"
+ echo "Set user_friendly_names (Default y): --user_friendly_names <y|n>"
+ echo "Set find_multipaths (Default on): --find_multipaths <on|yes|y|off|no|n|strict|greedy|smart>"
+ echo "Set find_multipaths (Default y): --find_multipaths <yes|no|strict|greedy|smart>"
+ echo "Set default property blacklist (Default n): --property_blacklist <y|n>"
+ echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign <y|n>"
+ echo "Set recheck_wwid (Defaut n): --recheck_wwid <y|n>"
@ -355,11 +328,11 @@ index 00000000..ce430075
+ exit 1
+ fi
+ if [ "$FIND" = "y" ]; then
+ FIND="on"
+ FIND="yes"
+ elif [ "$FIND" = "n" ]; then
+ FIND="off"
+ elif [ -n "$FIND" ] && [ "$FIND" != "on" -a "$FIND" != "yes" -a "$FIND" != "off" -a "$FIND" != "no" -a "$FIND" != "strict" -a "$FIND" != "greedy" -a "$FIND" != "smart" ]; then
+ echo "--find_multipaths must be one of 'on' 'yes' 'y' 'off' 'no' 'n' 'strict' 'greedy' or 'smart'"
+ FIND="no"
+ elif [ -n "$FIND" ] && [ "$FIND" != "yes" -a "$FIND" != "no" -a "$FIND" != "strict" -a "$FIND" != "greedy" -a "$FIND" != "smart" ]; then
+ echo "--find_multipaths must be one of 'yes' 'no' 'strict' 'greedy' or 'smart'"
+ exit 1
+ fi
+ if [ -n "$PROPERTY" ] && [ "$PROPERTY" != "y" -a "$PROPERTY" != "n" ]; then
@ -524,7 +497,7 @@ index 00000000..ce430075
+ echo "multipath is disabled"
+ fi
+ if [ -z "$HAVE_FIND" ]; then
+ echo "find_multipaths is off"
+ echo "find_multipaths is no"
+ else
+ echo "find_multipaths is $HAVE_FIND"
+ fi
@ -760,7 +733,7 @@ index 00000000..ce430075
+fi
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
new file mode 100644
index 00000000..ec4e5c56
index 00000000..9c2fb835
--- /dev/null
+++ b/multipath/mpathconf.8
@@ -0,0 +1,151 @@
@ -806,10 +779,10 @@ index 00000000..ec4e5c56
+.B user_friendly_names
+set and
+.B find_multipaths
+set to \fBon\fP. To disable these, use the
+set to \fByes\fP. To disable these, use the
+.B --user_friendly_names n
+and
+.B --find_multipaths off
+.B --find_multipaths n
+options
+.SH COMMANDS
+.TP
@ -852,7 +825,7 @@ index 00000000..ec4e5c56
+sets an existing \fBrecheck_wwid\fP line to \fBno\fP. This command can be used
+along with any other command.
+.TP
+.B --find_multipaths\fP { \fBon\fP | \fByes\fP | \fBy\fP | \fBoff\fP | \fBno\fP | \fBn\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP }
+.B --find_multipaths\fP { \fByes\fP | \fBno\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP }
+If set to \fB<value>\fP, this adds the line
+.B find_multipaths <value>
+to the
@ -902,7 +875,7 @@ index 00000000..ec4e5c56
+.B service multipathd stop
+to stop the multipathd daemon on \fB--disable\fP, and
+.B service multipathd reload
+to reconfigure multipathd on \fB--user_friendly_names\fP and
+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

View file

@ -1,4 +1,4 @@
From d6ad888bad3850bb0a342ebcdc9fd78773eb3b2a Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 17 Oct 2014 11:20:34 -0500
Subject: [PATCH] RH: add wwids from kernel cmdline mpath.wwids with -A
@ -14,16 +14,16 @@ multipathd.service
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 54 ++++++++++++++++++++++++++++++--
multipath/multipath.8.in | 7 ++++-
multipathd/multipathd.service.in | 1 +
multipath/main.c | 54 +++++++++++++++++++++++++++++++++--
multipath/multipath.8 | 7 ++++-
multipathd/multipathd.service | 1 +
3 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index 31012874..a667c2ee 100644
index b9f360b4..5eb752ee 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -111,7 +111,7 @@ usage (char * progname)
@@ -120,7 +120,7 @@ usage (char * progname)
fprintf (stderr, " %s [-v level] [-R retries] -F\n", progname);
fprintf (stderr, " %s [-v level] [-l|-ll] [device]\n", progname);
fprintf (stderr, " %s [-v level] [-a|-w] device\n", progname);
@ -32,7 +32,7 @@ index 31012874..a667c2ee 100644
fprintf (stderr, " %s [-v level] [-i] [-c|-C] device\n", progname);
fprintf (stderr, " %s [-v level] [-i] [-u|-U]\n", progname);
fprintf (stderr, " %s [-h|-t|-T]\n", progname);
@@ -125,6 +125,8 @@ usage (char * 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"
@ -41,7 +41,7 @@ index 31012874..a667c2ee 100644
" -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"
@@ -440,6 +442,50 @@ static void cleanup_vecs(void)
@@ -447,6 +449,50 @@ static void cleanup_vecs(void)
free_pathvec(vecs.pathvec, FREE_PATHS);
}
@ -92,16 +92,16 @@ index 31012874..a667c2ee 100644
static int
configure (struct config *conf, enum mpath_cmds cmd,
enum devtypes dev_type, char *devpath)
@@ -851,7 +897,7 @@ main (int argc, char *argv[])
@@ -840,7 +886,7 @@ main (int argc, char *argv[])
conf->force_sync = 1;
if (atexit(cleanup_vecs))
condlog(1, "failed to register cleanup handler for vecs: %m");
if (atexit(cleanup_bindings))
condlog(1, "failed to register cleanup handler for bindings: %m");
- while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":aAdDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
switch(arg) {
case 'v':
if (!isdigit(optarg[0])) {
@@ -922,6 +968,10 @@ main (int argc, char *argv[])
@@ -911,6 +957,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
@ -112,11 +112,11 @@ index 31012874..a667c2ee 100644
case 'h':
usage(argv[0]);
exit(RTVL_OK);
diff --git a/multipath/multipath.8.in b/multipath/multipath.8.in
index b88e9a4c..edd742aa 100644
--- a/multipath/multipath.8.in
+++ b/multipath/multipath.8.in
@@ -64,7 +64,7 @@ multipath \- Device mapper target autoconfig.
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 88149d53..072a03ee 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 \|]
@ -125,7 +125,7 @@ index b88e9a4c..edd742aa 100644
.
.LP
.B multipath
@@ -146,6 +146,11 @@ device mapper, path checkers ...).
@@ -145,6 +145,11 @@ device mapper, path checkers ...).
Add the WWID for the specified device to the WWIDs file.
.
.TP
@ -137,15 +137,15 @@ index b88e9a4c..edd742aa 100644
.B \-w
Remove the WWID for the specified device from the WWIDs file.
.
diff --git a/multipathd/multipathd.service.in b/multipathd/multipathd.service.in
index ab166435..1ec08c6e 100644
--- a/multipathd/multipathd.service.in
+++ b/multipathd/multipathd.service.in
@@ -19,6 +19,7 @@ StartLimitBurst=3
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index d76f94f9..bb5f383a 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -17,6 +17,7 @@ ConditionVirtualization=!container
[Service]
Type=notify
NotifyAccess=main
+ExecStartPre=-@BINDIR@/multipath -A
ExecStart=@BINDIR@/multipathd -d -s
ExecReload=@BINDIR@/multipathd reconfigure
Restart=on-failure
+ExecStartPre=-/sbin/multipath -A
ExecStart=/sbin/multipathd -d -s
ExecReload=/sbin/multipathd reconfigure
TasksMax=infinity

View file

@ -1,4 +1,4 @@
From 064d761121e7e2c7b63ab280e341d8010a413119 Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 7 Jun 2018 17:43:52 -0500
Subject: [PATCH] RH: reset default find_mutipaths value to off
@ -6,18 +6,16 @@ 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".
Co-authored-by: Paul Donohue <git@PaulSD.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/defaults.h | 2 +-
multipath/multipath.conf.5.in | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
libmultipath/defaults.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index 134b690a..e2fe7ac4 100644
index a5e9ea0c..514fd880 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -24,7 +24,7 @@
@@ -23,7 +23,7 @@
#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 0
@ -26,16 +24,3 @@ index 134b690a..e2fe7ac4 100644
#define DEFAULT_FAST_IO_FAIL 5
#define DEFAULT_DEV_LOSS_TMO 600
#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON
diff --git a/multipath/multipath.conf.5.in b/multipath/multipath.conf.5.in
index ba291e11..b8389db3 100644
--- a/multipath/multipath.conf.5.in
+++ b/multipath/multipath.conf.5.in
@@ -1227,7 +1227,7 @@ as non-multipath and passed on to upper layers.
\fBNote:\fR this may cause delays during device detection if
there are single-path devices which aren\'t blacklisted.
.TP
-The default is: \fBstrict\fR
+The default is: \fBoff\fR
.RE
.
.

View file

@ -1,4 +1,4 @@
From 335b8eb2773b07a602e84e14c1f3e289a9b25b5a Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 11 Apr 2019 13:25:42 -0500
Subject: [PATCH] RH: attempt to get ANA info via sysfs first
@ -13,10 +13,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c
index 34527b22..4eaa3cc3 100644
index b5c7873d..e139360c 100644
--- a/libmultipath/prioritizers/ana.c
+++ b/libmultipath/prioritizers/ana.c
@@ -23,6 +23,7 @@
@@ -24,6 +24,7 @@
#include "prio.h"
#include "util.h"
#include "structs.h"
@ -24,7 +24,7 @@ index 34527b22..4eaa3cc3 100644
enum {
ANA_ERR_GETCTRL_FAILED = 1,
@@ -35,6 +36,7 @@ enum {
@@ -36,6 +37,7 @@ enum {
ANA_ERR_GETNS_FAILED,
ANA_ERR_NO_MEMORY,
ANA_ERR_NO_INFORMATION,
@ -32,7 +32,7 @@ index 34527b22..4eaa3cc3 100644
};
static const char *ana_errmsg[] = {
@@ -48,6 +50,7 @@ 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",
@ -40,7 +40,7 @@ index 34527b22..4eaa3cc3 100644
};
static const char *anas_string[] = {
@@ -106,6 +109,27 @@ static int get_ana_state(__u32 nsid, __u32 anagrpid, void *ana_log,
@@ -107,6 +110,27 @@ static int get_ana_state(__u32 nsid, __u32 anagrpid, void *ana_log,
return -ANA_ERR_GETANAS_NOTFOUND;
}
@ -68,7 +68,7 @@ index 34527b22..4eaa3cc3 100644
static int get_ana_info(struct path * pp)
{
int rc;
@@ -208,8 +232,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args)
@@ -210,8 +234,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args,
if (pp->fd < 0)
rc = -ANA_ERR_NO_INFORMATION;

View file

@ -1,4 +1,4 @@
From 137c96d16b6bb03d8a52854e152db4ee36b7d9e4 Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 25 Mar 2021 13:05:10 -0500
Subject: [PATCH] RH: make parse_vpd_pg83 match scsi_id output
@ -14,10 +14,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index 31db8758..21cfcc73 100644
index 67ac0e6d..7fdbc1c3 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1225,13 +1225,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
@@ -1177,13 +1177,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
good_len = 8;
break;
case 2:
@ -33,7 +33,7 @@ index 31db8758..21cfcc73 100644
good_len = 8;
break;
default:
@@ -1249,10 +1245,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
@@ -1201,10 +1197,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
break;
case 0x8:
/* SCSI Name: Prio 3 */
@ -45,10 +45,10 @@ index 31db8758..21cfcc73 100644
case 0x1:
/* T-10 Vendor ID: Prio 2 */
diff --git a/tests/vpd.c b/tests/vpd.c
index e3212e61..cdb111bb 100644
index a7d2092c..2366cfba 100644
--- a/tests/vpd.c
+++ b/tests/vpd.c
@@ -232,11 +232,13 @@ static const char * const str_prefix[] = {
@@ -231,11 +231,13 @@ static const char * const str_prefix[] = {
[STR_IQN] = "iqn.",
};
@ -62,7 +62,7 @@ index e3212e61..cdb111bb 100644
/**
* create_scsi_string_desc() - create a SCSI name string descriptor.
@@ -767,6 +769,7 @@ make_test_vpd_naa(2, 18);
@@ -766,6 +768,7 @@ make_test_vpd_naa(2, 18);
make_test_vpd_naa(2, 17);
make_test_vpd_naa(2, 16);
@ -70,7 +70,7 @@ index e3212e61..cdb111bb 100644
/* SCSI Name string: EUI64, WWID size: 17 */
make_test_vpd_str(0, 20, 18)
make_test_vpd_str(0, 20, 17)
@@ -802,6 +805,7 @@ make_test_vpd_str(18, 20, 18)
@@ -801,6 +804,7 @@ make_test_vpd_str(18, 20, 18)
make_test_vpd_str(18, 20, 17)
make_test_vpd_str(18, 20, 16)
make_test_vpd_str(18, 20, 15)
@ -78,7 +78,7 @@ index e3212e61..cdb111bb 100644
static int test_vpd(void)
{
@@ -910,6 +914,7 @@ static int test_vpd(void)
@@ -909,6 +913,7 @@ static int test_vpd(void)
cmocka_unit_test(test_vpd_naa_2_18),
cmocka_unit_test(test_vpd_naa_2_17),
cmocka_unit_test(test_vpd_naa_2_16),
@ -86,7 +86,7 @@ index e3212e61..cdb111bb 100644
cmocka_unit_test(test_vpd_str_0_20_18),
cmocka_unit_test(test_vpd_str_0_20_17),
cmocka_unit_test(test_vpd_str_0_20_16),
@@ -934,6 +939,7 @@ static int test_vpd(void)
@@ -933,6 +938,7 @@ static int test_vpd(void)
cmocka_unit_test(test_vpd_str_18_20_17),
cmocka_unit_test(test_vpd_str_18_20_16),
cmocka_unit_test(test_vpd_str_18_20_15),

View file

@ -1,4 +1,4 @@
From 374755791536be4870ab2e93ae36549cbaaeb800 Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 25 Mar 2022 18:12:06 -0500
Subject: [PATCH] RH: add scsi device handlers to modules-load.d
@ -11,7 +11,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.inc b/Makefile.inc
index 03aee175..936a622f 100644
index 748911e2..c07bcb0c 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -16,7 +16,7 @@ READLINE :=

View file

@ -1,4 +1,4 @@
From cc15379130e8aa068e97c64afd46be212b456d4f Mon Sep 17 00:00:00 2001
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 15 Nov 2022 18:03:33 -0600
Subject: [PATCH] RH: compile with libreadline support
@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.inc b/Makefile.inc
index 936a622f..f475f70f 100644
index c07bcb0c..e59313c6 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -12,7 +12,7 @@

View file

@ -1,29 +1,42 @@
Name: device-mapper-multipath
Version: 0.13.0
Version: 0.9.4
Release: 2%{?dist}
Summary: Tools to manage multipath devices using device-mapper
# readline uses GPL-3.0-only
License: GPL-2.0-only AND GPL-3.0-only
License: GPLv2
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 -L https://github.com/opensvc/multipath-tools/archive/0.13.0.tar.gz -o multipath-tools-0.13.0.tgz
Source0: multipath-tools-0.13.0.tgz
# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.4.tar.gz -o multipath-tools-0.9.4.tgz
Source0: multipath-tools-0.9.4.tgz
Source1: multipath.conf
Patch0001: 0001-RH-fixup-udev-rules-for-redhat.patch
Patch0002: 0002-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0003: 0003-RH-don-t-start-without-a-config-file.patch
Patch0004: 0004-RH-Fix-nvme-function-missing-argument.patch
Patch0005: 0005-RH-use-rpm-optflags-if-present.patch
Patch0006: 0006-RH-add-mpathconf.patch
Patch0007: 0007-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0008: 0008-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0009: 0009-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0010: 0010-RH-make-parse_vpd_pg83-match-scsi_id-output.patch
Patch0011: 0011-RH-add-scsi-device-handlers-to-modules-load.d.patch
Patch0012: 0012-RH-compile-with-libreadline-support.patch
Patch0013: 0013-RH-Add-mpathcleanup.patch
Patch0001: 0001-multipathd-make-pr-registration-consistent.patch
Patch0002: 0002-libmultipath-make-prflag-an-enum.patch
Patch0003: 0003-multipathd-handle-no-active-paths-in-update_map_pr.patch
Patch0004: 0004-multipathd-add-missing-newline-to-cli_del_map-reply.patch
Patch0005: 0005-libmultipath-skip-extra-vector-work-in-remove_maps.patch
Patch0006: 0006-libmultipath-orphan-paths-if-coalesce_paths-frees-ne.patch
Patch0007: 0007-libmultipath-is_path_valid-check-if-device-is-in-use.patch
Patch0008: 0008-libmpathpersist-use-conf-timeout-for-updating-persis.patch
Patch0009: 0009-libmultipath-pathinfo-don-t-fail-for-devices-lacking.patch
Patch0010: 0010-libmultipath-bump-ABI-version-to-18.0.0.patch
Patch0011: 0011-libmultipath-use-select_reload_action-in-select_acti.patch
Patch0012: 0012-libmultipath-select-resize-action-even-if-reload-is-.patch
Patch0013: 0013-libmultipath-cleanup-ACT_CREATE-code-in-select_actio.patch
Patch0014: 0014-libmultipath-keep-renames-from-stopping-other-multip.patch
Patch0015: 0015-libmpathpersist-fix-resource-leak-in-update_map_pr.patch
Patch0016: 0016-RH-fixup-udev-rules-for-redhat.patch
Patch0017: 0017-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0018: 0018-RH-don-t-start-without-a-config-file.patch
Patch0019: 0019-RH-Fix-nvme-function-missing-argument.patch
Patch0020: 0020-RH-use-rpm-optflags-if-present.patch
Patch0021: 0021-RH-add-mpathconf.patch
Patch0022: 0022-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0023: 0023-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0024: 0024-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0025: 0025-RH-make-parse_vpd_pg83-match-scsi_id-output.patch
Patch0026: 0026-RH-add-scsi-device-handlers-to-modules-load.d.patch
Patch0027: 0027-RH-compile-with-libreadline-support.patch
# runtime
Requires: %{name}-libs = %{version}-%{release}
@ -65,8 +78,8 @@ The tools are :
%package libs
Summary: The %{name} modules and shared library
# only libmpathcmd is LGPL-2.1-or-later AND LGPL-2.0-or-later
License: GPL-2.0-or-later AND LGPL-2.1-or-later AND LGPL-2.0-or-later
# only libmpathcmd is LGPLv2+
License: GPLv2 and LGPLv2+
%description libs
The %{name}-libs provides the path checker
@ -91,8 +104,7 @@ kpartx manages partition creation and removal for device-mapper devices.
%package -n libdmmp
Summary: device-mapper-multipath C API library
# Automatically converted from old format: GPLv3+ - review is highly recommended.
License: GPL-3.0-or-later
License: GPLv3+
Requires: json-c
Requires: %{name} = %{version}-%{release}
Requires: %{name}-libs = %{version}-%{release}
@ -111,10 +123,11 @@ This package contains the files needed to develop applications that use
device-mapper-multipath's libdmmp C API library
%prep
%autosetup -n multipath-tools-0.13.0 -p1
%autosetup -n multipath-tools-0.9.4 -p1
cp %{SOURCE1} .
%build
%define _sbindir /usr/sbin
%define _libdir /usr/%{_lib}
%define _libmpathdir %{_libdir}/multipath
%define _pkgconfdir %{_libdir}/pkgconfig
@ -145,7 +158,7 @@ rm -rf %{buildroot}/%{_initrddir}
%postun
if [ $1 -ge 1 ] ; then
multipathd forcequeueing daemon > /dev/null 2>&1 || :
/sbin/multipathd forcequeueing daemon > /dev/null 2>&1 || :
fi
%systemd_postun_with_restart multipathd.service
@ -160,10 +173,8 @@ fi
%{_sbindir}/multipathd
%{_sbindir}/multipathc
%{_sbindir}/mpathconf
%{_sbindir}/mpathcleanup
%{_sbindir}/mpathpersist
%{_unitdir}/multipathd.service
%{_unitdir}/multipathd-queueing.service
%{_unitdir}/multipathd.socket
%{_mandir}/man5/multipath.conf.5*
%{_mandir}/man8/multipath.8*
@ -173,9 +184,9 @@ fi
%{_mandir}/man8/mpathpersist.8*
%config /usr/lib/udev/rules.d/62-multipath.rules
%config /usr/lib/udev/rules.d/11-dm-mpath.rules
%config /usr/lib/udev/rules.d/99-z-dm-mpath-late.rules
%dir %{_modulesloaddir}
%{_modulesloaddir}/scsi_dh.conf
%dir /usr/lib/modules-load.d
/usr/lib/modules-load.d/multipath.conf
/usr/lib/modules-load.d/scsi_dh.conf
%{_tmpfilesdir}/multipath.conf
%doc README.md
%doc multipath.conf
@ -234,124 +245,6 @@ fi
%{_pkgconfdir}/libdmmp.pc
%changelog
* Thu Nov 13 2025 Benjamin Marzinski <bmarzins@redhat.com> - 0.13.0-2
- Move STI tests to TMT
* Tue Nov 4 2025 Benjamin Marzinski <bmarzins@redhat.com> - 0.13.0-1
- Update source to upstream release 0.13.0
* Previous patches 0001-0004 are included in the tarball
- Install /lib/systemd/system/multipathd-queueing.service
- Rename redhat patches
* Previous patches 0005-0017 are now patches 0001-0013
* Wed Jul 23 2025 Fedora Release Engineering <releng@fedoraproject.org> - 0.11.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
* Thu Feb 27 2025 Benjamin Marzinski <bmarzins@redhat.com> - 0.11.1-1
- Update source to upstream staging branch for 0.11.1 plus additional
stable branch patches.
* Previous patches 0001-0032 are included in the tarball
- Rename redhat patches
* Previous patches 0033-0045 are now patches 0005-0017
* Sat Feb 1 2025 Benjamin Marzinski <bmarzins@redhat.com> - 0.10.0-5
- Update source to upstream staging branch for 0.10.y (will be 0.10.2 when
merged).
- Rebase redhat patches
* Thu Jan 16 2025 Fedora Release Engineering <releng@fedoraproject.org> - 0.10.0-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
* Sun Jan 12 2025 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 0.10.0-3
- Rebuilt for the bin-sbin merge (2nd attempt)
* Thu Aug 29 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.10.0-2
- update CI tests.
* Thu Aug 29 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.10.0-1
- Update source to upstream version 0.9.9
* Previous patch 0014-multipathd-fix-flush-check-in-flush_map.patch is
included in the source tarball
- Rebase redhat patches
* Fri Aug 9 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.9-6
- Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch
* multipath features tracking on failed removes
* Mon Jul 29 2024 Miroslav Suchý <msuchy@redhat.com> - 0.9.9-5
- convert license to SPDX
* Thu Jul 25 2024 Miroslav Suchý <msuchy@redhat.com> - 0.9.9-4
- convert license to SPDX
* Wed Jul 17 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.9-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
* Tue Jul 09 2024 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 0.9.9-2
- Rebuilt for the bin-sbin merge
* Thu Jun 13 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.9-1
- Update source to upstream version 0.9.9
* Previous patches 0001-0044 are included in the source tarball
- Rename redhat patches
* Previous patches 0045-0057 are now patches 0001-0013
* Mon May 20 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.8-1
- Update source to upstream version 0.9.8 plus latest staging branch
* Previous patches 0014 & 0015 are included in the source tarball
* patches 0001-0044 are from the upstream staging branch
- Rename redhat patches
* Previous patches 0001-0013 are now patches 0045-0057
- Install /lib/udev/rules.d/99-z-dm-mpath-late.rules
* Wed Jan 24 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.7-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Fri Jan 19 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.7-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Tue Jan 16 2024 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-5
- Add 0014-multipathd-fix-null-pointer-dereference-in-uev_updat.patch
* Fix auto_resize code to avoid a segfault
- Add 0015-multipathd-fix-auto-resize-configuration.patch
* Fix auto_resize default value
* Thu Nov 30 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-4
- Use modulesloaddir macro for installing scsi_dh.conf
* Wed Nov 29 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-3
- Fix multipath_conf_syntax test
- Fix restate_module test
* Tue Nov 28 2023 Paul Donohue <git@PaulSD.com> - 0.9.7-2
- Modify 0006-RH-add-mpathconf.patch
- Modify 0008-RH-reset-default-find_mutipaths-value-to-off.patch
* Fix find_multipaths values in docs and mpathconf
* Tue Nov 21 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.7-1
- Update source to upstream version 0.9.7
* Previous patches 0001-0040 are included in the source tarball
- Rename redhat patches
* Previous patches 0041-0053 are now patches 0001-0013
- Remove /usr/lib/modules-load.d/multipath.conf
* has been replaced with modprobe@dm_multipath.service unit Wants.
* Fri Sep 22 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.6-1
- Update to the head of the upstream staging branch
- Rename redhat patches
* Previous patches 0001-0012 are now patches 0041-0052
- Add 0053-RH-Add-mpathcleanup.patch
* add mpathcleanup program
* Wed Jul 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.5-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Tue May 16 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.5-1
- Update to the latest upstream release
* Previous patches 0001-0015 are included in the source tarball
- Rename redhat patches
* Previous patches 0016-0027 are now patches 0001-0012
* Thu Feb 2 2023 Benjamin Marzinski <bmarzins@redhat.com> - 0.9.4-2
- Update to the head of the upstream staging branch
* Patches 0011-0015 are from the upstream staging branch

View file

@ -1,58 +0,0 @@
summary: basic functionality tests
provision:
hardware:
memory: ">= 2 GB"
prepare:
how: install
package:
- device-mapper-multipath
- perl
discover:
how: shell
tests:
- name: medium_error_scsi_debug
path: /tests/medium_error_scsi_debug
test: ./main.sh
duration: 15m
- name: squelch_scsi_id
path: /tests/squelch_scsi_id
test: ./main.sh
duration: 15m
- name: multipathd_oom
path: /tests/multipathd_oom
test: ./main.sh
duration: 15m
- name: user_friendly_names
path: /tests/user_friendly_names
test: ./main.sh
duration: 15m
- name: kpartx_4k_aligned
path: /tests/kpartx_4k_aligned
test: ./main.sh
duration: 15m
- name: bindings
path: /tests/bindings
test: ./main.sh
duration: 15m
- name: restate_module
path: /tests/restate_module
test: ./main.sh
duration: 15m
- name: find_multipaths
path: /tests/find_multipaths
test: ./main.sh
duration: 15m
- name: multipath_conf_syntax
path: /tests/multipath_conf_syntax
test: ./main.sh
duration: 15m
- name: alias_clash
path: /tests/alias_clash
test: ./main.sh
duration: 15m
execute:
how: tmt

View file

@ -1,2 +1,2 @@
SHA512 (multipath-tools-0.13.0.tgz) = 75c84524ee27590b8b751ea500898a44e5ac3d58d55be6bcab919d0d423049db3a4466fcb9135705cf63ba074416973bb651255063269e9f682f11d21ba57e59
SHA512 (multipath-tools-0.9.4.tgz) = 5e0dcea610fc215e345444c04453a38f39c73e493c2bc53f6b3a90cd701266aabdf7c4693dfc321099af836d0019bf27355e265ad5db5deff48f8bb94ed4719d
SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942

View file

@ -18,110 +18,40 @@
# Author: Lin Li <lilin@redhat.com>
#set -x
source ../include/tc.sh || exit 200
source ../include/ec.sh || exit 200
tlog "running $0"
cleanup ()
{
local retries
if pidof multipathd; then
tlog "stopping multipathd"
trun "systemctl stop multipathd.service || pkill multipathd"
sleep 1
fi
retries=10
while pidof multipathd; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to stop multipath"
tend
fi
tlog "waiting for multipathd to stop"
sleep 2
pidof multipathd && pkill multipathd
done
trun "multipath -l -v1"
retries=10
while [[ -n `multipath -l -v1` ]]; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to remove deviece"
tend
fi
tlog "removing multipath device"
trun "udevadm settle"
trun "multipath -DF"
sleep 2
done
if lsmod | grep -q "^scsi_debug"; then
tlog "removing scsi_debug module"
tok "rmmod scsi_debug"
fi
trun "rm -f /etc/multipath.conf"
}
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
setup_config ()
{
trun "mpathconf --enable --user_friendly_names y"
sed -i '/^blacklist[[:space:]]*{/ a\
device {\
vendor ".*"\
product ".*"\
}
' /etc/multipath.conf
cat << _EOF_ >> /etc/multipath.conf
blacklist_exceptions {
device {
vendor Linux
product scsi_debug
}
}
_EOF_
trun "cat /etc/multipath.conf"
}
do_reconfigure ()
{
tok "multipathd reconfigure"
sleep 5
}
rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath
cleanup
setup_config
trun "rm -r /etc/multipath/bindings"
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2"
trun "service multipathd stop"
rpm -q device-mapper-multipath || yum install -y device-mapper-multipath
trun "mpathconf --enable --with_multipathd y --user_friendly_names y"
trun "service multipathd status"
sleep 5
trun "systemctl start multipathd.service"
while multipathd show daemon | grep -qv idle; do
tlog "waiting for multipathd to start"
sleep 1
done
trun 'multipathd show maps raw format "%n"'
mpath_name=`multipathd show maps raw format "%n" | head -1`
assert "[[ -n $mpath_name ]] && [[ $mpath_name != ok ]]"
trun "multipath -F"
sleep 5
terr "modprobe -r scsi_debug"
terr "modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 \
max_luns=2 no_lun_0=1"
sleep 60
disk_path=$(get_scsi_debug_devices)
disk=$(basename $disk_path)
mpath_name=$(get_mpath_disk_by_scsi_device $disk)
new_alias="mpath_test_$$"
trun "sed -i 's/$mpath_name/$new_alias/' /etc/multipath/bindings"
do_reconfigure
trun 'multipathd show maps raw format "%n"'
mpath_name=`multipathd show maps raw format "%n" | head -1`
assert "[[ $mpath_name = $new_alias ]]"
trun "multipath -r"
sleep 5
tok "[[ -b /dev/mapper/$new_alias ]]"
tok is_mpath $new_alias
sleep 5
cleanup
trun "multipath -F"
sleep 5
trun "modprobe -r scsi_debug"
trun "service multipathd stop"
sleep 3
trun "multipath -W"
trun "rm /etc/multipath/bindings"
tend

View file

@ -0,0 +1,49 @@
#!/bin/bash
# Copyright (c) 2016 Red Hat, Inc.
# #
# # This program is free software: you can redistribute it and/or modify
# # it under the terms of the GNU General Public License as published by
# # the Free Software Foundation, either version 3 of the License, or
# # (at your option) any later version.
# #
# # This program is distributed in the hope that it will be useful,
# # but WITHOUT ANY WARRANTY; without even the implied warranty of
# # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# # GNU General Public License for more details.
# #
# # You should have received a copy of the GNU General Public License
# # along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# # Author: Lin Li <lilin@redhat.com>
.PHONY: all install download clean
BUILT_FILES=
FILES=$(METADATA) Makefile PURPOSE main.sh
run: $(FILES) build
./main.sh
build: $(BUILT_FILES)
chmod a+x ./main.sh
clean:
rm -f *~ *.rpm $(BUILT_FILES)
include /usr/share/rhts/lib/rhts-make.include
$(METADATA): Makefile
@touch $(METADATA)
@echo "Owner: LiLin <lilin@redhat.com>" > $(METADATA)
@echo "Name: $(TEST)" >> $(METADATA)
@echo "Path: $(TEST_DIR)" >> $(METADATA)
@echo "License: GPLv3" >> $(METADATA)
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
@echo "Description: find_multipaths" >> $(METADATA)
@echo "TestTime: 15m" >> $(METADATA)
@echo "RunFor: device-mapper-multipath" >> $(METADATA)
@echo "Requires: device-mapper-multipath" >> $(METADATA)
rhts-lint $(METADATA)

View file

@ -18,92 +18,38 @@
# Author: Lin Li <lilin@redhat.com>
#set -x
source ../include/tc.sh || exit 200
tlog "running $0"
remove_devices ()
{
local retries
retries=10
while [[ -n `multipath -l -v1` ]]; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to remove devices"
cleanup
tend
fi
tlog "removing multipath devices"
trun "udevadm settle"
trun "multipath -F"
sleep 2
done
}
source ../include/ec.sh || exit 200
cleanup ()
{
local retries
if pidof multipathd; then
tlog "stopping multipathd"
trun "systemctl stop multipathd.service || pkill multipathd"
sleep 1
fi
retries=10
while pidof multipathd; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to stop multipath"
tend
fi
tlog "waiting for multipathd to stop"
sleep 2
pidof multipathd && pkill multipathd
done
trun "multipath -l -v1"
retries=10
while [[ -n `multipath -l -v1` ]]; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to remove devices"
tend
fi
tlog "removing multipath devices"
trun "udevadm settle"
trun "multipath -DF"
sleep 2
done
if lsmod | grep -q "^scsi_debug"; then
tlog "removing scsi_debug module"
tok "rmmod scsi_debug"
fi
trun "rm -f /etc/multipath.conf"
trun "rm -f /etc/multipath/wwids"
trun "rm -r /etc/multipath/bindings"
trun "multipathd disablequeueing maps"
trun "service multipathd stop"
sleep 5
trun "udevadm settle"
trun "multipath -F"
sleep 5
trun "modprobe -r scsi_debug"
}
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
tlog "running $0"
setup_config ()
{
trun "mpathconf --enable --user_friendly_names y --find_multipaths y"
sed -i '/^blacklist[[:space:]]*{/ a\
device {\
vendor ".*"\
product ".*"\
}
# which not set find_multipaths yes, so multipath always create a multipath device for single device
# so stop service and reconfig with --find_multipaths y, and reload/start the service again.
rpm -q device-mapper-multipath || yum install -y device-mapper-multipath
# test with find_multipath=y, will not multipath for the single device; reload/start the service to enable the config
cleanup
trun "rm -f /etc/multipath.conf"
trun "mpathconf --enable --user_friendly_names y --find_multipaths y --with_multipathd n"
sed -i '/^blacklist[[:space:]]*{/ a\
device {\n vendor ".*"\n product ".*"\n }
' /etc/multipath.conf
cat << _EOF_ >> /etc/multipath.conf
if grep -qw blacklist_exceptions /etc/multipath.conf ; then
sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
device {\n vendor Linux\n product scsi_debug\n }
' /etc/multipath.conf
else
cat << _EOF_ >> /etc/multipath.conf
blacklist_exceptions {
device {
vendor Linux
@ -111,69 +57,56 @@ blacklist_exceptions {
}
}
_EOF_
trun "cat /etc/multipath.conf"
}
do_reconfigure ()
{
trun "cat /etc/multipath.conf"
tok "multipathd reconfigure"
sleep 5
}
trun "rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath"
cleanup
setup_config
# test with find_multipath=y, will not multipath the single device
fi
trun "service multipathd start"
trun "modprobe scsi_debug"
sleep 5
trun "systemctl start multipathd.service"
while multipathd show daemon | grep -qv idle; do
tlog "waiting for multipathd to start"
sleep 1
done
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ $mpath_name = '[orphan]' ]]"
remove_devices
# test with find_multipath=n, will multipath the single device
trun 'mpathconf --find_multipaths n'
do_reconfigure
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ -n $mpath_name ]] && [[ $mpath_name != '[orphan]' ]]"
remove_devices
# test with find_multipath=y, with multipath single device with known WWID
trun 'mpathconf --find_multipaths y'
do_reconfigure
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ -n $mpath_name ]] && [[ $mpath_name != '[orphan]' ]]"
remove_devices
# Clear WWID, test with find_multipath=y, will not multipath single device
trun "multipath -W"
do_reconfigure
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ $mpath_name = '[orphan]' ]]"
remove_devices
assert 'rmmod scsi_debug'
cat /etc/multipath/wwids
trun "multipath"
disk_path=$(get_scsi_debug_devices)
disk_node=$(basename $disk_path)
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok '[[ $mpath_name = "[orphan]" ]]'
# test with find_multipath=n, will multipath for the single device
trun "mpathconf --user_friendly_names y --find_multipaths n --with_multipathd y"
sleep 5
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok "is_mpath $mpath_name"
# flush new created path
trun "multipath -F"
sleep 1
# test with find_multipath=y, A path has the same WWID as a multipath device that was previously created
trun "mpathconf --user_friendly_names y --find_multipaths y --with_multipathd y"
sleep 5
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok "is_mpath $mpath_name"
trun "multipath -F"
sleep 1
# Clear wwid, test with find_multipath=y, will not multipath for the single device
trun "multipath -W"
trun "service multipathd reload"
sleep 5
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok '[[ $mpath_name = "[orphan]" ]]'
trun "multipath -F"
sleep 5
trun "modprobe -r scsi_debug"
# test find_multipaths=y create device for paths have same wwid
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2"
sleep 5
trun 'multipathd show paths raw format "%d %m"'
trun 'cat /etc/multipath/wwids'
mpath_name=`multipathd show paths raw format "%m" | head -1`
tok "[[ -n $mpath_name ]] && [[ $mpath_name != '[orphan]' ]]"
tok "modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 max_luns=2 no_lun_0=1"
sleep 10
disk_paths=$(get_scsi_debug_devices)
disk_node=$(basename $disk_paths)
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
tok "is_mpath $mpath_name"
cleanup
trun "multipath -W"
cat /etc/multipath/wwids
tend

View file

@ -44,12 +44,9 @@ function _init (){
}
function _destroy (){
Cmd "multipathd disablequeueing maps"
sleep 10
Cmd "multipath -F"
sleep 5
Cmd "multipath -DF -R2"
Cmd "service multipathd stop"
sleep 5
Cmd "udevadm settle"
Cmd "modprobe -r scsi_debug"
}
@ -177,7 +174,10 @@ AA
fi
#setup scsi_debug
echo "INFO: Loading scsi_debug module for simulation of mpath"
modprobe scsi_debug vpd_use_hostno=0 add_host=2
modprobe scsi_debug \
num_tgts=1 vpd_use_hostno=0 \
add_host=4 delay=20 \
max_luns=2 no_lun_0=1 2>&1 1>/dev/null
echo "INFO: Waiting for udev to create /dev/sdX"
sleep 15s #wait for udev to create /dev/sdX
@ -189,6 +189,8 @@ AA
#enable multipath for scsi_debug.
cat << AA > /etc/multipath.conf
defaults {
#Enable multibus is for mutlbus testing
path_grouping_policy multibus
user_friendly_names yes
}
blacklist {

View file

@ -16,51 +16,47 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Author: LiLin <lilin@redhat.com>
source ../include/tc.sh || exit 200
cleanup()
function cleanup()
{
sleep 5
udevadm settle
trun "multipath -DF"
multipath -F
sleep 5
trun "modprobe -r scsi_debug"
modprobe -r scsi_debug
return 0
}
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
tlog "running $0"
rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath
trun "multipathd disablequeueing maps"
cleanup
trun "service multipathd stop"
trun "rm -f /etc/multipath.conf"
trun "mpathconf --enable"
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2 opts=2"
yum -y install device-mapper device-mapper-multipath
mpathconf --enable
service multipathd stop
modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 max_luns=2 no_lun_0=1 opts=2
sleep 5
trun "multipath"
multipath > /dev/null
sleep 5
trun "multipath -l"
mpathdev=`multipath -l | grep scsi_debug | awk '{print $1}' | head -1`
assert "[[ -n \"$mpathdev\" ]]"
if [ -z "$mpathdev" ]; then
echo "------- FAIL, no multipath device created -----"
cleanup
exit 1
fi
before_active=`multipath -l $mpathdev | grep "active undef" | wc -l`
tlog "before active = ${before_active}"
IO_error=`dd if=/dev/zero of=/dev/mapper/$mpathdev bs=1024 seek=2330 count=10 2>&1 | grep -o "Input/output error" `
assert "[[ -n \"$IO_error\" ]]"
after_active=`multipath -l $mpathdev | grep "active undef" | wc -l`
tlog "after active = ${after_active}"
assert "[[ \"$before_active\" -eq \"$after_active\" ]]"
cleanup
tend
if [ -n "$IO_error" ];then
after_active=`multipath -l $mpathdev | grep "active undef" | wc -l`
if [ "$before_active" -eq "$after_active" ]; then
echo "------- PASS, a medium error, correctly generated an I/O error and did not fail paths -----"
cleanup
exit 0
else
echo "------- FAIL, paths failed -----"
cleanup
exit 1
fi
else
echo "------- FAIL, did not generate an I/O error -----"
cleanup
exit 1
fi

View file

@ -119,7 +119,7 @@ tok "multipath -ll | grep mypath"
# test wrong alias keyword
trun "sed -i 's/alias.*$/alia mypath/g' /etc/multipath.conf"
tok "multipath 2>&1 | grep 'invalid keyword in the multipath section: alia'"
tok "multipath 2>&1 | grep 'invalid keyword: alia'"
trun "multipath -r"
tok "multipath -ll | grep mpath"
trun "sed -i 's/alia.*$/alias mypath/g' /etc/multipath.conf"

5
tests/provision.fmf Normal file
View file

@ -0,0 +1,5 @@
---
standard-inventory-qcow2:
qemu:
m: 2G

View file

@ -48,8 +48,10 @@ rpm -q device-mapper-multipath || yum install -y device-mapper-multipath
tlog "device-mapper-multipath is installed"
# cleanup existing devices
trun "rm /etc/multipath.conf"
trun "mpathconf --enable --with_module y --option max_polling_interval:10"
trun "mpathconf --option detect_pgpolicy_use_tpg:yes"
trun "mpathconf --enable --with_module y"
sed -i '/^defaults[[:space:]]*{/ a\
max_polling_interval 10
' /etc/multipath.conf
trun "service multipathd stop"
trun "multipath -F"
sleep 5
@ -67,7 +69,7 @@ tlog "Checking if active path count equals 2"
assert "[[ $pathcount -eq 2 ]]"
tlog "offline one path device"
pathname=`multipathd show paths raw format "%d %m %p" | grep ${mpathdev} | sort -k 3n | head -1 | awk '{print $1}'`
pathname=`multipathd show paths raw format "%d %m" | grep ${mpathdev} | head -1 | awk '{print $1}'`
tlog "path to offline: ${pathname}"
trun "echo 'offline' > /sys/block/${pathname}/device/state"
tlog "waiting for multipathd to fail path"

44
tests/tests.yml Normal file
View file

@ -0,0 +1,44 @@
---
# No tests suitable for atomic environment
# No tests suitable for container environment
# Tests suitable for classic environment
- hosts: localhost
roles:
- role: standard-test-basic
tags:
- classic
tests:
- medium_error_scsi_debug:
run: ./main.sh
timeout: 15m
- squelch_scsi_id:
run: ./main.sh
timeout: 15m
- multipathd_oom:
run: ./main.sh
timeout: 15m
- user_friendly_names:
run: ./main.sh
timeout: 15m
- kpartx_4k_aligned:
run: ./main.sh
timeout: 15m
- bindings:
run: ./main.sh
timeout: 15m
- restate_module:
run: ./main.sh
timeout: 15m
- find_multipaths:
run: ./main.sh
timeout: 15m
- multipath_conf_syntax:
run: ./main.sh
timeout: 15m
- alias_clash:
run: ./main.sh
timeout: 15m
required_packages:
- device-mapper-multipath
- perl

View file

@ -17,125 +17,50 @@
# Author: Lin Li <lilin@redhat.com>
source ../include/tc.sh || exit 200
source ../include/ec.sh || exit 200
tlog "running $0"
cleanup ()
{
local retries
if pidof multipathd; then
tlog "stopping multipathd"
trun "systemctl stop multipathd.service || pkill multipathd"
sleep 1
fi
retries=10
while pidof multipathd; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to stop multipath"
tend
fi
tlog "waiting for multipathd to stop"
sleep 2
pidof multipathd && pkill multipathd
done
trun "multipath -l -v1"
retries=10
while [[ -n `multipath -l -v1` ]]; do
((retries--))
if [[ $retries -le 0 ]]; then
tfail_ "failed to remove deviece"
tend
fi
tlog "removing multipath device"
trun "udevadm settle"
trun "multipath -DF"
sleep 2
done
if lsmod | grep -q "^scsi_debug"; then
tlog "removing scsi_debug module"
tok "rmmod scsi_debug"
fi
trun "rm -f /etc/multipath.conf"
}
trun "rpm -q device-mapper-multipath || yum install -y device-mapper-multipath"
trun "mpathconf --enable --with_multipathd y --user_friendly_names y"
assert ()
{
local cmd="$*"
_trun_ "$cmd" 0
if test $? -eq 0; then
tpass_ "$cmd" ;
else
tfail_ "$cmd" ;
cleanup ;
tend ;
fi
}
# backup the /etc/multipath.conf
trun "cp /etc/multipath.conf /etc/multipath.conf.$$"
trun "multipath -F"
setup_config ()
{
trun "mpathconf --enable --user_friendly_names y"
sed -i '/^blacklist[[:space:]]*{/ a\
device {\
vendor ".*"\
product ".*"\
}
' /etc/multipath.conf
cat << _EOF_ >> /etc/multipath.conf
trun "modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 \
max_luns=2 no_lun_0=1"
trun "multipath"
# wwid shown slowly on s390x by the script framework, but normally when run by multipath command directly
# so extend sleep time
sleep 20
blacklist_exceptions {
device {
vendor Linux
product scsi_debug
}
}
disk=$(get_scsi_debug_devices)
disk=$(basename $disk)
wwid=$(get_wwid_of_disk $disk)
mpath=$(get_mpath_disk_by_scsi_device $disk)
multipaths {
multipath {
wwid TEST_WWID
alias test
}
}
_EOF_
trun "cat /etc/multipath.conf"
}
# user_friendly_names = yes and mpath=test
#cur_dir=/mnt/tests/kernel/storage/multipath/user_friendly_names/
#cur_dir=/home/test/scratch/device-mapper-multipath/user_friendly_names
trun "cat multipath.conf.yes | sed "s/your_wwid/$wwid/g" > /etc/multipath.conf"
trun "cat -n /etc/multipath.conf"
trun "multipath -r"
echo ">>> Verify 'test ($wwid)' is present ..."
trun "multipath -ll"
tok "multipath -ll | egrep \"^test\""
do_reconfigure ()
{
trun "cat /etc/multipath.conf"
tok "multipathd reconfigure"
sleep 5
}
# user_friendly_names = no
trun "cat multipath.conf.no > /etc/multipath.conf"
trun "multipath -r"
echo ">>> Verify 'test' is gone but '$wwid' present ..."
trun "multipath -ll"
tok "multipath -ll | egrep \"^$wwid\""
sleep 10
tok "multipath -F $wwid"
sleep 10
trun "modprobe -r scsi_debug"
trun "rpm -q device-mapper-multipath || dnf install -y device-mapper-multipath"
cleanup
setup_config
trun "rm -r /etc/multipath/bindings"
trun "modprobe scsi_debug vpd_use_hostno=0 add_host=2"
sleep 5
trun "systemctl start multipathd.service"
while multipathd show daemon | grep -qv idle; do
tlog "waiting for multipathd to start"
sleep 1
done
trun 'multipathd show maps raw format "%n %w"'
# verify user_friendly_name
tok 'multipathd show maps raw format "%n" | head -1 | grep -q mpath'
wwid=`multipathd show maps raw format "%w" | head -1`
assert "[[ -n $wwid ]] && [[ $wwid != ok ]]"
sed -i 's/TEST_WWID/'"$wwid"'/' /etc/multipath.conf
do_reconfigure
trun 'multipathd show maps raw format "%n %w"'
# verify configured alias takes precedence over user_friendly_name
tok 'multipathd show maps raw format "%n" | head -1 | grep -q test'
trun "mpathconf --user_friendly_names n"
do_reconfigure
trun 'multipathd show maps raw format "%n %w"'
# verify configured alias takes precedence over wwid name
tok 'multipathd show maps raw format "%n" | head -1 | grep -q test'
sed -i 's/'"$wwid"'/TEST_WWID/' /etc/multipath.conf
do_reconfigure
trun 'multipathd show maps raw format "%n %w"'
tok 'multipathd show maps raw format "%n" | head -1 | grep -q '"$wwid"
cleanup
trun "cp /etc/multipath.conf.$$ /etc/multipath.conf"
trun "multipath -F; multipath"
tend

View file

@ -0,0 +1,3 @@
defaults {
user_friendly_names no
}

View file

@ -0,0 +1,11 @@
defaults {
user_friendly_names yes
}
multipaths {
multipath {
wwid your_wwid
alias test
}
}