device-mapper-multipath-0.8.7-45
Add 0208-libmpathpersist-fix-register-retry-status-checking.patch
Add 0209-multipathd-remember-number-of-registered-keys-when-i.patch
Add 0210-libmpathpersist-fix-code-for-skipping-multipathd-pat.patch
* Fixes RHEL-148462 ("Improve multipathd's handling of updating
persistent reservations on restored paths. [rhel-9]")
Resolves: RHEL-148462
This commit is contained in:
parent
9fce6f55fc
commit
3941311b98
@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 1 Dec 2025 22:02:10 -0500
|
||||
Subject: [PATCH] libmpathpersist: fix register retry status checking
|
||||
|
||||
If there libmpathpersist failed to create a thread to retry the register
|
||||
and ignore command, mpath_prout_reg should fail. Instead, the code was
|
||||
simply ignoring the failed threads. Fix that.
|
||||
|
||||
Fixes: 2a4ca250 ("libmpathpersist: change how reservation conflicts are handled")
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index 72be48c1..6cb56dab 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -858,18 +858,19 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count; i++) {
|
||||
- if (thread[i].param.status != MPATH_PR_SKIP &&
|
||||
- thread[i].param.status != MPATH_PR_THREAD_ERROR) {
|
||||
+ if (thread[i].param.status == MPATH_PR_SKIP)
|
||||
+ continue;
|
||||
+ if (thread[i].param.status != MPATH_PR_THREAD_ERROR) {
|
||||
rc = pthread_join(thread[i].id, NULL);
|
||||
if (rc) {
|
||||
condlog(3, "%s: failed to join thread while retrying %d",
|
||||
- mpp->wwid, i);
|
||||
+ mpp->wwid, i);
|
||||
}
|
||||
- if (thread[i].param.status == MPATH_PR_RETRYABLE_ERROR)
|
||||
- retryable_error = true;
|
||||
- else if (status == MPATH_PR_SUCCESS)
|
||||
- status = thread[i].param.status;
|
||||
}
|
||||
+ if (thread[i].param.status == MPATH_PR_RETRYABLE_ERROR)
|
||||
+ retryable_error = true;
|
||||
+ else if (status == MPATH_PR_SUCCESS)
|
||||
+ status = thread[i].param.status;
|
||||
}
|
||||
need_retry = false;
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 1 Dec 2025 22:02:12 -0500
|
||||
Subject: [PATCH] multipathd: remember number of registered keys when ioctl
|
||||
fails
|
||||
|
||||
If prin_do_scsi_ioctl() fails in update_map_pr() for some reason other
|
||||
than Persistent Reservations not being supported, It shouldn't clear the
|
||||
number of registered keys, since there's no reason to think that it has
|
||||
changed. Similarly, if update_map_pr() fails in mpath_pr_event_handle(),
|
||||
don't assume that the nr_keys_needed was cleared. Just return whatever
|
||||
the value is now. This saves multipathd from doing pointless calls to
|
||||
update_map_pr(), if one of the paths is failing.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
multipathd/main.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index d91a4d49..2526d8d1 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -3842,7 +3842,9 @@ void unset_pr(struct multipath *mpp)
|
||||
* The number of found keys must be at least as large as *nr_keys,
|
||||
* and if MPATH_PR_SUCCESS is returned and mpp->prflag is PR_SET after
|
||||
* the call, *nr_keys will be set to the number of found keys. Otherwise
|
||||
- * it will be set to 0.
|
||||
+ * if mpp->prflag is PR_UNSET it will be set to 0. If MPATH_PR_SUCCESS
|
||||
+ * is not returned and mpp->prflag is not PR_UNSET, nr_keys will not be
|
||||
+ * changed.
|
||||
*/
|
||||
static int update_map_pr(struct multipath *mpp, struct path *pp, unsigned int *nr_keys)
|
||||
{
|
||||
@@ -3871,11 +3873,12 @@ static int update_map_pr(struct multipath *mpp, struct path *pp, unsigned int *n
|
||||
|
||||
ret = prin_do_scsi_ioctl(pp->dev, MPATH_PRIN_RKEY_SA, &resp, 0);
|
||||
if (ret != MPATH_PR_SUCCESS) {
|
||||
- if (ret == MPATH_PR_ILLEGAL_REQ)
|
||||
+ if (ret == MPATH_PR_ILLEGAL_REQ) {
|
||||
unset_pr(mpp);
|
||||
+ *nr_keys = 0;
|
||||
+ }
|
||||
condlog(0, "%s : pr in read keys service action failed Error=%d",
|
||||
mpp->alias, ret);
|
||||
- *nr_keys = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3990,7 +3993,7 @@ retry:
|
||||
clear_reg ? "Clearing" : "Setting", pp->dev, ret);
|
||||
} else if (!clear_reg) {
|
||||
if (update_map_pr(mpp, pp, &nr_keys_needed) != MPATH_PR_SUCCESS)
|
||||
- return 0;
|
||||
+ return nr_keys_needed;
|
||||
if (mpp->prflag != PR_SET) {
|
||||
memset(¶m, 0, sizeof(param));
|
||||
clear_reg = true;
|
||||
459
0210-libmpathpersist-fix-code-for-skipping-multipathd-pat.patch
Normal file
459
0210-libmpathpersist-fix-code-for-skipping-multipathd-pat.patch
Normal file
@ -0,0 +1,459 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 15 Dec 2025 15:29:58 -0500
|
||||
Subject: [PATCH] libmpathpersist: fix code for skipping multipathd path
|
||||
registration
|
||||
|
||||
When libmpathpersist notifies multipathd that a key has been registered,
|
||||
cli_setprstatus() calls pr_register_active_paths() with a flag to let it
|
||||
know that the paths are likely already registered, and it can skip
|
||||
re-registering them, as long as the number of active paths matches the
|
||||
number of registered keys. This shortcut can fail, causing multipathd to
|
||||
not register needed paths, if either a path becomes usable and another
|
||||
becomes unusable while libmpathpersist is running or if there already
|
||||
were registered keys for I_T Nexus's that don't correspond to path
|
||||
devices.
|
||||
|
||||
To make this shortcut work in cases like that, this commit adds a new
|
||||
multipathd command "setprstatus map <map> pathlist <pathlist>", where
|
||||
<pathlist> is a quoted, whitespace separated list of scsi path devices.
|
||||
libmpathpersist will send out the list of paths it registered the key
|
||||
on. pr_register_active_paths() will skip calling mpath_pr_event_handle()
|
||||
for paths on that list.
|
||||
|
||||
In order to deal with the possiblity of a preempt occuring while
|
||||
libmpathpersist was running, the code still needs to check that it has
|
||||
the expected number of keys.
|
||||
|
||||
Fixes: f7d6cd17 ("multipathd: Fix race while registering PR key")
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 6 +--
|
||||
libmpathpersist/mpath_updatepr.c | 50 ++++++++++++++++++-------
|
||||
libmpathpersist/mpathpr.h | 2 +-
|
||||
multipathd/cli.c | 2 +
|
||||
multipathd/cli.h | 2 +
|
||||
multipathd/cli_handlers.c | 37 +++++++++++++++++--
|
||||
multipathd/cli_handlers.h | 1 +
|
||||
multipathd/main.c | 63 +++++++++++++++++++++-----------
|
||||
multipathd/main.h | 4 +-
|
||||
multipathd/multipathd.8 | 10 ++++-
|
||||
10 files changed, 132 insertions(+), 45 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index 6cb56dab..ab8fa630 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -527,12 +527,12 @@ static int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
|
||||
case MPATH_PROUT_REG_SA:
|
||||
case MPATH_PROUT_REG_IGN_SA:
|
||||
if (unregistering)
|
||||
- update_prflag(alias, 0);
|
||||
+ update_prflag(mpp, 0);
|
||||
else
|
||||
- update_prflag(alias, 1);
|
||||
+ update_prflag(mpp, 1);
|
||||
break;
|
||||
case MPATH_PROUT_CLEAR_SA:
|
||||
- update_prflag(alias, 0);
|
||||
+ update_prflag(mpp, 0);
|
||||
if (mpp->prkey_source == PRKEY_SOURCE_FILE)
|
||||
update_prkey(alias, 0);
|
||||
break;
|
||||
diff --git a/libmpathpersist/mpath_updatepr.c b/libmpathpersist/mpath_updatepr.c
|
||||
index bfa6e089..e24432bb 100644
|
||||
--- a/libmpathpersist/mpath_updatepr.c
|
||||
+++ b/libmpathpersist/mpath_updatepr.c
|
||||
@@ -19,9 +19,9 @@
|
||||
#include "memory.h"
|
||||
#include "mpathpr.h"
|
||||
#include "structs.h"
|
||||
+#include "strbuf.h"
|
||||
|
||||
-
|
||||
-static char *do_pr(char *alias, char *str)
|
||||
+static char *do_pr(char *alias, const char *str)
|
||||
{
|
||||
int fd;
|
||||
char *reply;
|
||||
@@ -51,24 +51,26 @@ static char *do_pr(char *alias, char *str)
|
||||
return reply;
|
||||
}
|
||||
|
||||
-static int do_update_pr(char *alias, char *cmd, char *key)
|
||||
+static int do_update_pr(char *alias, char *cmd, const char *data)
|
||||
{
|
||||
- char str[256];
|
||||
+ STRBUF_ON_STACK(buf);
|
||||
char *reply = NULL;
|
||||
int ret = -1;
|
||||
|
||||
- if (key)
|
||||
- snprintf(str,sizeof(str),"%s map %s key %s", cmd, alias, key);
|
||||
+ if (data)
|
||||
+ print_strbuf(&buf, "%s map %s %s %s", cmd, alias,
|
||||
+ strcmp(cmd, "setprkey") ? "pathlist" : "key", data);
|
||||
else
|
||||
- snprintf(str,sizeof(str),"%s map %s", cmd, alias);
|
||||
+ print_strbuf(&buf, "%s map %s", cmd, alias);
|
||||
|
||||
- reply = do_pr(alias, str);
|
||||
+ reply = do_pr(alias, get_strbuf_str(&buf));
|
||||
if (reply) {
|
||||
- condlog (2, "%s: message=%s reply=%s", alias, str, reply);
|
||||
- if (reply && strncmp(reply,"ok", 2) == 0)
|
||||
+ if (strncmp(reply, "ok", 2) == 0)
|
||||
ret = 0;
|
||||
else
|
||||
ret = -1;
|
||||
+ condlog(ret ? 0 : 4, "%s: message=%s reply=%s", alias,
|
||||
+ get_strbuf_str(&buf), reply);
|
||||
}
|
||||
|
||||
free(reply);
|
||||
@@ -104,9 +106,31 @@ int get_prhold(char *mapname) {
|
||||
return do_get_pr(mapname, "getprhold");
|
||||
}
|
||||
|
||||
-int update_prflag(char *mapname, int set) {
|
||||
- return do_update_pr(mapname, (set)? "setprstatus" : "unsetprstatus",
|
||||
- NULL);
|
||||
+int update_prflag(struct multipath *mpp, int set)
|
||||
+{
|
||||
+ STRBUF_ON_STACK(buf);
|
||||
+ int i, j;
|
||||
+ bool first = true;
|
||||
+ struct pathgroup *pgp = NULL;
|
||||
+ struct path *pp = NULL;
|
||||
+
|
||||
+ if (!set)
|
||||
+ return do_update_pr(mpp->alias, "unsetprstatus", NULL);
|
||||
+
|
||||
+ append_strbuf_str(&buf, "\"");
|
||||
+ vector_foreach_slot (mpp->pg, pgp, j) {
|
||||
+ vector_foreach_slot (pgp->paths, pp, i) {
|
||||
+ if (pp->state == PATH_UP || pp->state == PATH_GHOST) {
|
||||
+ if (first) {
|
||||
+ append_strbuf_str(&buf, pp->dev);
|
||||
+ first = false;
|
||||
+ } else
|
||||
+ print_strbuf(&buf, " %s", pp->dev_t);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ append_strbuf_str(&buf, "\"");
|
||||
+ return do_update_pr(mpp->alias, "setprstatus", get_strbuf_str(&buf));
|
||||
}
|
||||
|
||||
int update_prhold(char *mapname, bool set) {
|
||||
diff --git a/libmpathpersist/mpathpr.h b/libmpathpersist/mpathpr.h
|
||||
index 69f402f2..67d04247 100644
|
||||
--- a/libmpathpersist/mpathpr.h
|
||||
+++ b/libmpathpersist/mpathpr.h
|
||||
@@ -40,7 +40,7 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
|
||||
unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy,
|
||||
bool unregister);
|
||||
|
||||
-int update_prflag(char *mapname, int set);
|
||||
+int update_prflag(struct multipath *mpp, int set);
|
||||
int update_prkey_flags(char *mapname, uint64_t prkey, uint8_t sa_flags);
|
||||
int get_prflag(char *mapname);
|
||||
int get_prhold(char *mapname);
|
||||
diff --git a/multipathd/cli.c b/multipathd/cli.c
|
||||
index d33b571d..9e833b02 100644
|
||||
--- a/multipathd/cli.c
|
||||
+++ b/multipathd/cli.c
|
||||
@@ -226,6 +226,7 @@ load_keys (void)
|
||||
r += add_key(keys, "getprhold", GETPRHOLD, 0);
|
||||
r += add_key(keys, "setprhold", SETPRHOLD, 0);
|
||||
r += add_key(keys, "unsetprhold", UNSETPRHOLD, 0);
|
||||
+ r += add_key(keys, "pathlist", PATHLIST, 1);
|
||||
|
||||
if (r) {
|
||||
free_keys(keys);
|
||||
@@ -572,6 +573,7 @@ cli_init (void) {
|
||||
add_handler(SHUTDOWN, NULL);
|
||||
add_handler(GETPRSTATUS+MAP, NULL);
|
||||
add_handler(SETPRSTATUS+MAP, NULL);
|
||||
+ add_handler(SETPRSTATUS+MAP+PATHLIST, NULL);
|
||||
add_handler(UNSETPRSTATUS+MAP, NULL);
|
||||
add_handler(GETPRKEY+MAP, NULL);
|
||||
add_handler(SETPRKEY+MAP+KEY, NULL);
|
||||
diff --git a/multipathd/cli.h b/multipathd/cli.h
|
||||
index 4d12f8fd..17344cb4 100644
|
||||
--- a/multipathd/cli.h
|
||||
+++ b/multipathd/cli.h
|
||||
@@ -50,6 +50,7 @@ enum {
|
||||
__GETPRHOLD,
|
||||
__SETPRHOLD,
|
||||
__UNSETPRHOLD,
|
||||
+ __PATHLIST,
|
||||
};
|
||||
|
||||
#define LIST (1 << __LIST)
|
||||
@@ -99,6 +100,7 @@ enum {
|
||||
#define GETPRHOLD (1ULL << __GETPRHOLD)
|
||||
#define SETPRHOLD (1ULL << __SETPRHOLD)
|
||||
#define UNSETPRHOLD (1ULL << __UNSETPRHOLD)
|
||||
+#define PATHLIST (1ULL << __PATHLIST)
|
||||
|
||||
#define INITIAL_REPLY_LEN 1200
|
||||
|
||||
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
|
||||
index 0c63ca9a..f183fceb 100644
|
||||
--- a/multipathd/cli_handlers.c
|
||||
+++ b/multipathd/cli_handlers.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "foreign.h"
|
||||
#include "strbuf.h"
|
||||
#include "cli_handlers.h"
|
||||
+#include <ctype.h>
|
||||
|
||||
#define SET_REPLY_AND_LEN(__rep, __len, string_literal) \
|
||||
do { \
|
||||
@@ -1308,8 +1309,8 @@ cli_getprstatus (void * v, char ** reply, int * len, void * data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int
|
||||
-cli_setprstatus(void * v, char ** reply, int * len, void * data)
|
||||
+static int do_setprstatus(void * v, char ** reply, int * len, void * data,
|
||||
+ const struct _vector *registered_paths)
|
||||
{
|
||||
struct multipath * mpp;
|
||||
struct vectors * vecs = (struct vectors *)data;
|
||||
@@ -1324,7 +1325,7 @@ cli_setprstatus(void * v, char ** reply, int * len, void * data)
|
||||
|
||||
if (mpp->prflag != PR_SET) {
|
||||
set_pr(mpp);
|
||||
- pr_register_active_paths(mpp, true);
|
||||
+ pr_register_active_paths(mpp, registered_paths);
|
||||
if (mpp->prflag == PR_SET)
|
||||
condlog(2, "%s: prflag set", param);
|
||||
else
|
||||
@@ -1336,6 +1337,36 @@ cli_setprstatus(void * v, char ** reply, int * len, void * data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int
|
||||
+cli_setprstatus(void * v, char ** reply, int * len, void * data)
|
||||
+{
|
||||
+ return do_setprstatus(v, reply, len, data, NULL);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+cli_setprstatus_list(void * v, char ** reply, int * len, void *data)
|
||||
+{
|
||||
+ int r;
|
||||
+ struct _vector registered_paths_vec = {.allocated = 0};
|
||||
+ vector registered_paths
|
||||
+ __attribute__((cleanup(cleanup_reset_vec))) = ®istered_paths_vec;
|
||||
+ char *ptr = get_keyparam(v, PATHLIST);
|
||||
+
|
||||
+ while (isspace(*ptr))
|
||||
+ ptr++;
|
||||
+ while (*ptr) {
|
||||
+ if (!vector_alloc_slot(registered_paths))
|
||||
+ return -ENOMEM;
|
||||
+ vector_set_slot(registered_paths, ptr);
|
||||
+ while (*ptr && !isspace(*ptr))
|
||||
+ ptr++;
|
||||
+ while (isspace(*ptr))
|
||||
+ *ptr++ = '\0';
|
||||
+ }
|
||||
+ r = do_setprstatus(v, reply, len, data, registered_paths);
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
int
|
||||
cli_unsetprstatus(void * v, char ** reply, int * len, void * data)
|
||||
{
|
||||
diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h
|
||||
index 348c8485..28b6f2bb 100644
|
||||
--- a/multipathd/cli_handlers.h
|
||||
+++ b/multipathd/cli_handlers.h
|
||||
@@ -46,6 +46,7 @@ int cli_shutdown(void * v, char ** reply, int * len, void * data);
|
||||
int cli_reassign (void * v, char ** reply, int * len, void * data);
|
||||
int cli_getprstatus(void * v, char ** reply, int * len, void * data);
|
||||
int cli_setprstatus(void * v, char ** reply, int * len, void * data);
|
||||
+int cli_setprstatus_list(void * v, char ** reply, int * len, void * data);
|
||||
int cli_unsetprstatus(void * v, char ** reply, int * len, void * data);
|
||||
int cli_getprkey(void * v, char ** reply, int * len, void * data);
|
||||
int cli_setprkey(void * v, char ** reply, int * len, void * data);
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 2526d8d1..09d26fe2 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -548,28 +548,47 @@ flush_map_nopaths(struct multipath *mpp, struct vectors *vecs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
-void pr_register_active_paths(struct multipath *mpp, bool check_nr_active)
|
||||
+/*
|
||||
+ * If reg_paths in non-NULL, it is a vector of paths that libmpathpersist
|
||||
+ * registered. If the number of registered keys is smaller than the number
|
||||
+ * of registered paths, then likely a preempt that occurred while
|
||||
+ * libmpathpersist was registering the key. As long as there are still some
|
||||
+ * registered keys, treat the preempt as happening first, and make sure to
|
||||
+ * register keys on all the paths. If the number of registered keys is at
|
||||
+ * least as large as the number of registered paths, then no preempt happened,
|
||||
+ * and multipathd does not need to re-register the paths that libmpathpersist
|
||||
+ * handled
|
||||
+ */
|
||||
+void pr_register_active_paths(struct multipath *mpp, const struct _vector *reg_paths)
|
||||
{
|
||||
- unsigned int i, j, nr_keys = 0;
|
||||
- unsigned int nr_active = 0;
|
||||
+ unsigned int i, j, k, nr_keys = 0;
|
||||
+ unsigned int wanted_nr = VECTOR_SIZE(reg_paths);
|
||||
struct path *pp;
|
||||
struct pathgroup *pgp;
|
||||
-
|
||||
- if (check_nr_active) {
|
||||
- nr_active = count_active_paths(mpp);
|
||||
- if (!nr_active)
|
||||
- return;
|
||||
- }
|
||||
+ char *pathname;
|
||||
|
||||
vector_foreach_slot (mpp->pg, pgp, i) {
|
||||
vector_foreach_slot (pgp->paths, pp, j) {
|
||||
if (mpp->prflag == PR_UNSET)
|
||||
return;
|
||||
- if (pp->state == PATH_UP || pp->state == PATH_GHOST) {
|
||||
- nr_keys = mpath_pr_event_handle(pp, nr_keys, nr_active);
|
||||
- if (check_nr_active && nr_keys == nr_active)
|
||||
- return;
|
||||
+ if (pp->state != PATH_UP && pp->state != PATH_GHOST)
|
||||
+ continue;
|
||||
+ if (wanted_nr && nr_keys) {
|
||||
+ vector_foreach_slot (reg_paths, pathname, k) {
|
||||
+ if (strcmp(pp->dev_t, pathname) == 0) {
|
||||
+ goto skip;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ nr_keys = mpath_pr_event_handle(pp, nr_keys, wanted_nr);
|
||||
+ if (nr_keys && nr_keys < wanted_nr) {
|
||||
+ /*
|
||||
+ * Incorrect number of registered keys. Need
|
||||
+ * to register all devices
|
||||
+ */
|
||||
+ wanted_nr = 0;
|
||||
+ }
|
||||
+ skip:; /* a statement must follow a label on pre C23 clang */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -599,8 +618,7 @@ handle_orphaned_offline_paths(vector offline_paths)
|
||||
pp->add_when_online = true;
|
||||
}
|
||||
|
||||
-static void
|
||||
-cleanup_reset_vec(struct _vector **v)
|
||||
+void cleanup_reset_vec(struct _vector **v)
|
||||
{
|
||||
vector_reset(*v);
|
||||
}
|
||||
@@ -656,7 +674,7 @@ fail:
|
||||
|
||||
sync_map_state(mpp);
|
||||
|
||||
- pr_register_active_paths(mpp, false);
|
||||
+ pr_register_active_paths(mpp, NULL);
|
||||
|
||||
if (VECTOR_SIZE(offline_paths) != 0)
|
||||
handle_orphaned_offline_paths(offline_paths);
|
||||
@@ -1279,7 +1297,7 @@ rescan:
|
||||
|
||||
if (retries >= 0) {
|
||||
if ((mpp->prflag == PR_SET && prflag != PR_SET) || start_waiter)
|
||||
- pr_register_active_paths(mpp, false);
|
||||
+ pr_register_active_paths(mpp, NULL);
|
||||
condlog(2, "%s [%s]: path added to devmap %s",
|
||||
pp->dev, pp->dev_t, mpp->alias);
|
||||
return 0;
|
||||
@@ -1875,6 +1893,7 @@ uxlsnrloop (void * ap)
|
||||
set_unlocked_handler_callback(SHUTDOWN, cli_shutdown);
|
||||
set_handler_callback(GETPRSTATUS|MAP, cli_getprstatus);
|
||||
set_handler_callback(SETPRSTATUS|MAP, cli_setprstatus);
|
||||
+ set_handler_callback(SETPRSTATUS|MAP|PATHLIST, cli_setprstatus_list);
|
||||
set_handler_callback(UNSETPRSTATUS|MAP, cli_unsetprstatus);
|
||||
set_handler_callback(FORCEQ|DAEMON, cli_force_no_daemon_q);
|
||||
set_handler_callback(RESTOREQ|DAEMON, cli_restore_no_daemon_q);
|
||||
@@ -2581,7 +2600,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
mpath_pr_event_handle(pp, 0, 0);
|
||||
if (pp->mpp->prflag == PR_SET &&
|
||||
prflag != PR_SET)
|
||||
- pr_register_active_paths(pp->mpp, false);
|
||||
+ pr_register_active_paths(pp->mpp, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2950,7 +2969,7 @@ configure (struct vectors * vecs)
|
||||
vector_foreach_slot(mpvec, mpp, i){
|
||||
if (remember_wwid(mpp->wwid) == 1)
|
||||
trigger_paths_udev_change(mpp, true);
|
||||
- pr_register_active_paths(mpp, false);
|
||||
+ pr_register_active_paths(mpp, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3933,8 +3952,8 @@ static int update_map_pr(struct multipath *mpp, struct path *pp, unsigned int *n
|
||||
*
|
||||
* nr_keys_wanted: Only used if nr_keys_needed is 0, so we don't know how
|
||||
* many keys we currently have. If nr_keys_wanted in non-zero and the
|
||||
- * number of keys found by the initial call to update_map_pr() matches it,
|
||||
- * exit early, since we have all the keys we are expecting.
|
||||
+ * number of keys found by the initial call to update_map_pr() is at least
|
||||
+ * as large as it, exit early, since we have all the keys we are expecting.
|
||||
*
|
||||
* The function returns the number of keys that are registered or 0 if
|
||||
* it's unknown.
|
||||
@@ -3957,7 +3976,7 @@ mpath_pr_event_handle(struct path *pp, unsigned int nr_keys_needed,
|
||||
nr_keys_needed = 1;
|
||||
if (update_map_pr(mpp, pp, &nr_keys_needed) != MPATH_PR_SUCCESS)
|
||||
return 0;
|
||||
- if (nr_keys_wanted && nr_keys_wanted == nr_keys_needed)
|
||||
+ if (nr_keys_wanted && nr_keys_wanted <= nr_keys_needed)
|
||||
return nr_keys_needed;
|
||||
}
|
||||
|
||||
diff --git a/multipathd/main.h b/multipathd/main.h
|
||||
index 8a4c5f88..ea12455f 100644
|
||||
--- a/multipathd/main.h
|
||||
+++ b/multipathd/main.h
|
||||
@@ -60,5 +60,7 @@ int resize_map(struct multipath *mpp, unsigned long long size,
|
||||
struct vectors *vecs);
|
||||
void set_pr(struct multipath *mpp);
|
||||
void unset_pr(struct multipath *mpp);
|
||||
-void pr_register_active_paths(struct multipath *mpp, bool check_active_nr);
|
||||
+void pr_register_active_paths(struct multipath *mpp,
|
||||
+ const struct _vector *registered_paths);
|
||||
+void cleanup_reset_vec(struct _vector **v);
|
||||
#endif /* MAIN_H */
|
||||
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
|
||||
index 2ed036d4..0a76f3e3 100644
|
||||
--- a/multipathd/multipathd.8
|
||||
+++ b/multipathd/multipathd.8
|
||||
@@ -324,11 +324,17 @@ will not be disabled when the daemon stops.
|
||||
Restores configured queue_without_daemon mode.
|
||||
.
|
||||
.TP
|
||||
-.B map|multipath $map setprstatus
|
||||
+.B setprstatus map|multipath $map
|
||||
Enable persistent reservation management on $map.
|
||||
.
|
||||
.TP
|
||||
-.B map|multipath $map unsetprstatus
|
||||
+.B setprstatus map|multipath $map pathlist $pathlist
|
||||
+Enable persistent reservation management on $map, and notify multipathd of
|
||||
+the paths that have been registered, so it doesn't attempt to re-register
|
||||
+them.
|
||||
+.
|
||||
+.TP
|
||||
+.B unsetprstatus map|multipath $map
|
||||
Disable persistent reservation management on $map.
|
||||
.
|
||||
.TP
|
||||
@ -1,6 +1,6 @@
|
||||
Name: device-mapper-multipath
|
||||
Version: 0.8.7
|
||||
Release: 44%{?dist}
|
||||
Release: 45%{?dist}
|
||||
Summary: Tools to manage multipath devices using device-mapper
|
||||
License: GPLv2
|
||||
URL: http://christophe.varoqui.free.fr/
|
||||
@ -217,6 +217,9 @@ Patch0204: 0204-libmultipath-is_uevent_busy-check-servicing_uev-unde.patch
|
||||
Patch0205: 0205-multipathd-make-multipathd-show-status-busy-checker-.patch
|
||||
Patch0206: 0206-libmultipath-add-purge_disconnected-configuration-op.patch
|
||||
Patch0207: 0207-multipathd-implement-purge-functionality-for-disconn.patch
|
||||
Patch0208: 0208-libmpathpersist-fix-register-retry-status-checking.patch
|
||||
Patch0209: 0209-multipathd-remember-number-of-registered-keys-when-i.patch
|
||||
Patch0210: 0210-libmpathpersist-fix-code-for-skipping-multipathd-pat.patch
|
||||
|
||||
# runtime
|
||||
Requires: %{name}-libs = %{version}-%{release}
|
||||
@ -419,6 +422,14 @@ fi
|
||||
%{_pkgconfdir}/libdmmp.pc
|
||||
|
||||
%changelog
|
||||
* Thu Feb 19 2026 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-45
|
||||
- Add 0208-libmpathpersist-fix-register-retry-status-checking.patch
|
||||
- Add 0209-multipathd-remember-number-of-registered-keys-when-i.patch
|
||||
- Add 0210-libmpathpersist-fix-code-for-skipping-multipathd-pat.patch
|
||||
* Fixes RHEL-148462 ("Improve multipathd's handling of updating
|
||||
persistent reservations on restored paths. [rhel-9]")
|
||||
- Resolves: RHEL-148462
|
||||
|
||||
* Thu Jan 29 2026 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.7-44
|
||||
- Add 0206-libmultipath-add-purge_disconnected-configuration-op.patch
|
||||
- Add 0207-multipathd-implement-purge-functionality-for-disconn.patch
|
||||
|
||||
Loading…
Reference in New Issue
Block a user