device-mapper-multipath-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
This commit is contained in:
Benjamin Marzinski 2023-05-16 17:02:58 -05:00
parent bbfe9b1229
commit 0761930b9e
30 changed files with 33 additions and 1790 deletions

1
.gitignore vendored
View File

@ -27,3 +27,4 @@ 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

View File

@ -1,159 +0,0 @@
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

@ -1,166 +0,0 @@
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

@ -57,7 +57,7 @@ index 87947469..0dc89c16 100644
enum devtypes {
DEV_NONE,
diff --git a/multipath/multipath.rules.in b/multipath/multipath.rules.in
index 8d3cf33a..5c4447a2 100644
index 6f123760..70b69a06 100644
--- a/multipath/multipath.rules.in
+++ b/multipath/multipath.rules.in
@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath"
@ -82,7 +82,7 @@ index bdf102eb..a16a0bd5 100644
.
.\" ----------------------------------------------------------------------------
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index aec62dbb..d76f94f9 100644
index 5a9cde12..311f49c7 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -6,6 +6,7 @@ Wants=systemd-udevd-kernel.socket

View File

@ -1,152 +0,0 @@
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

@ -1,24 +0,0 @@
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,33 +0,0 @@
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

@ -1,41 +0,0 @@
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

@ -20,7 +20,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
3 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index b9f360b4..5eb752ee 100644
index 90f940f1..3549740a 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -120,7 +120,7 @@ usage (char * progname)
@ -92,7 +92,7 @@ index b9f360b4..5eb752ee 100644
static int
configure (struct config *conf, enum mpath_cmds cmd,
enum devtypes dev_type, char *devpath)
@@ -840,7 +886,7 @@ main (int argc, char *argv[])
@@ -842,7 +888,7 @@ main (int argc, char *argv[])
conf->force_sync = 1;
if (atexit(cleanup_vecs))
condlog(1, "failed to register cleanup handler for vecs: %m");
@ -101,7 +101,7 @@ index b9f360b4..5eb752ee 100644
switch(arg) {
case 'v':
if (!isdigit(optarg[0])) {
@@ -911,6 +957,10 @@ main (int argc, char *argv[])
@@ -913,6 +959,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
@ -138,7 +138,7 @@ index 88149d53..072a03ee 100644
Remove the WWID for the specified device from the WWIDs file.
.
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index d76f94f9..bb5f383a 100644
index 311f49c7..5324f4bc 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -17,6 +17,7 @@ ConditionVirtualization=!container

View File

@ -1,609 +0,0 @@
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

@ -1,55 +0,0 @@
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

@ -1,77 +0,0 @@
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

@ -14,7 +14,7 @@ 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 67ac0e6d..7fdbc1c3 100644
index 6865cd92..72825829 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1177,13 +1177,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
@ -45,7 +45,7 @@ index 67ac0e6d..7fdbc1c3 100644
case 0x1:
/* T-10 Vendor ID: Prio 2 */
diff --git a/tests/vpd.c b/tests/vpd.c
index a7d2092c..2366cfba 100644
index 1b2d62d6..7309b5c5 100644
--- a/tests/vpd.c
+++ b/tests/vpd.c
@@ -231,11 +231,13 @@ static const char * const str_prefix[] = {

View File

@ -1,26 +0,0 @@
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

@ -1,39 +0,0 @@
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

@ -1,46 +0,0 @@
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,68 +0,0 @@
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

@ -1,186 +0,0 @@
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

@ -1,68 +0,0 @@
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,42 +1,27 @@
Name: device-mapper-multipath
Version: 0.9.4
Release: 2%{?dist}
Version: 0.9.5
Release: 1%{?dist}
Summary: Tools to manage multipath devices using device-mapper
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.9.4.tar.gz -o multipath-tools-0.9.4.tgz
Source0: multipath-tools-0.9.4.tgz
# curl -L https://github.com/opensvc/multipath-tools/archive/0.9.5.tar.gz -o multipath-tools-0.9.5.tgz
Source0: multipath-tools-0.9.5.tgz
Source1: multipath.conf
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
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
# runtime
Requires: %{name}-libs = %{version}-%{release}
@ -123,7 +108,7 @@ 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.9.4 -p1
%autosetup -n multipath-tools-0.9.5 -p1
cp %{SOURCE1} .
%build
@ -245,6 +230,12 @@ fi
%{_pkgconfdir}/libdmmp.pc
%changelog
* 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,2 +1,2 @@
SHA512 (multipath-tools-0.9.4.tgz) = 5e0dcea610fc215e345444c04453a38f39c73e493c2bc53f6b3a90cd701266aabdf7c4693dfc321099af836d0019bf27355e265ad5db5deff48f8bb94ed4719d
SHA512 (multipath-tools-0.9.5.tgz) = 39c2e5d45542c6076eb3b17b9994629b4c1f74347aa43e0119001fa2d07d3a606fd5e617962906a11b313afb37a115bd8eec2ef24447e980e61b5900625f9146
SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942