import device-mapper-multipath-0.8.4-9.el8
This commit is contained in:
parent
67f1445a6b
commit
e018fe60aa
@ -0,0 +1,322 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Tue, 23 Jun 2020 22:17:31 -0500
|
||||
Subject: [PATCH] libmultipath: make dm_get_map/status return codes symbolic
|
||||
|
||||
dm_get_map() and dm_get_status() now use symbolic return codes. They
|
||||
also differentiate between failing to get information from device-mapper
|
||||
and not finding the requested device. These symboilc return codes are
|
||||
also used by update_multipath_* functions.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/devmapper.c | 51 +++++++++++++++++++++++++-------------
|
||||
libmultipath/devmapper.h | 6 +++++
|
||||
libmultipath/structs_vec.c | 45 +++++++++++++++++++--------------
|
||||
multipathd/main.c | 12 ++++-----
|
||||
4 files changed, 72 insertions(+), 42 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index 13a1cf53..f6204e5f 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -525,36 +525,43 @@ int dm_map_present(const char * str)
|
||||
|
||||
int dm_get_map(const char *name, unsigned long long *size, char *outparams)
|
||||
{
|
||||
- int r = 1;
|
||||
+ int r = DMP_ERR;
|
||||
struct dm_task *dmt;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params = NULL;
|
||||
|
||||
if (!(dmt = libmp_dm_task_create(DM_DEVICE_TABLE)))
|
||||
- return 1;
|
||||
+ return r;
|
||||
|
||||
if (!dm_task_set_name(dmt, name))
|
||||
goto out;
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt))
|
||||
+ errno = 0;
|
||||
+ if (!dm_task_run(dmt)) {
|
||||
+ if (dm_task_get_errno(dmt) == ENXIO)
|
||||
+ r = DMP_NOT_FOUND;
|
||||
goto out;
|
||||
+ }
|
||||
|
||||
+ r = DMP_NOT_FOUND;
|
||||
/* Fetch 1st target */
|
||||
- dm_get_next_target(dmt, NULL, &start, &length,
|
||||
- &target_type, ¶ms);
|
||||
+ if (dm_get_next_target(dmt, NULL, &start, &length,
|
||||
+ &target_type, ¶ms) != NULL)
|
||||
+ /* more than one target */
|
||||
+ goto out;
|
||||
|
||||
if (size)
|
||||
*size = length;
|
||||
|
||||
if (!outparams) {
|
||||
- r = 0;
|
||||
+ r = DMP_OK;
|
||||
goto out;
|
||||
}
|
||||
if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
|
||||
- r = 0;
|
||||
+ r = DMP_OK;
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
@@ -628,35 +635,45 @@ is_mpath_part(const char *part_name, const char *map_name)
|
||||
|
||||
int dm_get_status(const char *name, char *outstatus)
|
||||
{
|
||||
- int r = 1;
|
||||
+ int r = DMP_ERR;
|
||||
struct dm_task *dmt;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *status = NULL;
|
||||
|
||||
if (!(dmt = libmp_dm_task_create(DM_DEVICE_STATUS)))
|
||||
- return 1;
|
||||
+ return r;
|
||||
|
||||
if (!dm_task_set_name(dmt, name))
|
||||
goto out;
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
- if (!dm_task_run(dmt))
|
||||
+ errno = 0;
|
||||
+ if (!dm_task_run(dmt)) {
|
||||
+ if (dm_task_get_errno(dmt) == ENXIO)
|
||||
+ r = DMP_NOT_FOUND;
|
||||
goto out;
|
||||
+ }
|
||||
|
||||
+ r = DMP_NOT_FOUND;
|
||||
/* Fetch 1st target */
|
||||
- dm_get_next_target(dmt, NULL, &start, &length,
|
||||
- &target_type, &status);
|
||||
+ if (dm_get_next_target(dmt, NULL, &start, &length,
|
||||
+ &target_type, &status) != NULL)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (!target_type || strcmp(target_type, TGT_MPATH) != 0)
|
||||
+ goto out;
|
||||
+
|
||||
if (!status) {
|
||||
condlog(2, "get null status.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (snprintf(outstatus, PARAMS_SIZE, "%s", status) <= PARAMS_SIZE)
|
||||
- r = 0;
|
||||
+ r = DMP_OK;
|
||||
out:
|
||||
- if (r)
|
||||
+ if (r != DMP_OK)
|
||||
condlog(0, "%s: error getting map status string", name);
|
||||
|
||||
dm_task_destroy(dmt);
|
||||
@@ -866,7 +883,7 @@ int _dm_flush_map (const char * mapname, int need_sync, int deferred_remove,
|
||||
return 1;
|
||||
|
||||
if (need_suspend &&
|
||||
- !dm_get_map(mapname, &mapsize, params) &&
|
||||
+ dm_get_map(mapname, &mapsize, params) == DMP_OK &&
|
||||
strstr(params, "queue_if_no_path")) {
|
||||
if (!dm_queue_if_no_path(mapname, 0))
|
||||
queue_if_no_path = 1;
|
||||
@@ -1075,7 +1092,7 @@ struct multipath *dm_get_multipath(const char *name)
|
||||
if (!mpp->alias)
|
||||
goto out;
|
||||
|
||||
- if (dm_get_map(name, &mpp->size, NULL))
|
||||
+ if (dm_get_map(name, &mpp->size, NULL) != DMP_OK)
|
||||
goto out;
|
||||
|
||||
dm_get_uuid(name, mpp->wwid, WWID_SIZE);
|
||||
@@ -1259,7 +1276,7 @@ do_foreach_partmaps (const char * mapname,
|
||||
/*
|
||||
* and we can fetch the map table from the kernel
|
||||
*/
|
||||
- !dm_get_map(names->name, &size, ¶ms[0]) &&
|
||||
+ dm_get_map(names->name, &size, ¶ms[0]) == DMP_OK &&
|
||||
|
||||
/*
|
||||
* and the table maps over the multipath map
|
||||
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
|
||||
index 7557a86b..adb55000 100644
|
||||
--- a/libmultipath/devmapper.h
|
||||
+++ b/libmultipath/devmapper.h
|
||||
@@ -27,6 +27,12 @@
|
||||
#define UUID_PREFIX "mpath-"
|
||||
#define UUID_PREFIX_LEN (sizeof(UUID_PREFIX) - 1)
|
||||
|
||||
+enum {
|
||||
+ DMP_ERR,
|
||||
+ DMP_OK,
|
||||
+ DMP_NOT_FOUND,
|
||||
+};
|
||||
+
|
||||
void dm_init(int verbosity);
|
||||
void libmp_dm_init(void);
|
||||
void libmp_udev_set_sync_support(int on);
|
||||
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
||||
index 077f2e42..8137ea21 100644
|
||||
--- a/libmultipath/structs_vec.c
|
||||
+++ b/libmultipath/structs_vec.c
|
||||
@@ -196,43 +196,47 @@ extract_hwe_from_path(struct multipath * mpp)
|
||||
int
|
||||
update_multipath_table (struct multipath *mpp, vector pathvec, int is_daemon)
|
||||
{
|
||||
+ int r = DMP_ERR;
|
||||
char params[PARAMS_SIZE] = {0};
|
||||
|
||||
if (!mpp)
|
||||
- return 1;
|
||||
+ return r;
|
||||
|
||||
- if (dm_get_map(mpp->alias, &mpp->size, params)) {
|
||||
- condlog(3, "%s: cannot get map", mpp->alias);
|
||||
- return 1;
|
||||
+ r = dm_get_map(mpp->alias, &mpp->size, params);
|
||||
+ if (r != DMP_OK) {
|
||||
+ condlog(3, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting table" : "map not present");
|
||||
+ return r;
|
||||
}
|
||||
|
||||
if (disassemble_map(pathvec, params, mpp, is_daemon)) {
|
||||
condlog(3, "%s: cannot disassemble map", mpp->alias);
|
||||
- return 1;
|
||||
+ return DMP_ERR;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return DMP_OK;
|
||||
}
|
||||
|
||||
int
|
||||
update_multipath_status (struct multipath *mpp)
|
||||
{
|
||||
+ int r = DMP_ERR;
|
||||
char status[PARAMS_SIZE] = {0};
|
||||
|
||||
if (!mpp)
|
||||
- return 1;
|
||||
+ return r;
|
||||
|
||||
- if (dm_get_status(mpp->alias, status)) {
|
||||
- condlog(3, "%s: cannot get status", mpp->alias);
|
||||
- return 1;
|
||||
+ r = dm_get_status(mpp->alias, status);
|
||||
+ if (r != DMP_OK) {
|
||||
+ condlog(3, "%s: %s", mpp->alias, (r == DMP_ERR)? "error getting status" : "map not present");
|
||||
+ return r;
|
||||
}
|
||||
|
||||
if (disassemble_status(status, mpp)) {
|
||||
condlog(3, "%s: cannot disassemble status", mpp->alias);
|
||||
- return 1;
|
||||
+ return DMP_ERR;
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return DMP_OK;
|
||||
}
|
||||
|
||||
void sync_paths(struct multipath *mpp, vector pathvec)
|
||||
@@ -264,10 +268,10 @@ int
|
||||
update_multipath_strings(struct multipath *mpp, vector pathvec, int is_daemon)
|
||||
{
|
||||
struct pathgroup *pgp;
|
||||
- int i;
|
||||
+ int i, r = DMP_ERR;
|
||||
|
||||
if (!mpp)
|
||||
- return 1;
|
||||
+ return r;
|
||||
|
||||
update_mpp_paths(mpp, pathvec);
|
||||
condlog(4, "%s: %s", mpp->alias, __FUNCTION__);
|
||||
@@ -276,18 +280,21 @@ update_multipath_strings(struct multipath *mpp, vector pathvec, int is_daemon)
|
||||
free_pgvec(mpp->pg, KEEP_PATHS);
|
||||
mpp->pg = NULL;
|
||||
|
||||
- if (update_multipath_table(mpp, pathvec, is_daemon))
|
||||
- return 1;
|
||||
+ r = update_multipath_table(mpp, pathvec, is_daemon);
|
||||
+ if (r != DMP_OK)
|
||||
+ return r;
|
||||
+
|
||||
sync_paths(mpp, pathvec);
|
||||
|
||||
- if (update_multipath_status(mpp))
|
||||
- return 1;
|
||||
+ r = update_multipath_status(mpp);
|
||||
+ if (r != DMP_OK)
|
||||
+ return r;
|
||||
|
||||
vector_foreach_slot(mpp->pg, pgp, i)
|
||||
if (pgp->paths)
|
||||
path_group_prio_update(pgp);
|
||||
|
||||
- return 0;
|
||||
+ return DMP_OK;
|
||||
}
|
||||
|
||||
static void enter_recovery_mode(struct multipath *mpp)
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 6b7db2c0..e3427d3d 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -414,7 +414,7 @@ int __setup_multipath(struct vectors *vecs, struct multipath *mpp,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (update_multipath_strings(mpp, vecs->pathvec, 1)) {
|
||||
+ if (update_multipath_strings(mpp, vecs->pathvec, 1) != DMP_OK) {
|
||||
condlog(0, "%s: failed to setup multipath", mpp->alias);
|
||||
goto out;
|
||||
}
|
||||
@@ -553,9 +553,9 @@ add_map_without_path (struct vectors *vecs, const char *alias)
|
||||
mpp->mpe = find_mpe(conf->mptable, mpp->wwid);
|
||||
put_multipath_config(conf);
|
||||
|
||||
- if (update_multipath_table(mpp, vecs->pathvec, 1))
|
||||
+ if (update_multipath_table(mpp, vecs->pathvec, 1) != DMP_OK)
|
||||
goto out;
|
||||
- if (update_multipath_status(mpp))
|
||||
+ if (update_multipath_status(mpp) != DMP_OK)
|
||||
goto out;
|
||||
|
||||
if (!vector_alloc_slot(vecs->mpvec))
|
||||
@@ -1346,8 +1346,8 @@ map_discovery (struct vectors * vecs)
|
||||
return 1;
|
||||
|
||||
vector_foreach_slot (vecs->mpvec, mpp, i)
|
||||
- if (update_multipath_table(mpp, vecs->pathvec, 1) ||
|
||||
- update_multipath_status(mpp)) {
|
||||
+ if (update_multipath_table(mpp, vecs->pathvec, 1) != DMP_OK ||
|
||||
+ update_multipath_status(mpp) != DMP_OK) {
|
||||
remove_map(mpp, vecs, 1);
|
||||
i--;
|
||||
}
|
||||
@@ -2087,7 +2087,7 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
/*
|
||||
* Synchronize with kernel state
|
||||
*/
|
||||
- if (update_multipath_strings(pp->mpp, vecs->pathvec, 1)) {
|
||||
+ if (update_multipath_strings(pp->mpp, vecs->pathvec, 1) != DMP_OK) {
|
||||
condlog(1, "%s: Could not synchronize with kernel state",
|
||||
pp->dev);
|
||||
pp->dmstate = PSTATE_UNDEF;
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,116 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 11 Jun 2020 15:41:18 -0500
|
||||
Subject: [PATCH] multipathd: fix check_path errors with removed map
|
||||
|
||||
If a multipath device is removed during, or immediately before the call
|
||||
to check_path(), multipathd can behave incorrectly. A missing multpath
|
||||
device will cause update_multipath_strings() to fail, setting
|
||||
pp->dmstate to PSTATE_UNDEF. If the path is up, this state will cause
|
||||
reinstate_path() to be called, which will also fail. This will trigger
|
||||
a reload, restoring the recently removed device.
|
||||
|
||||
If update_multipath_strings() fails because there is no multipath
|
||||
device, check_path should just quit, since the remove dmevent and uevent
|
||||
are likely already queued up. Also, I don't see any reason to reload the
|
||||
multipath device if reinstate fails. This code was added by
|
||||
fac68d7a99ef17d496079538a5c6836acd7911ab, which clamined that reinstate
|
||||
could fail if the path was disabled. Looking through the current kernel
|
||||
code, I can't see any reason why a reinstate would fail, where a reload
|
||||
would help. If the path was missing from the multipath device,
|
||||
update_multipath_strings() would already catch that, and quit
|
||||
check_path() early, which make more sense to me than reloading does.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/main.c | 44 +++++++++++++++++++-------------------------
|
||||
1 file changed, 19 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index e3427d3d..1d9ce7f7 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -1611,22 +1611,18 @@ fail_path (struct path * pp, int del_active)
|
||||
/*
|
||||
* caller must have locked the path list before calling that function
|
||||
*/
|
||||
-static int
|
||||
+static void
|
||||
reinstate_path (struct path * pp)
|
||||
{
|
||||
- int ret = 0;
|
||||
-
|
||||
if (!pp->mpp)
|
||||
- return 0;
|
||||
+ return;
|
||||
|
||||
- if (dm_reinstate_path(pp->mpp->alias, pp->dev_t)) {
|
||||
+ if (dm_reinstate_path(pp->mpp->alias, pp->dev_t))
|
||||
condlog(0, "%s: reinstate failed", pp->dev_t);
|
||||
- ret = 1;
|
||||
- } else {
|
||||
+ else {
|
||||
condlog(2, "%s: reinstated", pp->dev_t);
|
||||
update_queue_mode_add_path(pp->mpp);
|
||||
}
|
||||
- return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2087,9 +2083,16 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
/*
|
||||
* Synchronize with kernel state
|
||||
*/
|
||||
- if (update_multipath_strings(pp->mpp, vecs->pathvec, 1) != DMP_OK) {
|
||||
- condlog(1, "%s: Could not synchronize with kernel state",
|
||||
- pp->dev);
|
||||
+ ret = update_multipath_strings(pp->mpp, vecs->pathvec, 1);
|
||||
+ if (ret != DMP_OK) {
|
||||
+ if (ret == DMP_NOT_FOUND) {
|
||||
+ /* multipath device missing. Likely removed */
|
||||
+ condlog(1, "%s: multipath device '%s' not found",
|
||||
+ pp->dev, pp->mpp->alias);
|
||||
+ return 0;
|
||||
+ } else
|
||||
+ condlog(1, "%s: Couldn't synchronize with kernel state",
|
||||
+ pp->dev);
|
||||
pp->dmstate = PSTATE_UNDEF;
|
||||
}
|
||||
/* if update_multipath_strings orphaned the path, quit early */
|
||||
@@ -2179,12 +2182,8 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
/*
|
||||
* reinstate this path
|
||||
*/
|
||||
- if (!disable_reinstate && reinstate_path(pp)) {
|
||||
- condlog(3, "%s: reload map", pp->dev);
|
||||
- ev_add_path(pp, vecs, 1);
|
||||
- pp->tick = 1;
|
||||
- return 0;
|
||||
- }
|
||||
+ if (!disable_reinstate)
|
||||
+ reinstate_path(pp);
|
||||
new_path_up = 1;
|
||||
|
||||
if (oldchkrstate != PATH_UP && oldchkrstate != PATH_GHOST)
|
||||
@@ -2200,15 +2199,10 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
else if (newstate == PATH_UP || newstate == PATH_GHOST) {
|
||||
if ((pp->dmstate == PSTATE_FAILED ||
|
||||
pp->dmstate == PSTATE_UNDEF) &&
|
||||
- !disable_reinstate) {
|
||||
+ !disable_reinstate)
|
||||
/* Clear IO errors */
|
||||
- if (reinstate_path(pp)) {
|
||||
- condlog(3, "%s: reload map", pp->dev);
|
||||
- ev_add_path(pp, vecs, 1);
|
||||
- pp->tick = 1;
|
||||
- return 0;
|
||||
- }
|
||||
- } else {
|
||||
+ reinstate_path(pp);
|
||||
+ else {
|
||||
LOG_MSG(4, verbosity, pp);
|
||||
if (pp->checkint != max_checkint) {
|
||||
/*
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Wed, 17 Jun 2020 13:31:37 -0500
|
||||
Subject: [PATCH] libmultipath: make dm_flush_maps only return 0 on success
|
||||
|
||||
dm_flush_maps() returned both 0 and 1 on error, depending on which part
|
||||
of the function it was in, but the caller was always treating 0 as a
|
||||
success. Make dm_flush_maps() always return 1 on error and 0 on success.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/devmapper.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index f6204e5f..cda83ce4 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -953,13 +953,13 @@ dm_flush_map_nopaths(const char * mapname, int deferred_remove)
|
||||
|
||||
int dm_flush_maps (int retries)
|
||||
{
|
||||
- int r = 0;
|
||||
+ int r = 1;
|
||||
struct dm_task *dmt;
|
||||
struct dm_names *names;
|
||||
unsigned next = 0;
|
||||
|
||||
if (!(dmt = libmp_dm_task_create (DM_DEVICE_LIST)))
|
||||
- return 0;
|
||||
+ return r;
|
||||
|
||||
dm_task_no_open_count(dmt);
|
||||
|
||||
@@ -972,6 +972,7 @@ int dm_flush_maps (int retries)
|
||||
if (!names->dev)
|
||||
goto out;
|
||||
|
||||
+ r = 0;
|
||||
do {
|
||||
r |= dm_suspend_and_flush_map(names->name, retries);
|
||||
next = names->next;
|
||||
--
|
||||
2.17.2
|
||||
|
160
SOURCES/0027-multipathd-add-del-maps-multipathd-command.patch
Normal file
160
SOURCES/0027-multipathd-add-del-maps-multipathd-command.patch
Normal file
@ -0,0 +1,160 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 15 Jun 2020 17:00:54 -0500
|
||||
Subject: [PATCH] multipathd: add "del maps" multipathd command
|
||||
|
||||
This will flush all multipath devices.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/devmapper.c | 7 +++++--
|
||||
libmultipath/devmapper.h | 2 +-
|
||||
multipath/main.c | 2 +-
|
||||
multipathd/cli.c | 1 +
|
||||
multipathd/cli_handlers.c | 19 +++++++++++++++++++
|
||||
multipathd/cli_handlers.h | 1 +
|
||||
multipathd/main.c | 3 ++-
|
||||
multipathd/main.h | 1 +
|
||||
8 files changed, 31 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index cda83ce4..7f98bf9d 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -951,7 +951,7 @@ dm_flush_map_nopaths(const char * mapname, int deferred_remove)
|
||||
|
||||
#endif
|
||||
|
||||
-int dm_flush_maps (int retries)
|
||||
+int dm_flush_maps (int need_suspend, int retries)
|
||||
{
|
||||
int r = 1;
|
||||
struct dm_task *dmt;
|
||||
@@ -974,7 +974,10 @@ int dm_flush_maps (int retries)
|
||||
|
||||
r = 0;
|
||||
do {
|
||||
- r |= dm_suspend_and_flush_map(names->name, retries);
|
||||
+ if (need_suspend)
|
||||
+ r |= dm_suspend_and_flush_map(names->name, retries);
|
||||
+ else
|
||||
+ r |= dm_flush_map(names->name);
|
||||
next = names->next;
|
||||
names = (void *) names + next;
|
||||
} while (next);
|
||||
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
|
||||
index adb55000..7e8812ad 100644
|
||||
--- a/libmultipath/devmapper.h
|
||||
+++ b/libmultipath/devmapper.h
|
||||
@@ -55,7 +55,7 @@ int dm_flush_map_nopaths(const char * mapname, int deferred_remove);
|
||||
#define dm_suspend_and_flush_map(mapname, retries) \
|
||||
_dm_flush_map(mapname, 1, 0, 1, retries)
|
||||
int dm_cancel_deferred_remove(struct multipath *mpp);
|
||||
-int dm_flush_maps (int retries);
|
||||
+int dm_flush_maps (int need_suspend, int retries);
|
||||
int dm_fail_path(const char * mapname, char * path);
|
||||
int dm_reinstate_path(const char * mapname, char * path);
|
||||
int dm_queue_if_no_path(const char *mapname, int enable);
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 78822ee1..7ab3102f 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -1127,7 +1127,7 @@ main (int argc, char *argv[])
|
||||
goto out;
|
||||
}
|
||||
else if (conf->remove == FLUSH_ALL) {
|
||||
- r = dm_flush_maps(retries) ? RTVL_FAIL : RTVL_OK;
|
||||
+ r = dm_flush_maps(1, retries) ? RTVL_FAIL : RTVL_OK;
|
||||
goto out;
|
||||
}
|
||||
while ((r = configure(conf, cmd, dev_type, dev)) == RTVL_RETRY)
|
||||
diff --git a/multipathd/cli.c b/multipathd/cli.c
|
||||
index 800c0fbe..bdc9fb10 100644
|
||||
--- a/multipathd/cli.c
|
||||
+++ b/multipathd/cli.c
|
||||
@@ -568,6 +568,7 @@ cli_init (void) {
|
||||
add_handler(DEL+PATH, NULL);
|
||||
add_handler(ADD+MAP, NULL);
|
||||
add_handler(DEL+MAP, NULL);
|
||||
+ add_handler(DEL+MAPS, NULL);
|
||||
add_handler(SWITCH+MAP+GROUP, NULL);
|
||||
add_handler(RECONFIGURE, NULL);
|
||||
add_handler(SUSPEND+MAP, NULL);
|
||||
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
|
||||
index 31c3d9fd..782bb003 100644
|
||||
--- a/multipathd/cli_handlers.c
|
||||
+++ b/multipathd/cli_handlers.c
|
||||
@@ -852,6 +852,25 @@ cli_del_map (void * v, char ** reply, int * len, void * data)
|
||||
return rc;
|
||||
}
|
||||
|
||||
+int
|
||||
+cli_del_maps (void *v, char **reply, int *len, void *data)
|
||||
+{
|
||||
+ struct vectors * vecs = (struct vectors *)data;
|
||||
+ struct multipath *mpp;
|
||||
+ int i, ret = 0;
|
||||
+
|
||||
+ condlog(2, "remove maps (operator)");
|
||||
+ vector_foreach_slot(vecs->mpvec, mpp, i) {
|
||||
+ if (flush_map(mpp, vecs, 0))
|
||||
+ ret++;
|
||||
+ else
|
||||
+ i--;
|
||||
+ }
|
||||
+ /* flush any multipath maps that aren't currently known by multipathd */
|
||||
+ ret |= dm_flush_maps(0, 0);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int
|
||||
cli_reload(void *v, char **reply, int *len, void *data)
|
||||
{
|
||||
diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h
|
||||
index 0f451064..6f57b429 100644
|
||||
--- a/multipathd/cli_handlers.h
|
||||
+++ b/multipathd/cli_handlers.h
|
||||
@@ -26,6 +26,7 @@ int cli_add_path (void * v, char ** reply, int * len, void * data);
|
||||
int cli_del_path (void * v, char ** reply, int * len, void * data);
|
||||
int cli_add_map (void * v, char ** reply, int * len, void * data);
|
||||
int cli_del_map (void * v, char ** reply, int * len, void * data);
|
||||
+int cli_del_maps (void * v, char ** reply, int * len, void * data);
|
||||
int cli_switch_group(void * v, char ** reply, int * len, void * data);
|
||||
int cli_reconfigure(void * v, char ** reply, int * len, void * data);
|
||||
int cli_resize(void * v, char ** reply, int * len, void * data);
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 1d9ce7f7..1d0579e9 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -631,7 +631,7 @@ sync_maps_state(vector mpvec)
|
||||
sync_map_state(mpp);
|
||||
}
|
||||
|
||||
-static int
|
||||
+int
|
||||
flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths)
|
||||
{
|
||||
int r;
|
||||
@@ -1551,6 +1551,7 @@ uxlsnrloop (void * ap)
|
||||
set_handler_callback(DEL+PATH, cli_del_path);
|
||||
set_handler_callback(ADD+MAP, cli_add_map);
|
||||
set_handler_callback(DEL+MAP, cli_del_map);
|
||||
+ set_handler_callback(DEL+MAPS, cli_del_maps);
|
||||
set_handler_callback(SWITCH+MAP+GROUP, cli_switch_group);
|
||||
set_unlocked_handler_callback(RECONFIGURE, cli_reconfigure);
|
||||
set_handler_callback(SUSPEND+MAP, cli_suspend);
|
||||
diff --git a/multipathd/main.h b/multipathd/main.h
|
||||
index 7bb8463f..5dff17e5 100644
|
||||
--- a/multipathd/main.h
|
||||
+++ b/multipathd/main.h
|
||||
@@ -28,6 +28,7 @@ int ev_add_path (struct path *, struct vectors *, int);
|
||||
int ev_remove_path (struct path *, struct vectors *, int);
|
||||
int ev_add_map (char *, const char *, struct vectors *);
|
||||
int ev_remove_map (char *, char *, int, struct vectors *);
|
||||
+int flush_map(struct multipath *, struct vectors *, int);
|
||||
int set_config_state(enum daemon_status);
|
||||
void * mpath_alloc_prin_response(int prin_sa);
|
||||
int prin_do_scsi_ioctl(char *, int rq_servact, struct prin_resp * resp,
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,103 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 15 Jun 2020 23:54:29 -0500
|
||||
Subject: [PATCH] multipath: make flushing maps work like other commands
|
||||
|
||||
The config structure doesn't need a special variable just for removes.
|
||||
Multipath can just use the cmd variable, like it does for the other
|
||||
commands.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.h | 3 ++-
|
||||
libmultipath/configure.h | 3 ---
|
||||
multipath/main.c | 20 ++++++++++----------
|
||||
3 files changed, 12 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index 3368d8c9..4042eba6 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -39,6 +39,8 @@ enum mpath_cmds {
|
||||
CMD_ADD_WWID,
|
||||
CMD_USABLE_PATHS,
|
||||
CMD_DUMP_CONFIG,
|
||||
+ CMD_FLUSH_ONE,
|
||||
+ CMD_FLUSH_ALL,
|
||||
};
|
||||
|
||||
enum force_reload_types {
|
||||
@@ -143,7 +145,6 @@ struct config {
|
||||
unsigned int max_checkint;
|
||||
bool use_watchdog;
|
||||
int pgfailback;
|
||||
- int remove;
|
||||
int rr_weight;
|
||||
int no_path_retry;
|
||||
int user_friendly_names;
|
||||
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
|
||||
index d7509000..0e33bf40 100644
|
||||
--- a/libmultipath/configure.h
|
||||
+++ b/libmultipath/configure.h
|
||||
@@ -45,9 +45,6 @@ enum {
|
||||
CP_RETRY,
|
||||
};
|
||||
|
||||
-#define FLUSH_ONE 1
|
||||
-#define FLUSH_ALL 2
|
||||
-
|
||||
struct vectors;
|
||||
|
||||
int setup_map (struct multipath * mpp, char * params, int params_size,
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 7ab3102f..a2080029 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -942,10 +942,10 @@ main (int argc, char *argv[])
|
||||
cmd = CMD_DRY_RUN;
|
||||
break;
|
||||
case 'f':
|
||||
- conf->remove = FLUSH_ONE;
|
||||
+ cmd = CMD_FLUSH_ONE;
|
||||
break;
|
||||
case 'F':
|
||||
- conf->remove = FLUSH_ALL;
|
||||
+ cmd = CMD_FLUSH_ALL;
|
||||
break;
|
||||
case 'l':
|
||||
if (optarg && !strncmp(optarg, "l", 1))
|
||||
@@ -1084,6 +1084,10 @@ main (int argc, char *argv[])
|
||||
condlog(0, "the -w option requires a device");
|
||||
goto out;
|
||||
}
|
||||
+ if (cmd == CMD_FLUSH_ONE && dev_type != DEV_DEVMAP) {
|
||||
+ condlog(0, "the -f option requires a map name to remove");
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
switch(delegate_to_multipathd(cmd, dev, dev_type, conf)) {
|
||||
case DELEGATE_OK:
|
||||
@@ -1117,16 +1121,12 @@ main (int argc, char *argv[])
|
||||
}
|
||||
if (retries < 0)
|
||||
retries = conf->remove_retries;
|
||||
- if (conf->remove == FLUSH_ONE) {
|
||||
- if (dev_type == DEV_DEVMAP) {
|
||||
- r = dm_suspend_and_flush_map(dev, retries) ?
|
||||
- RTVL_FAIL : RTVL_OK;
|
||||
- } else
|
||||
- condlog(0, "must provide a map name to remove");
|
||||
-
|
||||
+ if (cmd == CMD_FLUSH_ONE) {
|
||||
+ r = dm_suspend_and_flush_map(dev, retries) ?
|
||||
+ RTVL_FAIL : RTVL_OK;
|
||||
goto out;
|
||||
}
|
||||
- else if (conf->remove == FLUSH_ALL) {
|
||||
+ else if (cmd == CMD_FLUSH_ALL) {
|
||||
r = dm_flush_maps(1, retries) ? RTVL_FAIL : RTVL_OK;
|
||||
goto out;
|
||||
}
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Tue, 16 Jun 2020 16:25:34 -0500
|
||||
Subject: [PATCH] multipath: delegate flushing maps to multipathd
|
||||
|
||||
Since there can be problems with removing maps outside of multipathd,
|
||||
multipath should attempt to delegate this command to multipathd.
|
||||
However, multipathd doesn't attempt to suspend the device, in order
|
||||
to avoid potential hangs. If delegating to multipathd fails, multipath
|
||||
should try the remove itself.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipath/main.c | 14 ++++++++++++++
|
||||
multipath/multipath.8 | 4 ++--
|
||||
2 files changed, 16 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index a2080029..612c6815 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -828,6 +828,20 @@ int delegate_to_multipathd(enum mpath_cmds cmd,
|
||||
if (cmd == CMD_CREATE && conf->force_reload == FORCE_RELOAD_YES) {
|
||||
p += snprintf(p, n, "reconfigure");
|
||||
}
|
||||
+ else if (cmd == CMD_FLUSH_ONE && dev && dev_type == DEV_DEVMAP) {
|
||||
+ p += snprintf(p, n, "del map %s", dev);
|
||||
+ /* multipathd doesn't try as hard, to avoid potentially
|
||||
+ * hanging. If it fails, retry with the regular multipath
|
||||
+ * command */
|
||||
+ r = NOT_DELEGATED;
|
||||
+ }
|
||||
+ else if (cmd == CMD_FLUSH_ALL) {
|
||||
+ p += snprintf(p, n, "del maps");
|
||||
+ /* multipathd doesn't try as hard, to avoid potentially
|
||||
+ * hanging. If it fails, retry with the regular multipath
|
||||
+ * command */
|
||||
+ r = NOT_DELEGATED;
|
||||
+ }
|
||||
/* Add other translations here */
|
||||
|
||||
if (strlen(command) == 0)
|
||||
diff --git a/multipath/multipath.8 b/multipath/multipath.8
|
||||
index 8befc45a..47a33f9b 100644
|
||||
--- a/multipath/multipath.8
|
||||
+++ b/multipath/multipath.8
|
||||
@@ -125,11 +125,11 @@ the system.
|
||||
Other operation modes are chosen by using one of the following command line switches:
|
||||
.TP
|
||||
.B \-f
|
||||
-Flush (remove) a multipath device map specified as parameter, if unused.
|
||||
+Flush (remove) a multipath device map specified as parameter, if unused. This operation is delegated to the multipathd daemon if it's running.
|
||||
.
|
||||
.TP
|
||||
.B \-F
|
||||
-Flush (remove) all unused multipath device maps.
|
||||
+Flush (remove) all unused multipath device maps. This operation is delegated to the multipathd daemon if it's running.
|
||||
.
|
||||
.TP
|
||||
.B \-l
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Tue, 16 Jun 2020 17:36:33 -0500
|
||||
Subject: [PATCH] multipath: add option to skip multipathd delegation
|
||||
|
||||
Add the -D option to allow users to skip delegating commands to
|
||||
multipathd.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.h | 1 +
|
||||
multipath/main.c | 8 +++++++-
|
||||
2 files changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index 4042eba6..160867cd 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -191,6 +191,7 @@ struct config {
|
||||
int ghost_delay;
|
||||
int find_multipaths_timeout;
|
||||
int marginal_pathgroups;
|
||||
+ int skip_delegate;
|
||||
unsigned int version[3];
|
||||
unsigned int sequence_nr;
|
||||
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 612c6815..3c3d2398 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -825,6 +825,9 @@ int delegate_to_multipathd(enum mpath_cmds cmd,
|
||||
*p = '\0';
|
||||
n = sizeof(command);
|
||||
|
||||
+ if (conf->skip_delegate)
|
||||
+ return NOT_DELEGATED;
|
||||
+
|
||||
if (cmd == CMD_CREATE && conf->force_reload == FORCE_RELOAD_YES) {
|
||||
p += snprintf(p, n, "reconfigure");
|
||||
}
|
||||
@@ -923,7 +926,7 @@ main (int argc, char *argv[])
|
||||
multipath_conf = conf;
|
||||
conf->retrigger_tries = 0;
|
||||
conf->force_sync = 1;
|
||||
- while ((arg = getopt(argc, argv, ":aAdcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||
+ while ((arg = getopt(argc, argv, ":aAdDcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||
switch(arg) {
|
||||
case 1: printf("optarg : %s\n",optarg);
|
||||
break;
|
||||
@@ -955,6 +958,9 @@ main (int argc, char *argv[])
|
||||
if (cmd == CMD_CREATE)
|
||||
cmd = CMD_DRY_RUN;
|
||||
break;
|
||||
+ case 'D':
|
||||
+ conf->skip_delegate = 1;
|
||||
+ break;
|
||||
case 'f':
|
||||
cmd = CMD_FLUSH_ONE;
|
||||
break;
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 25 Jun 2020 20:46:08 -0500
|
||||
Subject: [PATCH] libmultipath: fix sysfs dev_loss_tmo parsing
|
||||
|
||||
dev_loss_tmo is a u32 value. However the kernel sysfs code prints it as
|
||||
a signed integer. This means that if dev_loss_tmo is above INT_MAX, the
|
||||
sysfs value will be a negative number. Parsing this was causing
|
||||
sysfs_set_rport_tmo() to fail.
|
||||
|
||||
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/discovery.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index ffec5162..83a41a4a 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -583,7 +583,7 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||||
struct udev_device *rport_dev = NULL;
|
||||
char value[16], *eptr;
|
||||
char rport_id[32];
|
||||
- unsigned long long tmo = 0;
|
||||
+ unsigned int tmo;
|
||||
int ret;
|
||||
|
||||
sprintf(rport_id, "rport-%d:%d-%d",
|
||||
@@ -607,8 +607,8 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||||
"error %d", rport_id, -ret);
|
||||
goto out;
|
||||
}
|
||||
- tmo = strtoull(value, &eptr, 0);
|
||||
- if (value == eptr || tmo == ULLONG_MAX) {
|
||||
+ tmo = strtoul(value, &eptr, 0);
|
||||
+ if (value == eptr) {
|
||||
condlog(0, "%s: Cannot parse dev_loss_tmo "
|
||||
"attribute '%s'", rport_id, value);
|
||||
goto out;
|
||||
--
|
||||
2.17.2
|
||||
|
267
SOURCES/0032-kpartx-read-devices-with-direct-IO.patch
Normal file
267
SOURCES/0032-kpartx-read-devices-with-direct-IO.patch
Normal file
@ -0,0 +1,267 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Fri, 26 Jun 2020 20:06:24 -0500
|
||||
Subject: [PATCH] kpartx: read devices with direct IO
|
||||
|
||||
If kpartx is used on top of shared storage, and a device has its
|
||||
partition table changed on one machine, and then kpartx is run on
|
||||
another, it may not see the new data, because the cache still contains
|
||||
the old data, and there is nothing to tell the machine running kpartx to
|
||||
invalidate it. To solve this, kpartx should read the devices using
|
||||
direct io.
|
||||
|
||||
One issue with how this code has been updated is that the original code
|
||||
for getblock() always read 1024 bytes. The new code reads a logical
|
||||
sector size chunk of the device, and returns a pointer to the 512 byte
|
||||
sector that the caller asked for, within that (possibly larger) chunk.
|
||||
This means that if the logical sector size is 512, then the code is now
|
||||
only reading 512 bytes. Looking through the code for the various
|
||||
partition types, I can't see a case where more than 512 bytes is needed
|
||||
and getblock() is used. If anyone has a reason why this code should be
|
||||
reading 1024 bytes at minmum, I can certainly change this. But when I
|
||||
looked, I couldn't find a case where reading 512 bytes would cause a
|
||||
problem.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
kpartx/dasd.c | 7 ++++---
|
||||
kpartx/gpt.c | 22 +++++++++----------
|
||||
kpartx/kpartx.c | 56 +++++++++++++++++++++++++++++++++++++++----------
|
||||
kpartx/kpartx.h | 2 ++
|
||||
4 files changed, 61 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/kpartx/dasd.c b/kpartx/dasd.c
|
||||
index 14b9d3aa..f0398645 100644
|
||||
--- a/kpartx/dasd.c
|
||||
+++ b/kpartx/dasd.c
|
||||
@@ -22,6 +22,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
+#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -117,13 +118,13 @@ read_dasd_pt(int fd, __attribute__((unused)) struct slice all,
|
||||
|
||||
sprintf(pathname, "/dev/.kpartx-node-%u-%u",
|
||||
(unsigned int)major(dev), (unsigned int)minor(dev));
|
||||
- if ((fd_dasd = open(pathname, O_RDONLY)) == -1) {
|
||||
+ if ((fd_dasd = open(pathname, O_RDONLY | O_DIRECT)) == -1) {
|
||||
/* Devicenode does not exist. Try to create one */
|
||||
if (mknod(pathname, 0600 | S_IFBLK, dev) == -1) {
|
||||
/* Couldn't create a device node */
|
||||
return -1;
|
||||
}
|
||||
- fd_dasd = open(pathname, O_RDONLY);
|
||||
+ fd_dasd = open(pathname, O_RDONLY | O_DIRECT);
|
||||
/*
|
||||
* The file will vanish when the last process (we)
|
||||
* has ceased to access it.
|
||||
@@ -175,7 +176,7 @@ read_dasd_pt(int fd, __attribute__((unused)) struct slice all,
|
||||
* Get volume label, extract name and type.
|
||||
*/
|
||||
|
||||
- if (!(data = (unsigned char *)malloc(blocksize)))
|
||||
+ if (aligned_malloc((void **)&data, blocksize, NULL))
|
||||
goto out;
|
||||
|
||||
|
||||
diff --git a/kpartx/gpt.c b/kpartx/gpt.c
|
||||
index 785b34ea..f7fefb70 100644
|
||||
--- a/kpartx/gpt.c
|
||||
+++ b/kpartx/gpt.c
|
||||
@@ -243,8 +243,7 @@ alloc_read_gpt_entries(int fd, gpt_header * gpt)
|
||||
|
||||
if (!count) return NULL;
|
||||
|
||||
- pte = (gpt_entry *)malloc(count);
|
||||
- if (!pte)
|
||||
+ if (aligned_malloc((void **)&pte, get_sector_size(fd), &count))
|
||||
return NULL;
|
||||
memset(pte, 0, count);
|
||||
|
||||
@@ -269,12 +268,11 @@ static gpt_header *
|
||||
alloc_read_gpt_header(int fd, uint64_t lba)
|
||||
{
|
||||
gpt_header *gpt;
|
||||
- gpt = (gpt_header *)
|
||||
- malloc(sizeof (gpt_header));
|
||||
- if (!gpt)
|
||||
+ size_t size = sizeof (gpt_header);
|
||||
+ if (aligned_malloc((void **)&gpt, get_sector_size(fd), &size))
|
||||
return NULL;
|
||||
- memset(gpt, 0, sizeof (*gpt));
|
||||
- if (!read_lba(fd, lba, gpt, sizeof (gpt_header))) {
|
||||
+ memset(gpt, 0, size);
|
||||
+ if (!read_lba(fd, lba, gpt, size)) {
|
||||
free(gpt);
|
||||
return NULL;
|
||||
}
|
||||
@@ -498,6 +496,7 @@ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
|
||||
gpt_header *pgpt = NULL, *agpt = NULL;
|
||||
gpt_entry *pptes = NULL, *aptes = NULL;
|
||||
legacy_mbr *legacymbr = NULL;
|
||||
+ size_t size = sizeof(legacy_mbr);
|
||||
uint64_t lastlba;
|
||||
if (!gpt || !ptes)
|
||||
return 0;
|
||||
@@ -526,11 +525,10 @@ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
|
||||
}
|
||||
|
||||
/* This will be added to the EFI Spec. per Intel after v1.02. */
|
||||
- legacymbr = malloc(sizeof (*legacymbr));
|
||||
- if (legacymbr) {
|
||||
- memset(legacymbr, 0, sizeof (*legacymbr));
|
||||
- read_lba(fd, 0, (uint8_t *) legacymbr,
|
||||
- sizeof (*legacymbr));
|
||||
+ if (aligned_malloc((void **)&legacymbr, get_sector_size(fd),
|
||||
+ &size) == 0) {
|
||||
+ memset(legacymbr, 0, size);
|
||||
+ read_lba(fd, 0, (uint8_t *) legacymbr, size);
|
||||
good_pmbr = is_pmbr_valid(legacymbr);
|
||||
free(legacymbr);
|
||||
legacymbr=NULL;
|
||||
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
|
||||
index d3620c5c..c24ad6d9 100644
|
||||
--- a/kpartx/kpartx.c
|
||||
+++ b/kpartx/kpartx.c
|
||||
@@ -19,6 +19,7 @@
|
||||
* cva, 2002-10-26
|
||||
*/
|
||||
|
||||
+#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
@@ -41,7 +42,6 @@
|
||||
|
||||
#define SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
||||
|
||||
-#define READ_SIZE 1024
|
||||
#define MAXTYPES 64
|
||||
#define MAXSLICES 256
|
||||
#define DM_TARGET "linear"
|
||||
@@ -388,7 +388,7 @@ main(int argc, char **argv){
|
||||
set_delimiter(mapname, delim);
|
||||
}
|
||||
|
||||
- fd = open(device, O_RDONLY);
|
||||
+ fd = open(device, O_RDONLY | O_DIRECT);
|
||||
|
||||
if (fd == -1) {
|
||||
perror(device);
|
||||
@@ -690,9 +690,9 @@ xmalloc (size_t size) {
|
||||
*/
|
||||
|
||||
static int
|
||||
-sseek(int fd, unsigned int secnr) {
|
||||
+sseek(int fd, unsigned int secnr, int secsz) {
|
||||
off64_t in, out;
|
||||
- in = ((off64_t) secnr << 9);
|
||||
+ in = ((off64_t) secnr * secsz);
|
||||
out = 1;
|
||||
|
||||
if ((out = lseek64(fd, in, SEEK_SET)) != in)
|
||||
@@ -703,6 +703,31 @@ sseek(int fd, unsigned int secnr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int
|
||||
+aligned_malloc(void **mem_p, size_t align, size_t *size_p)
|
||||
+{
|
||||
+ static size_t pgsize = 0;
|
||||
+ size_t size;
|
||||
+ int err;
|
||||
+
|
||||
+ if (!mem_p || !align || (size_p && !*size_p))
|
||||
+ return EINVAL;
|
||||
+
|
||||
+ if (!pgsize)
|
||||
+ pgsize = getpagesize();
|
||||
+
|
||||
+ if (size_p)
|
||||
+ size = ((*size_p + align - 1) / align) * align;
|
||||
+ else
|
||||
+ size = pgsize;
|
||||
+
|
||||
+ err = posix_memalign(mem_p, pgsize, size);
|
||||
+ if (!err && size_p)
|
||||
+ *size_p = size;
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/* always in sector size blocks */
|
||||
static
|
||||
struct block {
|
||||
unsigned int secnr;
|
||||
@@ -710,30 +735,39 @@ struct block {
|
||||
struct block *next;
|
||||
} *blockhead;
|
||||
|
||||
+/* blknr is always in 512 byte blocks */
|
||||
char *
|
||||
-getblock (int fd, unsigned int secnr) {
|
||||
+getblock (int fd, unsigned int blknr) {
|
||||
+ unsigned int secsz = get_sector_size(fd);
|
||||
+ unsigned int blks_per_sec = secsz / 512;
|
||||
+ unsigned int secnr = blknr / blks_per_sec;
|
||||
+ unsigned int blk_off = (blknr % blks_per_sec) * 512;
|
||||
struct block *bp;
|
||||
|
||||
for (bp = blockhead; bp; bp = bp->next)
|
||||
|
||||
if (bp->secnr == secnr)
|
||||
- return bp->block;
|
||||
+ return bp->block + blk_off;
|
||||
|
||||
- if (sseek(fd, secnr))
|
||||
+ if (sseek(fd, secnr, secsz))
|
||||
return NULL;
|
||||
|
||||
bp = xmalloc(sizeof(struct block));
|
||||
bp->secnr = secnr;
|
||||
bp->next = blockhead;
|
||||
blockhead = bp;
|
||||
- bp->block = (char *) xmalloc(READ_SIZE);
|
||||
+ if (aligned_malloc((void **)&bp->block, secsz, NULL)) {
|
||||
+ fprintf(stderr, "aligned_malloc failed\n");
|
||||
+ exit(1);
|
||||
+ }
|
||||
|
||||
- if (read(fd, bp->block, READ_SIZE) != READ_SIZE) {
|
||||
+ if (read(fd, bp->block, secsz) != secsz) {
|
||||
fprintf(stderr, "read error, sector %d\n", secnr);
|
||||
- bp->block = NULL;
|
||||
+ blockhead = bp->next;
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
- return bp->block;
|
||||
+ return bp->block + blk_off;
|
||||
}
|
||||
|
||||
int
|
||||
diff --git a/kpartx/kpartx.h b/kpartx/kpartx.h
|
||||
index 67edeb82..727632c1 100644
|
||||
--- a/kpartx/kpartx.h
|
||||
+++ b/kpartx/kpartx.h
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef _KPARTX_H
|
||||
#define _KPARTX_H
|
||||
|
||||
+#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
@@ -61,6 +62,7 @@ extern ptreader read_mac_pt;
|
||||
extern ptreader read_sun_pt;
|
||||
extern ptreader read_ps3_pt;
|
||||
|
||||
+int aligned_malloc(void **mem_p, size_t align, size_t *size_p);
|
||||
char *getblock(int fd, unsigned int secnr);
|
||||
|
||||
static inline unsigned int
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Tue, 30 Jun 2020 10:49:59 -0500
|
||||
Subject: [PATCH] kpartx: handle alternate bsd disklabel location
|
||||
|
||||
bsd disk labels can either be at the start of the second sector, or 64
|
||||
bytes into the first sector, but kpartx only handled the first case.
|
||||
However the second case is what parted creates, and what the linux
|
||||
kernel partition code expects. kpartx should handle both cases.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
kpartx/bsd.c | 16 ++++++++++++++--
|
||||
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/kpartx/bsd.c b/kpartx/bsd.c
|
||||
index 0e661fbc..950b0f92 100644
|
||||
--- a/kpartx/bsd.c
|
||||
+++ b/kpartx/bsd.c
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "kpartx.h"
|
||||
#include <stdio.h>
|
||||
|
||||
+#define BSD_LABEL_OFFSET 64
|
||||
#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
|
||||
#define XBSD_MAXPARTITIONS 16
|
||||
#define BSD_FS_UNUSED 0
|
||||
@@ -60,8 +61,19 @@ read_bsd_pt(int fd, struct slice all, struct slice *sp, unsigned int ns) {
|
||||
return -1;
|
||||
|
||||
l = (struct bsd_disklabel *) bp;
|
||||
- if (l->d_magic != BSD_DISKMAGIC)
|
||||
- return -1;
|
||||
+ if (l->d_magic != BSD_DISKMAGIC) {
|
||||
+ /*
|
||||
+ * BSD disklabels can also start 64 bytes offset from the
|
||||
+ * start of the first sector
|
||||
+ */
|
||||
+ bp = getblock(fd, offset);
|
||||
+ if (bp == NULL)
|
||||
+ return -1;
|
||||
+
|
||||
+ l = (struct bsd_disklabel *)(bp + 64);
|
||||
+ if (l->d_magic != BSD_DISKMAGIC)
|
||||
+ return -1;
|
||||
+ }
|
||||
|
||||
max_partitions = 16;
|
||||
if (l->d_npartitions < max_partitions)
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,61 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Tue, 30 Jun 2020 13:59:13 -0500
|
||||
Subject: [PATCH] libmultipath: fix checker detection for nvme devices
|
||||
|
||||
In order to fix hwhandler autodetection, commit 8794a776 made
|
||||
detect_alua() differentiate between failures to detect whether alua was
|
||||
supported, and successfully detecting that it was not supported.
|
||||
However, this causes nvme devices to get the TUR checker assigned to
|
||||
them. This is because there is nothing in detect_alua() to make it only
|
||||
work on scsi devices, and select_checker wasn't updated to handle
|
||||
detect_alua() failing without setting pp->tpgs to TPGS_NONE.
|
||||
|
||||
detect_alua() should automatically set pp->tpgs to TPGS_NONE and exit on
|
||||
non-scsi devices. Also, select_checker() should not assume that a
|
||||
devices is ALUA, simply because if failed to detect if alua was
|
||||
supported.
|
||||
|
||||
Fixes: 8794a776 "libmultipath: fix ALUA autodetection when paths are
|
||||
down"
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/discovery.c | 6 ++++++
|
||||
libmultipath/propsel.c | 4 +++-
|
||||
2 files changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index 83a41a4a..aa5942c3 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -887,6 +887,12 @@ detect_alua(struct path * pp)
|
||||
int tpgs;
|
||||
unsigned int timeout;
|
||||
|
||||
+
|
||||
+ if (pp->bus != SYSFS_BUS_SCSI) {
|
||||
+ pp->tpgs = TPGS_NONE;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (sysfs_get_timeout(pp, &timeout) <= 0)
|
||||
timeout = DEF_TIMEOUT;
|
||||
|
||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||
index 897e48ca..d362beb4 100644
|
||||
--- a/libmultipath/propsel.c
|
||||
+++ b/libmultipath/propsel.c
|
||||
@@ -521,7 +521,9 @@ int select_checker(struct config *conf, struct path *pp)
|
||||
if (check_rdac(pp)) {
|
||||
ckr_name = RDAC;
|
||||
goto out;
|
||||
- } else if (path_get_tpgs(pp) != TPGS_NONE) {
|
||||
+ }
|
||||
+ path_get_tpgs(pp);
|
||||
+ if (pp->tpgs != TPGS_NONE && pp->tpgs != TPGS_UNDEF) {
|
||||
ckr_name = TUR;
|
||||
goto out;
|
||||
}
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 6 Jul 2020 13:21:12 -0500
|
||||
Subject: [PATCH] Makefile.inc: trim extra information from systemd version
|
||||
|
||||
Some systemd versions print extra information in the
|
||||
"pkg-config --modversion" output, which confuses make. Trim this
|
||||
off.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
Makefile.inc | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Makefile.inc b/Makefile.inc
|
||||
index c2abd301..220009e0 100644
|
||||
--- a/Makefile.inc
|
||||
+++ b/Makefile.inc
|
||||
@@ -37,7 +37,7 @@ endif
|
||||
|
||||
ifndef SYSTEMD
|
||||
ifeq ($(shell pkg-config --modversion libsystemd >/dev/null 2>&1 && echo 1), 1)
|
||||
- SYSTEMD = $(shell pkg-config --modversion libsystemd)
|
||||
+ SYSTEMD = $(shell pkg-config --modversion libsystemd | awk '{print $$1}')
|
||||
else
|
||||
ifeq ($(shell systemctl --version >/dev/null 2>&1 && echo 1), 1)
|
||||
SYSTEMD = $(shell systemctl --version 2> /dev/null | \
|
||||
--
|
||||
2.17.2
|
||||
|
26
SOURCES/0036-kpartx-fix-Wsign-compare-error.patch
Normal file
26
SOURCES/0036-kpartx-fix-Wsign-compare-error.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 6 Jul 2020 17:28:46 -0500
|
||||
Subject: [PATCH] kpartx: fix -Wsign-compare error
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
kpartx/kpartx.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
|
||||
index c24ad6d9..653ce0c8 100644
|
||||
--- a/kpartx/kpartx.c
|
||||
+++ b/kpartx/kpartx.c
|
||||
@@ -738,7 +738,7 @@ struct block {
|
||||
/* blknr is always in 512 byte blocks */
|
||||
char *
|
||||
getblock (int fd, unsigned int blknr) {
|
||||
- unsigned int secsz = get_sector_size(fd);
|
||||
+ int secsz = get_sector_size(fd);
|
||||
unsigned int blks_per_sec = secsz / 512;
|
||||
unsigned int secnr = blknr / blks_per_sec;
|
||||
unsigned int blk_off = (blknr % blks_per_sec) * 512;
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,86 @@
|
||||
From 7159242be31dbb3f25aa67920462107bc2bc5fe0 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 9 Jul 2020 18:20:18 -0500
|
||||
Subject: [PATCH] libmultipath: count pending paths as active on loads
|
||||
|
||||
When multipath loads a table, it signals to udev if there are no active
|
||||
paths. Multipath wasn't counting pending paths as active. This meant
|
||||
that if all the paths were pending, udev would treat the device as not
|
||||
ready, and not run kpartx on it. Even if the pending paths later
|
||||
because active and were reinstated, the kernel would not send a new
|
||||
uevent, because from its point of view, they were always up.
|
||||
|
||||
The alternative would be to continue to treat them as failed in the udev
|
||||
rules, but then also tell the kernel that they were down, so that it
|
||||
would trigger a uevent when they were reinstated. However, this could
|
||||
lead to newly created multipath devices failing IO, simply because the
|
||||
path checkers hadn't returned yet. Having udev assume that the the
|
||||
device is up, like the kernel does, seems like the safer option.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/devmapper.c | 3 ++-
|
||||
libmultipath/structs.c | 20 ++++++++++++++++++++
|
||||
libmultipath/structs.h | 1 +
|
||||
3 files changed, 23 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index 7f98bf9d..91ff0b3d 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -408,7 +408,8 @@ static uint16_t build_udev_flags(const struct multipath *mpp, int reload)
|
||||
/* DM_UDEV_DISABLE_LIBRARY_FALLBACK is added in dm_addmap */
|
||||
return (mpp->skip_kpartx == SKIP_KPARTX_ON ?
|
||||
MPATH_UDEV_NO_KPARTX_FLAG : 0) |
|
||||
- ((count_active_paths(mpp) == 0 || mpp->ghost_delay_tick > 0) ?
|
||||
+ ((count_active_pending_paths(mpp) == 0 ||
|
||||
+ mpp->ghost_delay_tick > 0) ?
|
||||
MPATH_UDEV_NO_PATHS_FLAG : 0) |
|
||||
(reload && !mpp->force_udev_reload ?
|
||||
MPATH_UDEV_RELOAD_FLAG : 0);
|
||||
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
|
||||
index 2dd378c4..dda9884c 100644
|
||||
--- a/libmultipath/structs.c
|
||||
+++ b/libmultipath/structs.c
|
||||
@@ -500,6 +500,26 @@ int count_active_paths(const struct multipath *mpp)
|
||||
return count;
|
||||
}
|
||||
|
||||
+int count_active_pending_paths(const struct multipath *mpp)
|
||||
+{
|
||||
+ struct pathgroup *pgp;
|
||||
+ struct path *pp;
|
||||
+ int count = 0;
|
||||
+ int i, j;
|
||||
+
|
||||
+ if (!mpp->pg)
|
||||
+ return 0;
|
||||
+
|
||||
+ vector_foreach_slot (mpp->pg, pgp, i) {
|
||||
+ vector_foreach_slot (pgp->paths, pp, j) {
|
||||
+ if (pp->state == PATH_UP || pp->state == PATH_GHOST ||
|
||||
+ pp->state == PATH_PENDING)
|
||||
+ count++;
|
||||
+ }
|
||||
+ }
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
int pathcmp(const struct pathgroup *pgp, const struct pathgroup *cpgp)
|
||||
{
|
||||
int i, j;
|
||||
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||
index 9bd39eb1..8e78b8c0 100644
|
||||
--- a/libmultipath/structs.h
|
||||
+++ b/libmultipath/structs.h
|
||||
@@ -465,6 +465,7 @@ struct path * first_path (const struct multipath *mpp);
|
||||
int pathcountgr (const struct pathgroup *, int);
|
||||
int pathcount (const struct multipath *, int);
|
||||
int count_active_paths(const struct multipath *);
|
||||
+int count_active_pending_paths(const struct multipath *);
|
||||
int pathcmp (const struct pathgroup *, const struct pathgroup *);
|
||||
int add_feature (char **, const char *);
|
||||
int remove_feature (char **, const char *);
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 13 Jul 2020 15:41:15 -0500
|
||||
Subject: [PATCH] multipath: deal with failures flushing maps
|
||||
|
||||
dm_flush_maps() was failing if there were no device-mapper devices at
|
||||
all, instead of returning success, since there is nothing to do.
|
||||
|
||||
delegate_to_multipathd() was returning success, even if the multipathd
|
||||
command failed. Also, if the command was set to fail with NOT_DELEGATED,
|
||||
it shouldn't print any errors, since multipath will try to issue to
|
||||
command itself.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/devmapper.c | 2 +-
|
||||
multipath/main.c | 9 ++++++---
|
||||
2 files changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||
index 91ff0b3d..3f70e576 100644
|
||||
--- a/libmultipath/devmapper.c
|
||||
+++ b/libmultipath/devmapper.c
|
||||
@@ -970,10 +970,10 @@ int dm_flush_maps (int need_suspend, int retries)
|
||||
if (!(names = dm_task_get_names (dmt)))
|
||||
goto out;
|
||||
|
||||
+ r = 0;
|
||||
if (!names->dev)
|
||||
goto out;
|
||||
|
||||
- r = 0;
|
||||
do {
|
||||
if (need_suspend)
|
||||
r |= dm_suspend_and_flush_map(names->name, retries);
|
||||
diff --git a/multipath/main.c b/multipath/main.c
|
||||
index 3c3d2398..607cada2 100644
|
||||
--- a/multipath/main.c
|
||||
+++ b/multipath/main.c
|
||||
@@ -869,9 +869,12 @@ int delegate_to_multipathd(enum mpath_cmds cmd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (reply != NULL && *reply != '\0' && strcmp(reply, "ok\n"))
|
||||
- printf("%s", reply);
|
||||
- r = DELEGATE_OK;
|
||||
+ if (reply != NULL && *reply != '\0') {
|
||||
+ if (strcmp(reply, "fail\n"))
|
||||
+ r = DELEGATE_OK;
|
||||
+ if (r != NOT_DELEGATED && strcmp(reply, "ok\n"))
|
||||
+ printf("%s", reply);
|
||||
+ }
|
||||
|
||||
out:
|
||||
FREE(reply);
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Tue, 3 Nov 2020 14:27:58 -0600
|
||||
Subject: [PATCH] libmultipath: factor out code to get vpd page data
|
||||
|
||||
A future patch will reuse the code to get the vpd page data, so factor
|
||||
it out from get_vpd_sgio().
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/discovery.c | 19 +++++++++++++++----
|
||||
1 file changed, 15 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index aa5942c3..eb1e735d 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -1239,11 +1239,10 @@ get_vpd_sysfs (struct udev_device *parent, int pg, char * str, int maxlen)
|
||||
return len;
|
||||
}
|
||||
|
||||
-int
|
||||
-get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||
+static int
|
||||
+fetch_vpd_page(int fd, int pg, unsigned char *buff)
|
||||
{
|
||||
- int len, buff_len;
|
||||
- unsigned char buff[4096];
|
||||
+ int buff_len;
|
||||
|
||||
memset(buff, 0x0, 4096);
|
||||
if (sgio_get_vpd(buff, 4096, fd, pg) < 0) {
|
||||
@@ -1264,6 +1263,18 @@ get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||
condlog(3, "vpd pg%02x page truncated", pg);
|
||||
buff_len = 4096;
|
||||
}
|
||||
+ return buff_len;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||
+{
|
||||
+ int len, buff_len;
|
||||
+ unsigned char buff[4096];
|
||||
+
|
||||
+ buff_len = fetch_vpd_page(fd, pg, buff);
|
||||
+ if (buff_len < 0)
|
||||
+ return buff_len;
|
||||
if (pg == 0x80)
|
||||
len = parse_vpd_pg80(buff, str, maxlen);
|
||||
else if (pg == 0x83)
|
||||
--
|
||||
2.17.2
|
||||
|
98
SOURCES/0040-libmultipath-limit-reading-0xc9-vpd-page.patch
Normal file
98
SOURCES/0040-libmultipath-limit-reading-0xc9-vpd-page.patch
Normal file
@ -0,0 +1,98 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Wed, 7 Oct 2020 21:43:02 -0500
|
||||
Subject: [PATCH] libmultipath: limit reading 0xc9 vpd page
|
||||
|
||||
Only rdac arrays support 0xC9 vpd page inquiries. All other arrays will
|
||||
return a failure. Only do the rdac inquiry when detecting array
|
||||
capabilities if the array's path checker is explicitly set to rdac, or
|
||||
the path checker is not set, and the array reports that it supports vpd
|
||||
page 0xC9 in the Supported VPD Pages (0x00) vpd page.
|
||||
|
||||
Multipath was doing the check if either the path checker was set to
|
||||
rdac, or no path checker was set. This means that for almost all
|
||||
non-rdac arrays, multipath was issuing a bad inquiry. This was annoying
|
||||
users.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/discovery.c | 25 +++++++++++++++++++++++++
|
||||
libmultipath/discovery.h | 1 +
|
||||
libmultipath/propsel.c | 10 ++++++----
|
||||
3 files changed, 32 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index eb1e735d..01aadba9 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -1266,6 +1266,31 @@ fetch_vpd_page(int fd, int pg, unsigned char *buff)
|
||||
return buff_len;
|
||||
}
|
||||
|
||||
+/* heavily based on sg_inq.c from sg3_utils */
|
||||
+bool
|
||||
+is_vpd_page_supported(int fd, int pg)
|
||||
+{
|
||||
+ int i, len, buff_len;
|
||||
+ unsigned char buff[4096];
|
||||
+
|
||||
+ buff_len = fetch_vpd_page(fd, 0x00, buff);
|
||||
+ if (buff_len < 0)
|
||||
+ return false;
|
||||
+ if (buff_len < 4) {
|
||||
+ condlog(3, "VPD page 00h too short");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ len = buff[3] + 4;
|
||||
+ if (len > buff_len)
|
||||
+ condlog(3, "vpd page 00h trucated, expected %d, have %d",
|
||||
+ len, buff_len);
|
||||
+ for (i = 4; i < len; ++i)
|
||||
+ if (buff[i] == pg)
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
int
|
||||
get_vpd_sgio (int fd, int pg, int vend_id, char * str, int maxlen)
|
||||
{
|
||||
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
|
||||
index 6444887d..d3193daf 100644
|
||||
--- a/libmultipath/discovery.h
|
||||
+++ b/libmultipath/discovery.h
|
||||
@@ -56,6 +56,7 @@ int sysfs_get_asymmetric_access_state(struct path *pp,
|
||||
char *buff, int buflen);
|
||||
int get_uid(struct path * pp, int path_state, struct udev_device *udev,
|
||||
int allow_fallback);
|
||||
+bool is_vpd_page_supported(int fd, int pg);
|
||||
|
||||
/*
|
||||
* discovery bitmask
|
||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||
index d362beb4..d7febec6 100644
|
||||
--- a/libmultipath/propsel.c
|
||||
+++ b/libmultipath/propsel.c
|
||||
@@ -496,13 +496,15 @@ check_rdac(struct path * pp)
|
||||
{
|
||||
int len;
|
||||
char buff[44];
|
||||
- const char *checker_name;
|
||||
+ const char *checker_name = NULL;
|
||||
|
||||
if (pp->bus != SYSFS_BUS_SCSI)
|
||||
return 0;
|
||||
- /* Avoid ioctl if this is likely not an RDAC array */
|
||||
- if (__do_set_from_hwe(checker_name, pp, checker_name) &&
|
||||
- strcmp(checker_name, RDAC))
|
||||
+ /* Avoid checking 0xc9 if this is likely not an RDAC array */
|
||||
+ if (!__do_set_from_hwe(checker_name, pp, checker_name) &&
|
||||
+ !is_vpd_page_supported(pp->fd, 0xC9))
|
||||
+ return 0;
|
||||
+ if (checker_name && strcmp(checker_name, RDAC))
|
||||
return 0;
|
||||
len = get_vpd_sgio(pp->fd, 0xC9, 0, buff, 44);
|
||||
if (len <= 0)
|
||||
--
|
||||
2.17.2
|
||||
|
44
SOURCES/0041-libmultipath-add-device-to-hwtable.c.patch
Normal file
44
SOURCES/0041-libmultipath-add-device-to-hwtable.c.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Schremmer <steve.schremmer@netapp.com>
|
||||
Date: Mon, 6 Jul 2020 20:22:35 +0000
|
||||
Subject: [PATCH] libmultipath: add device to hwtable.c
|
||||
|
||||
Add FUJITSU ETERNUS_AHB defaults.
|
||||
|
||||
Signed-off-by: Steve Schremmer <steve.schremmer@netapp.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/hwtable.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
|
||||
index d1fcfdb3..d680bdfc 100644
|
||||
--- a/libmultipath/hwtable.c
|
||||
+++ b/libmultipath/hwtable.c
|
||||
@@ -428,6 +428,22 @@ static struct hwentry default_hw[] = {
|
||||
.pgpolicy = MULTIBUS,
|
||||
.no_path_retry = 10,
|
||||
},
|
||||
+ {
|
||||
+ /*
|
||||
+ * ETERNUS AB/HB
|
||||
+ * Maintainer: NetApp RDAC team <ng-eseries-upstream-maintainers@netapp.com>
|
||||
+ */
|
||||
+ .vendor = "FUJITSU",
|
||||
+ .product = "ETERNUS_AHB",
|
||||
+ .bl_product = "Universal Xport",
|
||||
+ .pgpolicy = GROUP_BY_PRIO,
|
||||
+ .checker_name = RDAC,
|
||||
+ .features = "2 pg_init_retries 50",
|
||||
+ .hwhandler = "1 rdac",
|
||||
+ .prio_name = PRIO_RDAC,
|
||||
+ .pgfailback = -FAILBACK_IMMEDIATE,
|
||||
+ .no_path_retry = 30,
|
||||
+ },
|
||||
/*
|
||||
* Hitachi Vantara
|
||||
*
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,159 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 12 Oct 2020 16:06:11 -0500
|
||||
Subject: [PATCH] libmultipath: move fast_io_fail defines to structs.h
|
||||
|
||||
Since fast_io_fail is part of the multipath struct, its symbolic values
|
||||
belong in structs.h. Also, make it an instance of a general enum, which
|
||||
will be used again in future patches, and change the set/print functions
|
||||
which use it to use the general enum instead.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.h | 8 --------
|
||||
libmultipath/dict.c | 30 +++++++++++++++---------------
|
||||
libmultipath/dict.h | 2 +-
|
||||
libmultipath/propsel.c | 2 +-
|
||||
libmultipath/structs.h | 17 +++++++++++++++++
|
||||
5 files changed, 34 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index 160867cd..f38c7639 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -11,14 +11,6 @@
|
||||
#define ORIGIN_CONFIG 1
|
||||
#define ORIGIN_NO_CONFIG 2
|
||||
|
||||
-/*
|
||||
- * In kernel, fast_io_fail == 0 means immediate failure on rport delete.
|
||||
- * OTOH '0' means not-configured in various places in multipath-tools.
|
||||
- */
|
||||
-#define MP_FAST_IO_FAIL_UNSET (0)
|
||||
-#define MP_FAST_IO_FAIL_OFF (-1)
|
||||
-#define MP_FAST_IO_FAIL_ZERO (-2)
|
||||
-
|
||||
enum devtypes {
|
||||
DEV_NONE,
|
||||
DEV_DEVT,
|
||||
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||
index 184d4b22..ce8e1cda 100644
|
||||
--- a/libmultipath/dict.c
|
||||
+++ b/libmultipath/dict.c
|
||||
@@ -834,7 +834,7 @@ declare_mp_attr_handler(gid, set_gid)
|
||||
declare_mp_attr_snprint(gid, print_gid)
|
||||
|
||||
static int
|
||||
-set_fast_io_fail(vector strvec, void *ptr)
|
||||
+set_undef_off_zero(vector strvec, void *ptr)
|
||||
{
|
||||
char * buff;
|
||||
int *int_ptr = (int *)ptr;
|
||||
@@ -844,36 +844,36 @@ set_fast_io_fail(vector strvec, void *ptr)
|
||||
return 1;
|
||||
|
||||
if (strcmp(buff, "off") == 0)
|
||||
- *int_ptr = MP_FAST_IO_FAIL_OFF;
|
||||
+ *int_ptr = UOZ_OFF;
|
||||
else if (sscanf(buff, "%d", int_ptr) != 1 ||
|
||||
- *int_ptr < MP_FAST_IO_FAIL_ZERO)
|
||||
- *int_ptr = MP_FAST_IO_FAIL_UNSET;
|
||||
+ *int_ptr < UOZ_ZERO)
|
||||
+ *int_ptr = UOZ_UNDEF;
|
||||
else if (*int_ptr == 0)
|
||||
- *int_ptr = MP_FAST_IO_FAIL_ZERO;
|
||||
+ *int_ptr = UOZ_ZERO;
|
||||
|
||||
FREE(buff);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
-print_fast_io_fail(char * buff, int len, long v)
|
||||
+print_undef_off_zero(char * buff, int len, long v)
|
||||
{
|
||||
- if (v == MP_FAST_IO_FAIL_UNSET)
|
||||
+ if (v == UOZ_UNDEF)
|
||||
return 0;
|
||||
- if (v == MP_FAST_IO_FAIL_OFF)
|
||||
+ if (v == UOZ_OFF)
|
||||
return snprintf(buff, len, "\"off\"");
|
||||
- if (v == MP_FAST_IO_FAIL_ZERO)
|
||||
+ if (v == UOZ_ZERO)
|
||||
return snprintf(buff, len, "0");
|
||||
return snprintf(buff, len, "%ld", v);
|
||||
}
|
||||
|
||||
-declare_def_handler(fast_io_fail, set_fast_io_fail)
|
||||
-declare_def_snprint_defint(fast_io_fail, print_fast_io_fail,
|
||||
+declare_def_handler(fast_io_fail, set_undef_off_zero)
|
||||
+declare_def_snprint_defint(fast_io_fail, print_undef_off_zero,
|
||||
DEFAULT_FAST_IO_FAIL)
|
||||
-declare_ovr_handler(fast_io_fail, set_fast_io_fail)
|
||||
-declare_ovr_snprint(fast_io_fail, print_fast_io_fail)
|
||||
-declare_hw_handler(fast_io_fail, set_fast_io_fail)
|
||||
-declare_hw_snprint(fast_io_fail, print_fast_io_fail)
|
||||
+declare_ovr_handler(fast_io_fail, set_undef_off_zero)
|
||||
+declare_ovr_snprint(fast_io_fail, print_undef_off_zero)
|
||||
+declare_hw_handler(fast_io_fail, set_undef_off_zero)
|
||||
+declare_hw_snprint(fast_io_fail, print_undef_off_zero)
|
||||
|
||||
static int
|
||||
set_dev_loss(vector strvec, void *ptr)
|
||||
diff --git a/libmultipath/dict.h b/libmultipath/dict.h
|
||||
index a40ac66f..a917e1ca 100644
|
||||
--- a/libmultipath/dict.h
|
||||
+++ b/libmultipath/dict.h
|
||||
@@ -13,7 +13,7 @@ int print_rr_weight(char *buff, int len, long v);
|
||||
int print_pgfailback(char *buff, int len, long v);
|
||||
int print_pgpolicy(char *buff, int len, long v);
|
||||
int print_no_path_retry(char *buff, int len, long v);
|
||||
-int print_fast_io_fail(char *buff, int len, long v);
|
||||
+int print_undef_off_zero(char *buff, int len, long v);
|
||||
int print_dev_loss(char *buff, int len, unsigned long v);
|
||||
int print_reservation_key(char * buff, int len, struct be64 key, uint8_t
|
||||
flags, int source);
|
||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||
index d7febec6..725db2b1 100644
|
||||
--- a/libmultipath/propsel.c
|
||||
+++ b/libmultipath/propsel.c
|
||||
@@ -755,7 +755,7 @@ int select_fast_io_fail(struct config *conf, struct multipath *mp)
|
||||
mp_set_conf(fast_io_fail);
|
||||
mp_set_default(fast_io_fail, DEFAULT_FAST_IO_FAIL);
|
||||
out:
|
||||
- print_fast_io_fail(buff, 12, mp->fast_io_fail);
|
||||
+ print_undef_off_zero(buff, 12, mp->fast_io_fail);
|
||||
condlog(3, "%s: fast_io_fail_tmo = %s %s", mp->alias, buff, origin);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||
index 8e78b8c0..29209984 100644
|
||||
--- a/libmultipath/structs.h
|
||||
+++ b/libmultipath/structs.h
|
||||
@@ -229,6 +229,23 @@ enum vpd_vendor_ids {
|
||||
VPD_VP_ARRAY_SIZE, /* This must remain the last entry */
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * Multipath treats 0 as undefined for optional config parameters.
|
||||
+ * Use this for cases where 0 is a valid option for systems multipath
|
||||
+ * is communicating with
|
||||
+ */
|
||||
+enum undefined_off_zero {
|
||||
+ UOZ_UNDEF = 0,
|
||||
+ UOZ_OFF = -1,
|
||||
+ UOZ_ZERO = -2,
|
||||
+};
|
||||
+
|
||||
+enum fast_io_fail_states {
|
||||
+ MP_FAST_IO_FAIL_UNSET = UOZ_UNDEF,
|
||||
+ MP_FAST_IO_FAIL_OFF = UOZ_OFF,
|
||||
+ MP_FAST_IO_FAIL_ZERO = UOZ_ZERO,
|
||||
+};
|
||||
+
|
||||
struct vpd_vendor_page {
|
||||
int pg;
|
||||
const char *name;
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,295 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Wed, 14 Oct 2020 18:38:20 -0500
|
||||
Subject: [PATCH] libmultipath: add eh_deadline multipath.conf parameter
|
||||
|
||||
There are times a fc rport is never lost, meaning that fast_io_fail_tmo
|
||||
and dev_loss_tmo never trigger, but scsi commands still hang. This can
|
||||
cause problems in cases where users have string timing requirements, and
|
||||
the easiest way to solve these issues is to set eh_deadline. Since it's
|
||||
already possible to set fast_io_fail_tmo and dev_loss_tmo from
|
||||
multipath.conf, and have multipath take care of setting it correctly for
|
||||
the scsi devices in sysfs, it makes sense to allow users to set
|
||||
eh_deadline here as well.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.c | 2 ++
|
||||
libmultipath/config.h | 2 ++
|
||||
libmultipath/configure.c | 1 +
|
||||
libmultipath/dict.c | 10 +++++++
|
||||
libmultipath/discovery.c | 58 +++++++++++++++++++++++++++++++++-----
|
||||
libmultipath/propsel.c | 17 +++++++++++
|
||||
libmultipath/propsel.h | 1 +
|
||||
libmultipath/structs.h | 7 +++++
|
||||
multipath/multipath.conf.5 | 16 +++++++++++
|
||||
9 files changed, 107 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index 26f8e050..a71db2d0 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -359,6 +359,7 @@ merge_hwe (struct hwentry * dst, struct hwentry * src)
|
||||
merge_num(flush_on_last_del);
|
||||
merge_num(fast_io_fail);
|
||||
merge_num(dev_loss);
|
||||
+ merge_num(eh_deadline);
|
||||
merge_num(user_friendly_names);
|
||||
merge_num(retain_hwhandler);
|
||||
merge_num(detect_prio);
|
||||
@@ -514,6 +515,7 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
|
||||
hwe->flush_on_last_del = dhwe->flush_on_last_del;
|
||||
hwe->fast_io_fail = dhwe->fast_io_fail;
|
||||
hwe->dev_loss = dhwe->dev_loss;
|
||||
+ hwe->eh_deadline = dhwe->eh_deadline;
|
||||
hwe->user_friendly_names = dhwe->user_friendly_names;
|
||||
hwe->retain_hwhandler = dhwe->retain_hwhandler;
|
||||
hwe->detect_prio = dhwe->detect_prio;
|
||||
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||
index f38c7639..a22c1b4e 100644
|
||||
--- a/libmultipath/config.h
|
||||
+++ b/libmultipath/config.h
|
||||
@@ -64,6 +64,7 @@ struct hwentry {
|
||||
int flush_on_last_del;
|
||||
int fast_io_fail;
|
||||
unsigned int dev_loss;
|
||||
+ int eh_deadline;
|
||||
int user_friendly_names;
|
||||
int retain_hwhandler;
|
||||
int detect_prio;
|
||||
@@ -149,6 +150,7 @@ struct config {
|
||||
int attribute_flags;
|
||||
int fast_io_fail;
|
||||
unsigned int dev_loss;
|
||||
+ int eh_deadline;
|
||||
int log_checker_err;
|
||||
int allow_queueing;
|
||||
int find_multipaths;
|
||||
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||
index 96c79610..b7113291 100644
|
||||
--- a/libmultipath/configure.c
|
||||
+++ b/libmultipath/configure.c
|
||||
@@ -340,6 +340,7 @@ int setup_map(struct multipath *mpp, char *params, int params_size,
|
||||
select_gid(conf, mpp);
|
||||
select_fast_io_fail(conf, mpp);
|
||||
select_dev_loss(conf, mpp);
|
||||
+ select_eh_deadline(conf, mpp);
|
||||
select_reservation_key(conf, mpp);
|
||||
select_deferred_remove(conf, mpp);
|
||||
select_marginal_path_err_sample_time(conf, mpp);
|
||||
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||
index ce8e1cda..8fd91d8c 100644
|
||||
--- a/libmultipath/dict.c
|
||||
+++ b/libmultipath/dict.c
|
||||
@@ -911,6 +911,13 @@ declare_ovr_snprint(dev_loss, print_dev_loss)
|
||||
declare_hw_handler(dev_loss, set_dev_loss)
|
||||
declare_hw_snprint(dev_loss, print_dev_loss)
|
||||
|
||||
+declare_def_handler(eh_deadline, set_undef_off_zero)
|
||||
+declare_def_snprint(eh_deadline, print_undef_off_zero)
|
||||
+declare_ovr_handler(eh_deadline, set_undef_off_zero)
|
||||
+declare_ovr_snprint(eh_deadline, print_undef_off_zero)
|
||||
+declare_hw_handler(eh_deadline, set_undef_off_zero)
|
||||
+declare_hw_snprint(eh_deadline, print_undef_off_zero)
|
||||
+
|
||||
static int
|
||||
set_pgpolicy(vector strvec, void *ptr)
|
||||
{
|
||||
@@ -1776,6 +1783,7 @@ init_keywords(vector keywords)
|
||||
install_keyword("gid", &def_gid_handler, &snprint_def_gid);
|
||||
install_keyword("fast_io_fail_tmo", &def_fast_io_fail_handler, &snprint_def_fast_io_fail);
|
||||
install_keyword("dev_loss_tmo", &def_dev_loss_handler, &snprint_def_dev_loss);
|
||||
+ install_keyword("eh_deadline", &def_eh_deadline_handler, &snprint_def_eh_deadline);
|
||||
install_keyword("bindings_file", &def_bindings_file_handler, &snprint_def_bindings_file);
|
||||
install_keyword("wwids_file", &def_wwids_file_handler, &snprint_def_wwids_file);
|
||||
install_keyword("prkeys_file", &def_prkeys_file_handler, &snprint_def_prkeys_file);
|
||||
@@ -1885,6 +1893,7 @@ init_keywords(vector keywords)
|
||||
install_keyword("flush_on_last_del", &hw_flush_on_last_del_handler, &snprint_hw_flush_on_last_del);
|
||||
install_keyword("fast_io_fail_tmo", &hw_fast_io_fail_handler, &snprint_hw_fast_io_fail);
|
||||
install_keyword("dev_loss_tmo", &hw_dev_loss_handler, &snprint_hw_dev_loss);
|
||||
+ install_keyword("eh_deadline", &hw_eh_deadline_handler, &snprint_hw_eh_deadline);
|
||||
install_keyword("user_friendly_names", &hw_user_friendly_names_handler, &snprint_hw_user_friendly_names);
|
||||
install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler);
|
||||
install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_hw_detect_prio);
|
||||
@@ -1925,6 +1934,7 @@ init_keywords(vector keywords)
|
||||
install_keyword("flush_on_last_del", &ovr_flush_on_last_del_handler, &snprint_ovr_flush_on_last_del);
|
||||
install_keyword("fast_io_fail_tmo", &ovr_fast_io_fail_handler, &snprint_ovr_fast_io_fail);
|
||||
install_keyword("dev_loss_tmo", &ovr_dev_loss_handler, &snprint_ovr_dev_loss);
|
||||
+ install_keyword("eh_deadline", &ovr_eh_deadline_handler, &snprint_ovr_eh_deadline);
|
||||
install_keyword("user_friendly_names", &ovr_user_friendly_names_handler, &snprint_ovr_user_friendly_names);
|
||||
install_keyword("retain_attached_hw_handler", &ovr_retain_hwhandler_handler, &snprint_ovr_retain_hwhandler);
|
||||
install_keyword("detect_prio", &ovr_detect_prio_handler, &snprint_ovr_detect_prio);
|
||||
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||
index 01aadba9..a328aafa 100644
|
||||
--- a/libmultipath/discovery.c
|
||||
+++ b/libmultipath/discovery.c
|
||||
@@ -577,6 +577,42 @@ sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen)
|
||||
return !!preferred;
|
||||
}
|
||||
|
||||
+static int
|
||||
+sysfs_set_eh_deadline(struct multipath *mpp, struct path *pp)
|
||||
+{
|
||||
+ struct udev_device *hostdev;
|
||||
+ char host_name[HOST_NAME_LEN], value[16];
|
||||
+ int ret;
|
||||
+
|
||||
+ if (mpp->eh_deadline == EH_DEADLINE_UNSET)
|
||||
+ return 0;
|
||||
+
|
||||
+ sprintf(host_name, "host%d", pp->sg_id.host_no);
|
||||
+ hostdev = udev_device_new_from_subsystem_sysname(udev,
|
||||
+ "scsi_host", host_name);
|
||||
+ if (!hostdev)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (mpp->eh_deadline == EH_DEADLINE_OFF)
|
||||
+ sprintf(value, "off");
|
||||
+ else if (mpp->eh_deadline == EH_DEADLINE_ZERO)
|
||||
+ sprintf(value, "0");
|
||||
+ else
|
||||
+ snprintf(value, 16, "%u", mpp->eh_deadline);
|
||||
+
|
||||
+ ret = sysfs_attr_set_value(hostdev, "eh_deadline",
|
||||
+ value, strlen(value));
|
||||
+ /*
|
||||
+ * not all scsi drivers support setting eh_deadline, so failing
|
||||
+ * is totally reasonable
|
||||
+ */
|
||||
+ if (ret <= 0)
|
||||
+ condlog(4, "%s: failed to set eh_deadline to %s, error %d", udev_device_get_sysname(hostdev), value, -ret);
|
||||
+
|
||||
+ udev_device_unref(hostdev);
|
||||
+ return (ret <= 0);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||||
{
|
||||
@@ -787,16 +823,24 @@ sysfs_set_scsi_tmo (struct multipath *mpp, unsigned int checkint)
|
||||
mpp->alias, mpp->fast_io_fail);
|
||||
mpp->fast_io_fail = MP_FAST_IO_FAIL_OFF;
|
||||
}
|
||||
- if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)
|
||||
+ if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET &&
|
||||
+ mpp->eh_deadline == EH_DEADLINE_UNSET)
|
||||
return 0;
|
||||
|
||||
vector_foreach_slot(mpp->paths, pp, i) {
|
||||
- if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP)
|
||||
- sysfs_set_rport_tmo(mpp, pp);
|
||||
- if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
|
||||
- sysfs_set_session_tmo(mpp, pp);
|
||||
- if (pp->sg_id.proto_id == SCSI_PROTOCOL_SAS)
|
||||
- sysfs_set_nexus_loss_tmo(mpp, pp);
|
||||
+ if (pp->bus != SYSFS_BUS_SCSI)
|
||||
+ continue;
|
||||
+
|
||||
+ if (mpp->dev_loss ||
|
||||
+ mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
|
||||
+ if (pp->sg_id.proto_id == SCSI_PROTOCOL_FCP)
|
||||
+ sysfs_set_rport_tmo(mpp, pp);
|
||||
+ else if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI)
|
||||
+ sysfs_set_session_tmo(mpp, pp);
|
||||
+ else if (pp->sg_id.proto_id == SCSI_PROTOCOL_SAS)
|
||||
+ sysfs_set_nexus_loss_tmo(mpp, pp);
|
||||
+ }
|
||||
+ sysfs_set_eh_deadline(mpp, pp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||
index 725db2b1..1150cfe8 100644
|
||||
--- a/libmultipath/propsel.c
|
||||
+++ b/libmultipath/propsel.c
|
||||
@@ -776,6 +776,23 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int select_eh_deadline(struct config *conf, struct multipath *mp)
|
||||
+{
|
||||
+ const char *origin;
|
||||
+ char buff[12];
|
||||
+
|
||||
+ mp_set_ovr(eh_deadline);
|
||||
+ mp_set_hwe(eh_deadline);
|
||||
+ mp_set_conf(eh_deadline);
|
||||
+ mp->eh_deadline = EH_DEADLINE_UNSET;
|
||||
+ /* not changing sysfs in default cause, so don't print anything */
|
||||
+ return 0;
|
||||
+out:
|
||||
+ print_undef_off_zero(buff, 12, mp->eh_deadline);
|
||||
+ condlog(3, "%s: eh_deadline = %s %s", mp->alias, buff, origin);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int select_flush_on_last_del(struct config *conf, struct multipath *mp)
|
||||
{
|
||||
const char *origin;
|
||||
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
|
||||
index 3d6edd8a..a68bacf0 100644
|
||||
--- a/libmultipath/propsel.h
|
||||
+++ b/libmultipath/propsel.h
|
||||
@@ -17,6 +17,7 @@ int select_uid(struct config *conf, struct multipath *mp);
|
||||
int select_gid(struct config *conf, struct multipath *mp);
|
||||
int select_fast_io_fail(struct config *conf, struct multipath *mp);
|
||||
int select_dev_loss(struct config *conf, struct multipath *mp);
|
||||
+int select_eh_deadline(struct config *conf, struct multipath *mp);
|
||||
int select_reservation_key(struct config *conf, struct multipath *mp);
|
||||
int select_retain_hwhandler (struct config *conf, struct multipath * mp);
|
||||
int select_detect_prio(struct config *conf, struct path * pp);
|
||||
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||
index 29209984..65542dea 100644
|
||||
--- a/libmultipath/structs.h
|
||||
+++ b/libmultipath/structs.h
|
||||
@@ -246,6 +246,12 @@ enum fast_io_fail_states {
|
||||
MP_FAST_IO_FAIL_ZERO = UOZ_ZERO,
|
||||
};
|
||||
|
||||
+enum eh_deadline_states {
|
||||
+ EH_DEADLINE_UNSET = UOZ_UNDEF,
|
||||
+ EH_DEADLINE_OFF = UOZ_OFF,
|
||||
+ EH_DEADLINE_ZERO = UOZ_ZERO,
|
||||
+};
|
||||
+
|
||||
struct vpd_vendor_page {
|
||||
int pg;
|
||||
const char *name;
|
||||
@@ -366,6 +372,7 @@ struct multipath {
|
||||
int ghost_delay;
|
||||
int ghost_delay_tick;
|
||||
unsigned int dev_loss;
|
||||
+ int eh_deadline;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
mode_t mode;
|
||||
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||
index 6dc26f10..60954574 100644
|
||||
--- a/multipath/multipath.conf.5
|
||||
+++ b/multipath/multipath.conf.5
|
||||
@@ -700,6 +700,22 @@ The default is: \fB600\fR
|
||||
.
|
||||
.
|
||||
.TP
|
||||
+.B eh_deadline
|
||||
+Specify the maximum number of seconds the SCSI layer will spend doing error
|
||||
+handling when scsi devices fail. After this timeout the scsi layer will perform
|
||||
+a full HBA reset. Setting this may be necessary in cases where the rport is
|
||||
+never lost, so \fIfast_io_fail_tmo\fR and \fIdev_loss_tmo\fR will never
|
||||
+trigger, but (frequently do to load) scsi commands still hang. \fBNote:\fR when
|
||||
+the scsi error handler performs the HBA reset, all target paths on that HBA
|
||||
+will be affected. eh_deadline should only be set in cases where all targets on
|
||||
+the affected HBAs are multipathed.
|
||||
+.RS
|
||||
+.TP
|
||||
+The default is: \fB<unset>\fR
|
||||
+.RE
|
||||
+.
|
||||
+.
|
||||
+.TP
|
||||
.B bindings_file
|
||||
The full pathname of the binding file to be used when the user_friendly_names
|
||||
option is set.
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,89 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Fri, 23 Oct 2020 11:38:24 -0500
|
||||
Subject: [PATCH] libmultipath: don't dlclose tur checker DSO
|
||||
|
||||
The multipathd tur checker thread is designed to be able to finish at
|
||||
any time, even after the tur checker itself has been freed. The
|
||||
multipathd shutdown code makes sure all the checkers have been freed
|
||||
before freeing the checker_class and calling dlclose() to unload the
|
||||
DSO, but this doesn't guarantee that the checker threads have finished.
|
||||
If one hasn't, the DSO will get unloaded while the thread still running
|
||||
code from it, causing a segfault. Unfortunately, it's not possible to be
|
||||
sure that all tur checker threads have ended during shutdown, without
|
||||
making them joinable.
|
||||
|
||||
However, since libmultipath will never be reinitialized after it has
|
||||
been uninitialzed, not dlclosing the tur checker DSO once a thread is
|
||||
started has minimal cost (keeping the DSO code around until the program
|
||||
exits, which usually happens right after freeing the checkers).
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/checkers.c | 10 +++++++++-
|
||||
libmultipath/checkers.h | 1 +
|
||||
libmultipath/checkers/tur.c | 1 +
|
||||
3 files changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
|
||||
index 8d2be8a9..6359e5d8 100644
|
||||
--- a/libmultipath/checkers.c
|
||||
+++ b/libmultipath/checkers.c
|
||||
@@ -21,6 +21,7 @@ struct checker_class {
|
||||
void (*reset)(void); /* to reset the global variables */
|
||||
const char **msgtable;
|
||||
short msgtable_size;
|
||||
+ int keep_dso;
|
||||
};
|
||||
|
||||
char *checker_state_names[] = {
|
||||
@@ -69,7 +70,7 @@ void free_checker_class(struct checker_class *c)
|
||||
list_del(&c->node);
|
||||
if (c->reset)
|
||||
c->reset();
|
||||
- if (c->handle) {
|
||||
+ if (c->handle && !c->keep_dso) {
|
||||
if (dlclose(c->handle) != 0) {
|
||||
condlog(0, "Cannot unload checker %s: %s",
|
||||
c->name, dlerror());
|
||||
@@ -192,6 +193,13 @@ out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+void checker_keep_dso(struct checker * c)
|
||||
+{
|
||||
+ if (!c || !c->cls)
|
||||
+ return;
|
||||
+ c->cls->keep_dso = 1;
|
||||
+}
|
||||
+
|
||||
void checker_set_fd (struct checker * c, int fd)
|
||||
{
|
||||
if (!c)
|
||||
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
|
||||
index b458118d..f183cff9 100644
|
||||
--- a/libmultipath/checkers.h
|
||||
+++ b/libmultipath/checkers.h
|
||||
@@ -145,6 +145,7 @@ void checker_reset (struct checker *);
|
||||
void checker_set_sync (struct checker *);
|
||||
void checker_set_async (struct checker *);
|
||||
void checker_set_fd (struct checker *, int);
|
||||
+void checker_keep_dso(struct checker *c);
|
||||
void checker_enable (struct checker *);
|
||||
void checker_disable (struct checker *);
|
||||
int checker_check (struct checker *, int);
|
||||
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
|
||||
index e886fcf8..fd58d62a 100644
|
||||
--- a/libmultipath/checkers/tur.c
|
||||
+++ b/libmultipath/checkers/tur.c
|
||||
@@ -394,6 +394,7 @@ int libcheck_check(struct checker * c)
|
||||
uatomic_set(&ct->running, 1);
|
||||
tur_set_async_timeout(c);
|
||||
setup_thread_attr(&attr, 32 * 1024, 1);
|
||||
+ checker_keep_dso(c);
|
||||
r = pthread_create(&ct->thread, &attr, tur_thread, ct);
|
||||
pthread_attr_destroy(&attr);
|
||||
if (r) {
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 16 Nov 2020 13:52:09 -0600
|
||||
Subject: [PATCH] libmultipath: warn about missing braces at end of
|
||||
multipath.conf
|
||||
|
||||
Multipath doesn't warn when multipath.conf is missing closing braces at
|
||||
the end of the file. This has confused people about the correct config
|
||||
file syntax, so add a warning.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/parser.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||
index a7285a35..48b54e87 100644
|
||||
--- a/libmultipath/parser.c
|
||||
+++ b/libmultipath/parser.c
|
||||
@@ -544,7 +544,7 @@ process_stream(struct config *conf, FILE *stream, vector keywords, char *file)
|
||||
if (!strcmp(str, EOB)) {
|
||||
if (kw_level > 0) {
|
||||
free_strvec(strvec);
|
||||
- break;
|
||||
+ goto out;
|
||||
}
|
||||
condlog(0, "unmatched '%s' at line %d of %s",
|
||||
EOB, line_nr, file);
|
||||
@@ -583,7 +583,8 @@ process_stream(struct config *conf, FILE *stream, vector keywords, char *file)
|
||||
|
||||
free_strvec(strvec);
|
||||
}
|
||||
-
|
||||
+ if (kw_level == 1)
|
||||
+ condlog(1, "missing '%s' at end of %s", EOB, file);
|
||||
out:
|
||||
FREE(buf);
|
||||
free_uniques(uniques);
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 16 Nov 2020 16:38:21 -0600
|
||||
Subject: [PATCH] libmultipath: ignore multipaths sections without wwid option
|
||||
|
||||
"multipathd show config local" was crashing in find_mp_by_wwid() if
|
||||
the multipath configuration included a multipaths section that did
|
||||
not set a wwid option. There is no reason to keep a mpentry that
|
||||
didn't set its wwid. Remove it in merge_mptable().
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index a71db2d0..dc81c994 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -444,6 +444,13 @@ void merge_mptable(vector mptable)
|
||||
int i, j;
|
||||
|
||||
vector_foreach_slot(mptable, mp1, i) {
|
||||
+ /* drop invalid multipath configs */
|
||||
+ if (!mp1->wwid) {
|
||||
+ condlog(0, "multipaths config section missing wwid");
|
||||
+ vector_del_slot(mptable, i--);
|
||||
+ free_mpe(mp1);
|
||||
+ continue;
|
||||
+ }
|
||||
j = i + 1;
|
||||
vector_foreach_slot_after(mptable, mp2, j) {
|
||||
if (strcmp(mp1->wwid, mp2->wwid))
|
||||
--
|
||||
2.17.2
|
||||
|
25
SOURCES/0047-tests-fix-missing-priority-blacklist-test.patch
Normal file
25
SOURCES/0047-tests-fix-missing-priority-blacklist-test.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 16 Nov 2020 23:21:41 -0600
|
||||
Subject: [PATCH] tests: fix missing priority blacklist test
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
tests/blacklist.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/tests/blacklist.c b/tests/blacklist.c
|
||||
index d20e97af..401600d9 100644
|
||||
--- a/tests/blacklist.c
|
||||
+++ b/tests/blacklist.c
|
||||
@@ -378,7 +378,6 @@ 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;
|
||||
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
|
||||
assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"),
|
||||
MATCH_NOTHING);
|
||||
assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"),
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 5 Nov 2020 09:15:43 -0600
|
||||
Subject: [PATCH] mpathpersist: Fix Register and Ignore with 0x00 SARK
|
||||
|
||||
When the Register and Ignore command is run with sg_persist, if a 0x00
|
||||
Service Action Reservation Key is given or the --param-sark option is
|
||||
not used at all, sg_persist will clear the registration. mpathpersist
|
||||
will fail with an error. This patch fixes mpathpersist to work like
|
||||
sg_persist in this case.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index 3da7a6cf..aa196008 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -321,7 +321,8 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
}
|
||||
|
||||
if (memcmp(paramp->key, &mpp->reservation_key, 8) &&
|
||||
- memcmp(paramp->sa_key, &mpp->reservation_key, 8)) {
|
||||
+ memcmp(paramp->sa_key, &mpp->reservation_key, 8) &&
|
||||
+ (prkey || rq_servact != MPATH_PROUT_REG_IGN_SA)) {
|
||||
condlog(0, "%s: configured reservation key doesn't match: 0x%" PRIx64, alias, get_be64(mpp->reservation_key));
|
||||
ret = MPATH_PR_SYNTAX_ERROR;
|
||||
goto out1;
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 23 Nov 2020 20:45:50 -0600
|
||||
Subject: [PATCH] mpathpersist: update prkeys file on changing registrations
|
||||
|
||||
When the "reservation_key" option is set to "file" and Register command
|
||||
is run with both the current Reservation Key and a new Service Action
|
||||
Reservation Key, mpathpersist will change the registration, but will not
|
||||
update the prkeys file. This means that future paths that come online
|
||||
will not be able to register, since multipathd is still using the old
|
||||
reservation key. Fix this.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index aa196008..a01dfb0b 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -307,9 +307,10 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
|
||||
memcpy(&prkey, paramp->sa_key, 8);
|
||||
if (mpp->prkey_source == PRKEY_SOURCE_FILE && prkey &&
|
||||
- ((!get_be64(mpp->reservation_key) &&
|
||||
- rq_servact == MPATH_PROUT_REG_SA) ||
|
||||
- rq_servact == MPATH_PROUT_REG_IGN_SA)) {
|
||||
+ (rq_servact == MPATH_PROUT_REG_IGN_SA ||
|
||||
+ (rq_servact == MPATH_PROUT_REG_SA &&
|
||||
+ (!get_be64(mpp->reservation_key) ||
|
||||
+ memcmp(paramp->key, &mpp->reservation_key, 8) == 0)))) {
|
||||
memcpy(&mpp->reservation_key, paramp->sa_key, 8);
|
||||
if (update_prkey_flags(alias, get_be64(mpp->reservation_key),
|
||||
paramp->sa_flags)) {
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 14 Dec 2020 14:16:29 -0600
|
||||
Subject: [PATCH] multipathd: Fix multipathd stopping on shutdown
|
||||
|
||||
According to man "systemd.special"
|
||||
|
||||
"shutdown.target: ... Services that shall be terminated on system
|
||||
shutdown shall add Conflicts= and Before= dependencies to this unit for
|
||||
their service unit, which is implicitly done when
|
||||
DefaultDependencies=yes is set (the default)."
|
||||
|
||||
multipathd.service sets DefaultDependencies=no and includes the
|
||||
Conflits= dependency, but not the Before= one. This can cause multipathd
|
||||
to continue running past when it is supposed to during shutdown.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipathd/multipathd.service | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
|
||||
index 0fbcc46b..bc8fa07a 100644
|
||||
--- a/multipathd/multipathd.service
|
||||
+++ b/multipathd/multipathd.service
|
||||
@@ -2,7 +2,7 @@
|
||||
Description=Device-Mapper Multipath Device Controller
|
||||
Wants=systemd-udev-trigger.service systemd-udev-settle.service
|
||||
Before=iscsi.service iscsid.service lvm2-activation-early.service
|
||||
-Before=local-fs-pre.target blk-availability.service
|
||||
+Before=local-fs-pre.target blk-availability.service shutdown.target
|
||||
After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service
|
||||
ConditionPathExists=/etc/multipath.conf
|
||||
DefaultDependencies=no
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Tue, 15 Dec 2020 12:47:14 -0600
|
||||
Subject: [PATCH] multipath.conf.5: Improve checker_timeout description
|
||||
|
||||
I was asked to explain how checker_timeout works for checkers like
|
||||
directio, that don't issue scsi commands with an explicit timeout
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipath/multipath.conf.5 | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||
index 60954574..a5686090 100644
|
||||
--- a/multipath/multipath.conf.5
|
||||
+++ b/multipath/multipath.conf.5
|
||||
@@ -634,8 +634,13 @@ The default is: \fBno\fR
|
||||
.
|
||||
.TP
|
||||
.B checker_timeout
|
||||
-Specify the timeout to use for path checkers and prioritizers that issue SCSI
|
||||
-commands with an explicit timeout, in seconds.
|
||||
+Specify the timeout to use for path checkers and prioritizers, in seconds.
|
||||
+Only prioritizers that issue scsi commands use checker_timeout. Checkers
|
||||
+that support an asynchronous mode (\fItur\fR and \fIdirectio\fR), will
|
||||
+return shortly after being called by multipathd, regardless of whether the
|
||||
+storage array responds. If the storage array hasn't responded, mulitpathd will
|
||||
+check for a response every second, until \fIchecker_timeout\fR seconds have
|
||||
+elapsed.
|
||||
.RS
|
||||
.TP
|
||||
The default is: in \fB/sys/block/sd<x>/device/timeout\fR
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 4 Jan 2021 21:59:54 -0600
|
||||
Subject: [PATCH] libmultipath: check for null wwid before strcmp
|
||||
|
||||
Commit 749aabd0 (libmultipath: ignore multipaths sections without wwid
|
||||
option) removed all mpentries with a NULL wwid, but didn't stop strcmp()
|
||||
from being run on them in merge_mptable(). The result of strcmp() with
|
||||
a NULL parameter is undefined, so fix that.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
libmultipath/config.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||
index dc81c994..dd645f17 100644
|
||||
--- a/libmultipath/config.c
|
||||
+++ b/libmultipath/config.c
|
||||
@@ -453,7 +453,7 @@ void merge_mptable(vector mptable)
|
||||
}
|
||||
j = i + 1;
|
||||
vector_foreach_slot_after(mptable, mp2, j) {
|
||||
- if (strcmp(mp1->wwid, mp2->wwid))
|
||||
+ if (!mp2->wwid || strcmp(mp1->wwid, mp2->wwid))
|
||||
continue;
|
||||
condlog(1, "%s: duplicate multipath config section for %s",
|
||||
__func__, mp1->wwid);
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,27 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 14 Jan 2021 20:20:22 -0600
|
||||
Subject: [PATCH] libmultipath: make find_err_path_by_dev() static
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/io_err_stat.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||
index 1b9cd6c0..449760a0 100644
|
||||
--- a/libmultipath/io_err_stat.c
|
||||
+++ b/libmultipath/io_err_stat.c
|
||||
@@ -89,7 +89,7 @@ static void rcu_unregister(__attribute__((unused)) void *param)
|
||||
rcu_unregister_thread();
|
||||
}
|
||||
|
||||
-struct io_err_stat_path *find_err_path_by_dev(vector pathvec, char *dev)
|
||||
+static struct io_err_stat_path *find_err_path_by_dev(vector pathvec, char *dev)
|
||||
{
|
||||
int i;
|
||||
struct io_err_stat_path *pp;
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,291 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 14 Jan 2021 20:20:23 -0600
|
||||
Subject: [PATCH] multipathd: avoid io_err_stat crash during shutdown
|
||||
|
||||
The checker thread is reponsible for enqueueing paths for the
|
||||
io_err_stat thread to check. During shutdown, the io_err_stat thread is
|
||||
shut down and cleaned up before the checker thread. There is no code
|
||||
to make sure that the checker thread isn't accessing the io_err_stat
|
||||
pathvec or its mutex while they are being freed, which can lead to
|
||||
memory corruption crashes.
|
||||
|
||||
To solve this, get rid of the io_err_stat_pathvec structure, and
|
||||
statically define the mutex. This means that the mutex is always valid
|
||||
to access, and the io_err_stat pathvec can only be accessed while
|
||||
holding it. If the io_err_stat thread has already been cleaned up
|
||||
when the checker tries to access the pathvec, it will be NULL, and the
|
||||
checker will simply fail to enqueue the path.
|
||||
|
||||
This change also fixes a bug in free_io_err_pathvec(), which previously
|
||||
only attempted to free the pathvec if it was not set, instead of when it
|
||||
was set.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/io_err_stat.c | 112 +++++++++++++++----------------------
|
||||
libmultipath/util.c | 5 ++
|
||||
libmultipath/util.h | 1 +
|
||||
3 files changed, 50 insertions(+), 68 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||
index 449760a0..f6c564f0 100644
|
||||
--- a/libmultipath/io_err_stat.c
|
||||
+++ b/libmultipath/io_err_stat.c
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "lock.h"
|
||||
#include "time-util.h"
|
||||
#include "io_err_stat.h"
|
||||
+#include "util.h"
|
||||
|
||||
#define IOTIMEOUT_SEC 60
|
||||
#define TIMEOUT_NO_IO_NSEC 10000000 /*10ms = 10000000ns*/
|
||||
@@ -46,12 +47,6 @@
|
||||
#define io_err_stat_log(prio, fmt, args...) \
|
||||
condlog(prio, "io error statistic: " fmt, ##args)
|
||||
|
||||
-
|
||||
-struct io_err_stat_pathvec {
|
||||
- pthread_mutex_t mutex;
|
||||
- vector pathvec;
|
||||
-};
|
||||
-
|
||||
struct dio_ctx {
|
||||
struct timespec io_starttime;
|
||||
unsigned int blksize;
|
||||
@@ -76,9 +71,10 @@ pthread_attr_t io_err_stat_attr;
|
||||
|
||||
static pthread_mutex_t io_err_thread_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_cond_t io_err_thread_cond = PTHREAD_COND_INITIALIZER;
|
||||
+static pthread_mutex_t io_err_pathvec_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static int io_err_thread_running = 0;
|
||||
|
||||
-static struct io_err_stat_pathvec *paths;
|
||||
+static vector io_err_pathvec;
|
||||
struct vectors *vecs;
|
||||
io_context_t ioctx;
|
||||
|
||||
@@ -208,46 +204,23 @@ static void free_io_err_stat_path(struct io_err_stat_path *p)
|
||||
FREE(p);
|
||||
}
|
||||
|
||||
-static struct io_err_stat_pathvec *alloc_pathvec(void)
|
||||
-{
|
||||
- struct io_err_stat_pathvec *p;
|
||||
- int r;
|
||||
-
|
||||
- p = (struct io_err_stat_pathvec *)MALLOC(sizeof(*p));
|
||||
- if (!p)
|
||||
- return NULL;
|
||||
- p->pathvec = vector_alloc();
|
||||
- if (!p->pathvec)
|
||||
- goto out_free_struct_pathvec;
|
||||
- r = pthread_mutex_init(&p->mutex, NULL);
|
||||
- if (r)
|
||||
- goto out_free_member_pathvec;
|
||||
-
|
||||
- return p;
|
||||
-
|
||||
-out_free_member_pathvec:
|
||||
- vector_free(p->pathvec);
|
||||
-out_free_struct_pathvec:
|
||||
- FREE(p);
|
||||
- return NULL;
|
||||
-}
|
||||
-
|
||||
-static void free_io_err_pathvec(struct io_err_stat_pathvec *p)
|
||||
+static void free_io_err_pathvec(void)
|
||||
{
|
||||
struct io_err_stat_path *path;
|
||||
int i;
|
||||
|
||||
- if (!p)
|
||||
- return;
|
||||
- pthread_mutex_destroy(&p->mutex);
|
||||
- if (!p->pathvec) {
|
||||
- vector_foreach_slot(p->pathvec, path, i) {
|
||||
- destroy_directio_ctx(path);
|
||||
- free_io_err_stat_path(path);
|
||||
- }
|
||||
- vector_free(p->pathvec);
|
||||
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &io_err_pathvec_lock);
|
||||
+ if (!io_err_pathvec)
|
||||
+ goto out;
|
||||
+ vector_foreach_slot(io_err_pathvec, path, i) {
|
||||
+ destroy_directio_ctx(path);
|
||||
+ free_io_err_stat_path(path);
|
||||
}
|
||||
- FREE(p);
|
||||
+ vector_free(io_err_pathvec);
|
||||
+ io_err_pathvec = NULL;
|
||||
+out:
|
||||
+ pthread_cleanup_pop(1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -259,13 +232,13 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||
{
|
||||
struct io_err_stat_path *p;
|
||||
|
||||
- pthread_mutex_lock(&paths->mutex);
|
||||
- p = find_err_path_by_dev(paths->pathvec, path->dev);
|
||||
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||
+ p = find_err_path_by_dev(io_err_pathvec, path->dev);
|
||||
if (p) {
|
||||
- pthread_mutex_unlock(&paths->mutex);
|
||||
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
return 0;
|
||||
}
|
||||
- pthread_mutex_unlock(&paths->mutex);
|
||||
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
|
||||
p = alloc_io_err_stat_path();
|
||||
if (!p)
|
||||
@@ -277,18 +250,18 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||
|
||||
if (setup_directio_ctx(p))
|
||||
goto free_ioerr_path;
|
||||
- pthread_mutex_lock(&paths->mutex);
|
||||
- if (!vector_alloc_slot(paths->pathvec))
|
||||
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||
+ if (!vector_alloc_slot(io_err_pathvec))
|
||||
goto unlock_destroy;
|
||||
- vector_set_slot(paths->pathvec, p);
|
||||
- pthread_mutex_unlock(&paths->mutex);
|
||||
+ vector_set_slot(io_err_pathvec, p);
|
||||
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
|
||||
io_err_stat_log(2, "%s: enqueue path %s to check",
|
||||
path->mpp->alias, path->dev);
|
||||
return 0;
|
||||
|
||||
unlock_destroy:
|
||||
- pthread_mutex_unlock(&paths->mutex);
|
||||
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
destroy_directio_ctx(p);
|
||||
free_ioerr_path:
|
||||
free_io_err_stat_path(p);
|
||||
@@ -421,9 +394,9 @@ static int delete_io_err_stat_by_addr(struct io_err_stat_path *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
- i = find_slot(paths->pathvec, p);
|
||||
+ i = find_slot(io_err_pathvec, p);
|
||||
if (i != -1)
|
||||
- vector_del_slot(paths->pathvec, i);
|
||||
+ vector_del_slot(io_err_pathvec, i);
|
||||
|
||||
destroy_directio_ctx(p);
|
||||
free_io_err_stat_path(p);
|
||||
@@ -594,7 +567,7 @@ static void poll_async_io_timeout(void)
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0)
|
||||
return;
|
||||
- vector_foreach_slot(paths->pathvec, pp, i) {
|
||||
+ vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||
for (j = 0; j < CONCUR_NR_EVENT; j++) {
|
||||
rc = try_to_cancel_timeout_io(pp->dio_ctx_array + j,
|
||||
&curr_time, pp->devname);
|
||||
@@ -640,7 +613,7 @@ static void handle_async_io_done_event(struct io_event *io_evt)
|
||||
int rc = PATH_UNCHECKED;
|
||||
int i, j;
|
||||
|
||||
- vector_foreach_slot(paths->pathvec, pp, i) {
|
||||
+ vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||
for (j = 0; j < CONCUR_NR_EVENT; j++) {
|
||||
ct = pp->dio_ctx_array + j;
|
||||
if (&ct->io == io_evt->obj) {
|
||||
@@ -674,19 +647,14 @@ static void service_paths(void)
|
||||
struct io_err_stat_path *pp;
|
||||
int i;
|
||||
|
||||
- pthread_mutex_lock(&paths->mutex);
|
||||
- vector_foreach_slot(paths->pathvec, pp, i) {
|
||||
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||
+ vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||
send_batch_async_ios(pp);
|
||||
process_async_ios_event(TIMEOUT_NO_IO_NSEC, pp->devname);
|
||||
poll_async_io_timeout();
|
||||
poll_io_err_stat(vecs, pp);
|
||||
}
|
||||
- pthread_mutex_unlock(&paths->mutex);
|
||||
-}
|
||||
-
|
||||
-static void cleanup_unlock(void *arg)
|
||||
-{
|
||||
- pthread_mutex_unlock((pthread_mutex_t*) arg);
|
||||
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
}
|
||||
|
||||
static void cleanup_exited(__attribute__((unused)) void *arg)
|
||||
@@ -744,12 +712,17 @@ int start_io_err_stat_thread(void *data)
|
||||
io_err_stat_log(4, "io_setup failed");
|
||||
return 1;
|
||||
}
|
||||
- paths = alloc_pathvec();
|
||||
- if (!paths)
|
||||
+
|
||||
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||
+ io_err_pathvec = vector_alloc();
|
||||
+ if (!io_err_pathvec) {
|
||||
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
goto destroy_ctx;
|
||||
+ }
|
||||
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
|
||||
pthread_mutex_lock(&io_err_thread_lock);
|
||||
- pthread_cleanup_push(cleanup_unlock, &io_err_thread_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &io_err_thread_lock);
|
||||
|
||||
ret = pthread_create(&io_err_stat_thr, &io_err_stat_attr,
|
||||
io_err_stat_loop, data);
|
||||
@@ -769,7 +742,10 @@ int start_io_err_stat_thread(void *data)
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
- free_io_err_pathvec(paths);
|
||||
+ pthread_mutex_lock(&io_err_pathvec_lock);
|
||||
+ vector_free(io_err_pathvec);
|
||||
+ io_err_pathvec = NULL;
|
||||
+ pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
destroy_ctx:
|
||||
io_destroy(ioctx);
|
||||
io_err_stat_log(0, "failed to start io_error statistic thread");
|
||||
@@ -785,6 +761,6 @@ void stop_io_err_stat_thread(void)
|
||||
pthread_cancel(io_err_stat_thr);
|
||||
|
||||
pthread_join(io_err_stat_thr, NULL);
|
||||
- free_io_err_pathvec(paths);
|
||||
+ free_io_err_pathvec();
|
||||
io_destroy(ioctx);
|
||||
}
|
||||
diff --git a/libmultipath/util.c b/libmultipath/util.c
|
||||
index 51c38c87..dd30a46e 100644
|
||||
--- a/libmultipath/util.c
|
||||
+++ b/libmultipath/util.c
|
||||
@@ -469,3 +469,8 @@ void close_fd(void *arg)
|
||||
{
|
||||
close((long)arg);
|
||||
}
|
||||
+
|
||||
+void cleanup_mutex(void *arg)
|
||||
+{
|
||||
+ pthread_mutex_unlock(arg);
|
||||
+}
|
||||
diff --git a/libmultipath/util.h b/libmultipath/util.h
|
||||
index 56bd78c7..ce277680 100644
|
||||
--- a/libmultipath/util.h
|
||||
+++ b/libmultipath/util.h
|
||||
@@ -44,6 +44,7 @@ void set_max_fds(rlim_t max_fds);
|
||||
pthread_cleanup_push(((void (*)(void *))&f), (arg))
|
||||
|
||||
void close_fd(void *arg);
|
||||
+void cleanup_mutex(void *arg);
|
||||
|
||||
struct scandir_result {
|
||||
struct dirent **di;
|
||||
--
|
||||
2.17.2
|
||||
|
146
SOURCES/0055-multipathd-avoid-io_err_stat-ABBA-deadlock.patch
Normal file
146
SOURCES/0055-multipathd-avoid-io_err_stat-ABBA-deadlock.patch
Normal file
@ -0,0 +1,146 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 14 Jan 2021 20:20:24 -0600
|
||||
Subject: [PATCH] multipathd: avoid io_err_stat ABBA deadlock
|
||||
|
||||
When the checker thread enqueues paths for the io_err_stat thread to
|
||||
check, it calls enqueue_io_err_stat_by_path() with the vecs lock held.
|
||||
start_io_err_stat_thread() is also called with the vecs lock held.
|
||||
These two functions both lock io_err_pathvec_lock. When the io_err_stat
|
||||
thread updates the paths in vecs->pathvec in poll_io_err_stat(), it has
|
||||
the io_err_pathvec_lock held, and then locks the vecs lock. This can
|
||||
cause an ABBA deadlock.
|
||||
|
||||
To solve this, service_paths() no longer updates the paths in
|
||||
vecs->pathvec with the io_err_pathvec_lock held. It does this by moving
|
||||
the io_err_stat_path from io_err_pathvec to a local vector when it needs
|
||||
to update the path. After releasing the io_err_pathvec_lock, it goes
|
||||
through this temporary vector, updates the paths with the vecs lock
|
||||
held, and then frees everything.
|
||||
|
||||
This change fixes a bug in service_paths() where elements were being
|
||||
deleted from io_err_pathvec, without the index being decremented,
|
||||
causing the loop to skip elements. Also, service_paths() could be
|
||||
cancelled while holding the io_err_pathvec_lock, so it should have a
|
||||
cleanup handler.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/io_err_stat.c | 56 ++++++++++++++++++++++----------------
|
||||
1 file changed, 32 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||
index f6c564f0..63ee2e07 100644
|
||||
--- a/libmultipath/io_err_stat.c
|
||||
+++ b/libmultipath/io_err_stat.c
|
||||
@@ -390,20 +390,6 @@ recover:
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int delete_io_err_stat_by_addr(struct io_err_stat_path *p)
|
||||
-{
|
||||
- int i;
|
||||
-
|
||||
- i = find_slot(io_err_pathvec, p);
|
||||
- if (i != -1)
|
||||
- vector_del_slot(io_err_pathvec, i);
|
||||
-
|
||||
- destroy_directio_ctx(p);
|
||||
- free_io_err_stat_path(p);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static void account_async_io_state(struct io_err_stat_path *pp, int rc)
|
||||
{
|
||||
switch (rc) {
|
||||
@@ -420,17 +406,26 @@ static void account_async_io_state(struct io_err_stat_path *pp, int rc)
|
||||
}
|
||||
}
|
||||
|
||||
-static int poll_io_err_stat(struct vectors *vecs, struct io_err_stat_path *pp)
|
||||
+static int io_err_stat_time_up(struct io_err_stat_path *pp)
|
||||
{
|
||||
struct timespec currtime, difftime;
|
||||
- struct path *path;
|
||||
- double err_rate;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||
- return 1;
|
||||
+ return 0;
|
||||
timespecsub(&currtime, &pp->start_time, &difftime);
|
||||
if (difftime.tv_sec < pp->total_time)
|
||||
return 0;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static void end_io_err_stat(struct io_err_stat_path *pp)
|
||||
+{
|
||||
+ struct timespec currtime;
|
||||
+ struct path *path;
|
||||
+ double err_rate;
|
||||
+
|
||||
+ if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||
+ currtime = pp->start_time;
|
||||
|
||||
io_err_stat_log(4, "%s: check end", pp->devname);
|
||||
|
||||
@@ -469,10 +464,6 @@ static int poll_io_err_stat(struct vectors *vecs, struct io_err_stat_path *pp)
|
||||
pp->devname);
|
||||
}
|
||||
lock_cleanup_pop(vecs->lock);
|
||||
-
|
||||
- delete_io_err_stat_by_addr(pp);
|
||||
-
|
||||
- return 0;
|
||||
}
|
||||
|
||||
static int send_each_async_io(struct dio_ctx *ct, int fd, char *dev)
|
||||
@@ -632,6 +623,7 @@ static void process_async_ios_event(int timeout_nsecs, char *dev)
|
||||
struct timespec timeout = { .tv_nsec = timeout_nsecs };
|
||||
|
||||
errno = 0;
|
||||
+ pthread_testcancel();
|
||||
n = io_getevents(ioctx, 1L, CONCUR_NR_EVENT, events, &timeout);
|
||||
if (n < 0) {
|
||||
io_err_stat_log(3, "%s: async io events returned %d (errno=%s)",
|
||||
@@ -644,17 +636,33 @@ static void process_async_ios_event(int timeout_nsecs, char *dev)
|
||||
|
||||
static void service_paths(void)
|
||||
{
|
||||
+ struct _vector _pathvec = {0};
|
||||
+ /* avoid gcc warnings that &_pathvec will never be NULL in vector ops */
|
||||
+ struct _vector * const tmp_pathvec = &_pathvec;
|
||||
struct io_err_stat_path *pp;
|
||||
int i;
|
||||
|
||||
pthread_mutex_lock(&io_err_pathvec_lock);
|
||||
+ pthread_cleanup_push(cleanup_mutex, &io_err_pathvec_lock);
|
||||
vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||
send_batch_async_ios(pp);
|
||||
process_async_ios_event(TIMEOUT_NO_IO_NSEC, pp->devname);
|
||||
poll_async_io_timeout();
|
||||
- poll_io_err_stat(vecs, pp);
|
||||
+ if (io_err_stat_time_up(pp)) {
|
||||
+ if (!vector_alloc_slot(tmp_pathvec))
|
||||
+ continue;
|
||||
+ vector_del_slot(io_err_pathvec, i--);
|
||||
+ vector_set_slot(tmp_pathvec, pp);
|
||||
+ }
|
||||
}
|
||||
- pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
+ pthread_cleanup_pop(1);
|
||||
+ vector_foreach_slot_backwards(tmp_pathvec, pp, i) {
|
||||
+ end_io_err_stat(pp);
|
||||
+ vector_del_slot(tmp_pathvec, i);
|
||||
+ destroy_directio_ctx(pp);
|
||||
+ free_io_err_stat_path(pp);
|
||||
+ }
|
||||
+ vector_reset(tmp_pathvec);
|
||||
}
|
||||
|
||||
static void cleanup_exited(__attribute__((unused)) void *arg)
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,111 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 14 Jan 2021 20:20:25 -0600
|
||||
Subject: [PATCH] multipathd: use get_monotonic_time() in io_err_stat code
|
||||
|
||||
Instead of calling clock_gettime(), and dealing with failure
|
||||
conditions, just call get_monotonic_time().
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/io_err_stat.c | 34 +++++++++++-----------------------
|
||||
1 file changed, 11 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||
index 63ee2e07..3389d693 100644
|
||||
--- a/libmultipath/io_err_stat.c
|
||||
+++ b/libmultipath/io_err_stat.c
|
||||
@@ -305,8 +305,7 @@ int io_err_stat_handle_pathfail(struct path *path)
|
||||
* the repeated count threshold and time frame, we assume a path
|
||||
* which fails at least twice within 60 seconds is flaky.
|
||||
*/
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0)
|
||||
- return 1;
|
||||
+ get_monotonic_time(&curr_time);
|
||||
if (path->io_err_pathfail_cnt == 0) {
|
||||
path->io_err_pathfail_cnt++;
|
||||
path->io_err_pathfail_starttime = curr_time.tv_sec;
|
||||
@@ -362,9 +361,9 @@ int need_io_err_check(struct path *pp)
|
||||
}
|
||||
if (pp->io_err_pathfail_cnt != PATH_IO_ERR_WAITING_TO_CHECK)
|
||||
return 1;
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0 ||
|
||||
- (curr_time.tv_sec - pp->io_err_dis_reinstate_time) >
|
||||
- pp->mpp->marginal_path_err_recheck_gap_time) {
|
||||
+ get_monotonic_time(&curr_time);
|
||||
+ if ((curr_time.tv_sec - pp->io_err_dis_reinstate_time) >
|
||||
+ pp->mpp->marginal_path_err_recheck_gap_time) {
|
||||
io_err_stat_log(4, "%s: reschedule checking after %d seconds",
|
||||
pp->dev,
|
||||
pp->mpp->marginal_path_err_recheck_gap_time);
|
||||
@@ -410,8 +409,7 @@ static int io_err_stat_time_up(struct io_err_stat_path *pp)
|
||||
{
|
||||
struct timespec currtime, difftime;
|
||||
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||
- return 0;
|
||||
+ get_monotonic_time(&currtime);
|
||||
timespecsub(&currtime, &pp->start_time, &difftime);
|
||||
if (difftime.tv_sec < pp->total_time)
|
||||
return 0;
|
||||
@@ -424,8 +422,7 @@ static void end_io_err_stat(struct io_err_stat_path *pp)
|
||||
struct path *path;
|
||||
double err_rate;
|
||||
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||
- currtime = pp->start_time;
|
||||
+ get_monotonic_time(&currtime);
|
||||
|
||||
io_err_stat_log(4, "%s: check end", pp->devname);
|
||||
|
||||
@@ -474,11 +471,7 @@ static int send_each_async_io(struct dio_ctx *ct, int fd, char *dev)
|
||||
ct->io_starttime.tv_sec == 0) {
|
||||
struct iocb *ios[1] = { &ct->io };
|
||||
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &ct->io_starttime) != 0) {
|
||||
- ct->io_starttime.tv_sec = 0;
|
||||
- ct->io_starttime.tv_nsec = 0;
|
||||
- return rc;
|
||||
- }
|
||||
+ get_monotonic_time(&ct->io_starttime);
|
||||
io_prep_pread(&ct->io, fd, ct->buf, ct->blksize, 0);
|
||||
if (io_submit(ioctx, 1, ios) != 1) {
|
||||
io_err_stat_log(5, "%s: io_submit error %i",
|
||||
@@ -497,8 +490,7 @@ static void send_batch_async_ios(struct io_err_stat_path *pp)
|
||||
struct dio_ctx *ct;
|
||||
struct timespec currtime, difftime;
|
||||
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &currtime) != 0)
|
||||
- return;
|
||||
+ get_monotonic_time(&currtime);
|
||||
/*
|
||||
* Give a free time for all IO to complete or timeout
|
||||
*/
|
||||
@@ -513,11 +505,8 @@ static void send_batch_async_ios(struct io_err_stat_path *pp)
|
||||
if (!send_each_async_io(ct, pp->fd, pp->devname))
|
||||
pp->io_nr++;
|
||||
}
|
||||
- if (pp->start_time.tv_sec == 0 && pp->start_time.tv_nsec == 0 &&
|
||||
- clock_gettime(CLOCK_MONOTONIC, &pp->start_time)) {
|
||||
- pp->start_time.tv_sec = 0;
|
||||
- pp->start_time.tv_nsec = 0;
|
||||
- }
|
||||
+ if (pp->start_time.tv_sec == 0 && pp->start_time.tv_nsec == 0)
|
||||
+ get_monotonic_time(&pp->start_time);
|
||||
}
|
||||
|
||||
static int try_to_cancel_timeout_io(struct dio_ctx *ct, struct timespec *t,
|
||||
@@ -556,8 +545,7 @@ static void poll_async_io_timeout(void)
|
||||
int rc = PATH_UNCHECKED;
|
||||
int i, j;
|
||||
|
||||
- if (clock_gettime(CLOCK_MONOTONIC, &curr_time) != 0)
|
||||
- return;
|
||||
+ get_monotonic_time(&curr_time);
|
||||
vector_foreach_slot(io_err_pathvec, pp, i) {
|
||||
for (j = 0; j < CONCUR_NR_EVENT; j++) {
|
||||
rc = try_to_cancel_timeout_io(pp->dio_ctx_array + j,
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,101 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Thu, 14 Jan 2021 20:20:26 -0600
|
||||
Subject: [PATCH] multipathd: combine free_io_err_stat_path and
|
||||
destroy_directio_ctx
|
||||
|
||||
destroy_directio_ctx() is only called from free_io_err_stat_path(), and
|
||||
free_io_err_stat_path() is very short, so combine them.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/io_err_stat.c | 24 ++++++++++--------------
|
||||
1 file changed, 10 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||
index 3389d693..bf1d3910 100644
|
||||
--- a/libmultipath/io_err_stat.c
|
||||
+++ b/libmultipath/io_err_stat.c
|
||||
@@ -163,12 +163,15 @@ fail_close:
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static void destroy_directio_ctx(struct io_err_stat_path *p)
|
||||
+static void free_io_err_stat_path(struct io_err_stat_path *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
- if (!p || !p->dio_ctx_array)
|
||||
+ if (!p)
|
||||
return;
|
||||
+ if (!p->dio_ctx_array)
|
||||
+ goto free_path;
|
||||
+
|
||||
cancel_inflight_io(p);
|
||||
|
||||
for (i = 0; i < CONCUR_NR_EVENT; i++)
|
||||
@@ -177,6 +180,8 @@ static void destroy_directio_ctx(struct io_err_stat_path *p)
|
||||
|
||||
if (p->fd > 0)
|
||||
close(p->fd);
|
||||
+free_path:
|
||||
+ FREE(p);
|
||||
}
|
||||
|
||||
static struct io_err_stat_path *alloc_io_err_stat_path(void)
|
||||
@@ -199,11 +204,6 @@ static struct io_err_stat_path *alloc_io_err_stat_path(void)
|
||||
return p;
|
||||
}
|
||||
|
||||
-static void free_io_err_stat_path(struct io_err_stat_path *p)
|
||||
-{
|
||||
- FREE(p);
|
||||
-}
|
||||
-
|
||||
static void free_io_err_pathvec(void)
|
||||
{
|
||||
struct io_err_stat_path *path;
|
||||
@@ -213,10 +213,8 @@ static void free_io_err_pathvec(void)
|
||||
pthread_cleanup_push(cleanup_mutex, &io_err_pathvec_lock);
|
||||
if (!io_err_pathvec)
|
||||
goto out;
|
||||
- vector_foreach_slot(io_err_pathvec, path, i) {
|
||||
- destroy_directio_ctx(path);
|
||||
+ vector_foreach_slot(io_err_pathvec, path, i)
|
||||
free_io_err_stat_path(path);
|
||||
- }
|
||||
vector_free(io_err_pathvec);
|
||||
io_err_pathvec = NULL;
|
||||
out:
|
||||
@@ -252,7 +250,7 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||
goto free_ioerr_path;
|
||||
pthread_mutex_lock(&io_err_pathvec_lock);
|
||||
if (!vector_alloc_slot(io_err_pathvec))
|
||||
- goto unlock_destroy;
|
||||
+ goto unlock_pathvec;
|
||||
vector_set_slot(io_err_pathvec, p);
|
||||
pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
|
||||
@@ -260,9 +258,8 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||
path->mpp->alias, path->dev);
|
||||
return 0;
|
||||
|
||||
-unlock_destroy:
|
||||
+unlock_pathvec:
|
||||
pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
- destroy_directio_ctx(p);
|
||||
free_ioerr_path:
|
||||
free_io_err_stat_path(p);
|
||||
|
||||
@@ -647,7 +644,6 @@ static void service_paths(void)
|
||||
vector_foreach_slot_backwards(tmp_pathvec, pp, i) {
|
||||
end_io_err_stat(pp);
|
||||
vector_del_slot(tmp_pathvec, i);
|
||||
- destroy_directio_ctx(pp);
|
||||
free_io_err_stat_path(pp);
|
||||
}
|
||||
vector_reset(tmp_pathvec);
|
||||
--
|
||||
2.17.2
|
||||
|
110
SOURCES/0058-multipathd-cleanup-logging-for-marginal-paths.patch
Normal file
110
SOURCES/0058-multipathd-cleanup-logging-for-marginal-paths.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 18 Jan 2021 22:46:04 -0600
|
||||
Subject: [PATCH] multipathd: cleanup logging for marginal paths
|
||||
|
||||
io_err_stat logged at level 2 whenever it enqueued a path to check,
|
||||
which could happen multiple times while a path was marginal. On the
|
||||
other hand if marginal_pathgroups wasn't set, multipathd didn't log when
|
||||
paths were set to marginal. Now io_err_stat only logs at level 2 when
|
||||
something unexpected happens, but multipathd will always log when a
|
||||
path switches its marginal state.
|
||||
|
||||
This patch also fixes an issue where paths in the delayed state could
|
||||
get set to the pending state if they could not be checked in time.
|
||||
Aside from going against the idea the paths should not be set to pending
|
||||
if they already have a valid state, this caused multipathd to log a
|
||||
message whenever the path state switched to from delayed to pending and
|
||||
then back.
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmultipath/io_err_stat.c | 7 +++----
|
||||
multipathd/main.c | 20 +++++++++++++-------
|
||||
2 files changed, 16 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/libmultipath/io_err_stat.c b/libmultipath/io_err_stat.c
|
||||
index bf1d3910..ee711f7f 100644
|
||||
--- a/libmultipath/io_err_stat.c
|
||||
+++ b/libmultipath/io_err_stat.c
|
||||
@@ -254,7 +254,7 @@ static int enqueue_io_err_stat_by_path(struct path *path)
|
||||
vector_set_slot(io_err_pathvec, p);
|
||||
pthread_mutex_unlock(&io_err_pathvec_lock);
|
||||
|
||||
- io_err_stat_log(2, "%s: enqueue path %s to check",
|
||||
+ io_err_stat_log(3, "%s: enqueue path %s to check",
|
||||
path->mpp->alias, path->dev);
|
||||
return 0;
|
||||
|
||||
@@ -353,7 +353,7 @@ int need_io_err_check(struct path *pp)
|
||||
if (uatomic_read(&io_err_thread_running) == 0)
|
||||
return 0;
|
||||
if (count_active_paths(pp->mpp) <= 0) {
|
||||
- io_err_stat_log(2, "%s: recover path early", pp->dev);
|
||||
+ io_err_stat_log(2, "%s: no paths. recovering early", pp->dev);
|
||||
goto recover;
|
||||
}
|
||||
if (pp->io_err_pathfail_cnt != PATH_IO_ERR_WAITING_TO_CHECK)
|
||||
@@ -371,8 +371,7 @@ int need_io_err_check(struct path *pp)
|
||||
* Or else, return 1 to set path state to PATH_SHAKY
|
||||
*/
|
||||
if (r == 1) {
|
||||
- io_err_stat_log(3, "%s: enqueue fails, to recover",
|
||||
- pp->dev);
|
||||
+ io_err_stat_log(2, "%s: enqueue failed. recovering early", pp->dev);
|
||||
goto recover;
|
||||
} else
|
||||
pp->io_err_pathfail_cnt = PATH_IO_ERR_IN_CHECKING;
|
||||
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||
index 1d0579e9..cc1aeea2 100644
|
||||
--- a/multipathd/main.c
|
||||
+++ b/multipathd/main.c
|
||||
@@ -2041,8 +2041,8 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
pathinfo(pp, conf, 0);
|
||||
pthread_cleanup_pop(1);
|
||||
return 1;
|
||||
- } else if ((newstate != PATH_UP && newstate != PATH_GHOST) &&
|
||||
- (pp->state == PATH_DELAYED)) {
|
||||
+ } else if ((newstate != PATH_UP && newstate != PATH_GHOST &&
|
||||
+ newstate != PATH_PENDING) && (pp->state == PATH_DELAYED)) {
|
||||
/* If path state become failed again cancel path delay state */
|
||||
pp->state = newstate;
|
||||
return 1;
|
||||
@@ -2104,8 +2104,9 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
if ((newstate == PATH_UP || newstate == PATH_GHOST) &&
|
||||
(san_path_check_enabled(pp->mpp) ||
|
||||
marginal_path_check_enabled(pp->mpp))) {
|
||||
- int was_marginal = pp->marginal;
|
||||
if (should_skip_path(pp)) {
|
||||
+ if (!pp->marginal && pp->state != PATH_DELAYED)
|
||||
+ condlog(2, "%s: path is now marginal", pp->dev);
|
||||
if (!marginal_pathgroups) {
|
||||
if (marginal_path_check_enabled(pp->mpp))
|
||||
/* to reschedule as soon as possible,
|
||||
@@ -2115,13 +2116,18 @@ check_path (struct vectors * vecs, struct path * pp, unsigned int ticks)
|
||||
pp->state = PATH_DELAYED;
|
||||
return 1;
|
||||
}
|
||||
- if (!was_marginal) {
|
||||
+ if (!pp->marginal) {
|
||||
pp->marginal = 1;
|
||||
marginal_changed = 1;
|
||||
}
|
||||
- } else if (marginal_pathgroups && was_marginal) {
|
||||
- pp->marginal = 0;
|
||||
- marginal_changed = 1;
|
||||
+ } else {
|
||||
+ if (pp->marginal || pp->state == PATH_DELAYED)
|
||||
+ condlog(2, "%s: path is no longer marginal",
|
||||
+ pp->dev);
|
||||
+ if (marginal_pathgroups && pp->marginal) {
|
||||
+ pp->marginal = 0;
|
||||
+ marginal_changed = 1;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,277 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Mon, 25 Jan 2021 23:31:04 -0600
|
||||
Subject: [PATCH] libmpathpersist: fix thread safety of default functions
|
||||
|
||||
commit a839e39e ("libmpathpersist: factor out initialization and
|
||||
teardown") made mpath_presistent_reserve_{in,out} use share variables
|
||||
for curmp and pathvec. There are users of this library that call these
|
||||
functions in a multi-threaded process, and this change causes their
|
||||
application to crash. config and udev are also shared variables, but
|
||||
libmpathpersist doesn't write to the config in
|
||||
mpath_presistent_reserve_{in,out}, and looking into the libudev code, I
|
||||
don't see any place where libmpathpersist uses the udev object in a way
|
||||
that isn't thread-safe.
|
||||
|
||||
This patch makes mpath_presistent_reserve_{in,out} go back to using
|
||||
local variables for curmp and pathvec, so that multiple threads won't
|
||||
be operating on these variables at the same time.
|
||||
|
||||
Fixes: a839e39e ("libmpathpersist: factor out initialization and teardown")
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||
---
|
||||
libmpathpersist/mpath_persist.c | 116 +++++++++++++++++++++-----------
|
||||
libmpathpersist/mpath_persist.h | 24 +++++--
|
||||
2 files changed, 94 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||
index a01dfb0b..07a5f17f 100644
|
||||
--- a/libmpathpersist/mpath_persist.c
|
||||
+++ b/libmpathpersist/mpath_persist.c
|
||||
@@ -147,72 +147,60 @@ mpath_prin_activepath (struct multipath *mpp, int rq_servact,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||
- struct prin_resp *resp, int noisy, int verbose)
|
||||
-{
|
||||
- int ret = mpath_persistent_reserve_init_vecs(verbose);
|
||||
-
|
||||
- if (ret != MPATH_PR_SUCCESS)
|
||||
- return ret;
|
||||
- ret = __mpath_persistent_reserve_in(fd, rq_servact, resp, noisy);
|
||||
- mpath_persistent_reserve_free_vecs();
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
|
||||
-{
|
||||
- int ret = mpath_persistent_reserve_init_vecs(verbose);
|
||||
-
|
||||
- if (ret != MPATH_PR_SUCCESS)
|
||||
- return ret;
|
||||
- ret = __mpath_persistent_reserve_out(fd, rq_servact, rq_scope, rq_type,
|
||||
- paramp, noisy);
|
||||
- mpath_persistent_reserve_free_vecs();
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
static vector curmp;
|
||||
static vector pathvec;
|
||||
|
||||
-void mpath_persistent_reserve_free_vecs(void)
|
||||
+static void __mpath_persistent_reserve_free_vecs(vector curmp, vector pathvec)
|
||||
{
|
||||
free_multipathvec(curmp, KEEP_PATHS);
|
||||
free_pathvec(pathvec, FREE_PATHS);
|
||||
+}
|
||||
+
|
||||
+void mpath_persistent_reserve_free_vecs(void)
|
||||
+{
|
||||
+ __mpath_persistent_reserve_free_vecs(curmp, pathvec);
|
||||
curmp = pathvec = NULL;
|
||||
}
|
||||
|
||||
-int mpath_persistent_reserve_init_vecs(int verbose)
|
||||
+static int __mpath_persistent_reserve_init_vecs(vector *curmp_p,
|
||||
+ vector *pathvec_p, int verbose)
|
||||
{
|
||||
struct config *conf = get_multipath_config();
|
||||
|
||||
conf->verbosity = verbose;
|
||||
put_multipath_config(conf);
|
||||
|
||||
- if (curmp)
|
||||
+ if (*curmp_p)
|
||||
return MPATH_PR_SUCCESS;
|
||||
/*
|
||||
* allocate core vectors to store paths and multipaths
|
||||
*/
|
||||
- curmp = vector_alloc ();
|
||||
- pathvec = vector_alloc ();
|
||||
+ *curmp_p = vector_alloc ();
|
||||
+ *pathvec_p = vector_alloc ();
|
||||
|
||||
- if (!curmp || !pathvec){
|
||||
+ if (!*curmp_p || !*pathvec_p){
|
||||
condlog (0, "vector allocation failed.");
|
||||
goto err;
|
||||
}
|
||||
|
||||
- if (dm_get_maps(curmp))
|
||||
+ if (dm_get_maps(*curmp_p))
|
||||
goto err;
|
||||
|
||||
return MPATH_PR_SUCCESS;
|
||||
|
||||
err:
|
||||
- mpath_persistent_reserve_free_vecs();
|
||||
+ __mpath_persistent_reserve_free_vecs(*curmp_p, *pathvec_p);
|
||||
+ *curmp_p = *pathvec_p = NULL;
|
||||
return MPATH_PR_DMMP_ERROR;
|
||||
}
|
||||
|
||||
-static int mpath_get_map(int fd, char **palias, struct multipath **pmpp)
|
||||
+int mpath_persistent_reserve_init_vecs(int verbose)
|
||||
+{
|
||||
+ return __mpath_persistent_reserve_init_vecs(&curmp, &pathvec, verbose);
|
||||
+}
|
||||
+
|
||||
+static int mpath_get_map(vector curmp, vector pathvec, int fd, char **palias,
|
||||
+ struct multipath **pmpp)
|
||||
{
|
||||
int ret = MPATH_PR_DMMP_ERROR;
|
||||
struct stat info;
|
||||
@@ -272,13 +260,13 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int __mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||
- struct prin_resp *resp, int noisy)
|
||||
+static int do_mpath_persistent_reserve_in (vector curmp, vector pathvec,
|
||||
+ int fd, int rq_servact, struct prin_resp *resp, int noisy)
|
||||
{
|
||||
struct multipath *mpp;
|
||||
int ret;
|
||||
|
||||
- ret = mpath_get_map(fd, NULL, &mpp);
|
||||
+ ret = mpath_get_map(curmp, pathvec, fd, NULL, &mpp);
|
||||
if (ret != MPATH_PR_SUCCESS)
|
||||
return ret;
|
||||
|
||||
@@ -287,8 +275,17 @@ int __mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
|
||||
+
|
||||
+int __mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||
+ struct prin_resp *resp, int noisy)
|
||||
+{
|
||||
+ return do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
|
||||
+ resp, noisy);
|
||||
+}
|
||||
+
|
||||
+static int do_mpath_persistent_reserve_out(vector curmp, vector pathvec, int fd,
|
||||
+ int rq_servact, int rq_scope, unsigned int rq_type,
|
||||
+ struct prout_param_descriptor *paramp, int noisy)
|
||||
{
|
||||
struct multipath *mpp;
|
||||
char *alias;
|
||||
@@ -296,7 +293,7 @@ int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
uint64_t prkey;
|
||||
struct config *conf;
|
||||
|
||||
- ret = mpath_get_map(fd, &alias, &mpp);
|
||||
+ ret = mpath_get_map(curmp, pathvec, fd, &alias, &mpp);
|
||||
if (ret != MPATH_PR_SUCCESS)
|
||||
return ret;
|
||||
|
||||
@@ -366,6 +363,45 @@ out1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+
|
||||
+int __mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
+ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
|
||||
+{
|
||||
+ return do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
|
||||
+ rq_scope, rq_type, paramp,
|
||||
+ noisy);
|
||||
+}
|
||||
+
|
||||
+int mpath_persistent_reserve_in (int fd, int rq_servact,
|
||||
+ struct prin_resp *resp, int noisy, int verbose)
|
||||
+{
|
||||
+ vector curmp = NULL, pathvec;
|
||||
+ int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
|
||||
+ verbose);
|
||||
+
|
||||
+ if (ret != MPATH_PR_SUCCESS)
|
||||
+ return ret;
|
||||
+ ret = do_mpath_persistent_reserve_in(curmp, pathvec, fd, rq_servact,
|
||||
+ resp, noisy);
|
||||
+ __mpath_persistent_reserve_free_vecs(curmp, pathvec);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
+ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy, int verbose)
|
||||
+{
|
||||
+ vector curmp = NULL, pathvec;
|
||||
+ int ret = __mpath_persistent_reserve_init_vecs(&curmp, &pathvec,
|
||||
+ verbose);
|
||||
+
|
||||
+ if (ret != MPATH_PR_SUCCESS)
|
||||
+ return ret;
|
||||
+ ret = do_mpath_persistent_reserve_out(curmp, pathvec, fd, rq_servact,
|
||||
+ rq_scope, rq_type, paramp, noisy);
|
||||
+ __mpath_persistent_reserve_free_vecs(curmp, pathvec);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int
|
||||
get_mpvec (vector curmp, vector pathvec, char * refwwid)
|
||||
{
|
||||
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
|
||||
index 7cf4faf9..0e4e0e53 100644
|
||||
--- a/libmpathpersist/mpath_persist.h
|
||||
+++ b/libmpathpersist/mpath_persist.h
|
||||
@@ -215,9 +215,13 @@ extern int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp
|
||||
|
||||
/*
|
||||
* DESCRIPTION :
|
||||
- * This function is like mpath_persistent_reserve_in(), except that it doesn't call
|
||||
- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs()
|
||||
- * before and after the actual PR call.
|
||||
+ * This function is like mpath_persistent_reserve_in(), except that it
|
||||
+ * requires mpath_persistent_reserve_init_vecs() to be called before the
|
||||
+ * PR call to set up internal variables. These must later be cleanup up
|
||||
+ * by calling mpath_persistent_reserve_free_vecs().
|
||||
+ *
|
||||
+ * RESTRICTIONS:
|
||||
+ * This function uses static internal variables, and is not thread-safe.
|
||||
*/
|
||||
extern int __mpath_persistent_reserve_in(int fd, int rq_servact,
|
||||
struct prin_resp *resp, int noisy);
|
||||
@@ -249,9 +253,13 @@ extern int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
|
||||
int verbose);
|
||||
/*
|
||||
* DESCRIPTION :
|
||||
- * This function is like mpath_persistent_reserve_out(), except that it doesn't call
|
||||
- * mpath_persistent_reserve_init_vecs() and mpath_persistent_reserve_free_vecs()
|
||||
- * before and after the actual PR call.
|
||||
+ * This function is like mpath_persistent_reserve_out(), except that it
|
||||
+ * requires mpath_persistent_reserve_init_vecs() to be called before the
|
||||
+ * PR call to set up internal variables. These must later be cleanup up
|
||||
+ * by calling mpath_persistent_reserve_free_vecs().
|
||||
+ *
|
||||
+ * RESTRICTIONS:
|
||||
+ * This function uses static internal variables, and is not thread-safe.
|
||||
*/
|
||||
extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope,
|
||||
unsigned int rq_type, struct prout_param_descriptor *paramp,
|
||||
@@ -265,6 +273,7 @@ extern int __mpath_persistent_reserve_out( int fd, int rq_servact, int rq_scope,
|
||||
* @verbose: Set verbosity level. Input argument. value:0 to 3. 0->disabled, 3->Max verbose
|
||||
*
|
||||
* RESTRICTIONS:
|
||||
+ * This function uses static internal variables, and is not thread-safe.
|
||||
*
|
||||
* RETURNS: MPATH_PR_SUCCESS if successful else returns any of the status specified
|
||||
* above in RETURN_STATUS.
|
||||
@@ -275,6 +284,9 @@ int mpath_persistent_reserve_init_vecs(int verbose);
|
||||
* DESCRIPTION :
|
||||
* This function frees data structures allocated by
|
||||
* mpath_persistent_reserve_init_vecs().
|
||||
+ *
|
||||
+ * RESTRICTIONS:
|
||||
+ * This function uses static internal variables, and is not thread-safe.
|
||||
*/
|
||||
void mpath_persistent_reserve_free_vecs(void);
|
||||
|
||||
--
|
||||
2.17.2
|
||||
|
@ -0,0 +1,61 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Tue, 9 Feb 2021 17:16:04 -0600
|
||||
Subject: [PATCH] kpartx: free loop device after listing partitions
|
||||
|
||||
If "kpartx -l" is run on a file that doesn't already have a loop device
|
||||
associated with it, it will create a loop device to run the command.
|
||||
Starting with da59d15c6 ("Fix loopback file with kpartx -av"), it will
|
||||
not free the loop device when exitting. This is because it checks if the
|
||||
the file it stat()ed is a regular file, before freeing the loop device.
|
||||
However, after da59d15c6, stat() is rerun on the loop device itself, so
|
||||
the check fails. There is no need to check this, if loopcreated is
|
||||
true, then the file will be a kpartx created loop device, and should be
|
||||
freed.
|
||||
|
||||
Also, keep kpartx from printing that the loop device has been removed
|
||||
at normal verbosity.
|
||||
|
||||
Fixes: da59d15c6 ("Fix loopback file with kpartx -av")
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
kpartx/kpartx.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
|
||||
index 653ce0c8..a337a07b 100644
|
||||
--- a/kpartx/kpartx.c
|
||||
+++ b/kpartx/kpartx.c
|
||||
@@ -407,7 +407,7 @@ main(int argc, char **argv){
|
||||
fprintf(stderr, "can't del loop : %s\n",
|
||||
loopdev);
|
||||
r = 1;
|
||||
- } else
|
||||
+ } else if (verbose)
|
||||
fprintf(stderr, "loop deleted : %s\n", loopdev);
|
||||
}
|
||||
goto end;
|
||||
@@ -649,16 +649,17 @@ main(int argc, char **argv){
|
||||
if (n > 0)
|
||||
break;
|
||||
}
|
||||
- if (what == LIST && loopcreated && S_ISREG (buf.st_mode)) {
|
||||
+ if (what == LIST && loopcreated) {
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
if (del_loop(device)) {
|
||||
if (verbose)
|
||||
- printf("can't del loop : %s\n",
|
||||
+ fprintf(stderr, "can't del loop : %s\n",
|
||||
device);
|
||||
exit(1);
|
||||
}
|
||||
- printf("loop deleted : %s\n", device);
|
||||
+ if (verbose)
|
||||
+ fprintf(stderr, "loop deleted : %s\n", device);
|
||||
}
|
||||
|
||||
end:
|
||||
--
|
||||
2.17.2
|
||||
|
134
SOURCES/0061-RH-fix-find_multipaths-in-mpathconf.patch
Normal file
134
SOURCES/0061-RH-fix-find_multipaths-in-mpathconf.patch
Normal file
@ -0,0 +1,134 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
Date: Wed, 10 Feb 2021 15:42:42 -0600
|
||||
Subject: [PATCH] RH: fix find_multipaths in mpathconf
|
||||
|
||||
mpathconf wasn't correctly dealing with the new rhel-8 values for
|
||||
find_multipaths
|
||||
|
||||
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||
---
|
||||
multipath/mpathconf | 38 +++++++++++++++++++-------------------
|
||||
multipath/mpathconf.8 | 14 +++++++-------
|
||||
2 files changed, 26 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/multipath/mpathconf b/multipath/mpathconf
|
||||
index f34003c9..2f4f3eaf 100644
|
||||
--- a/multipath/mpathconf
|
||||
+++ b/multipath/mpathconf
|
||||
@@ -54,7 +54,7 @@ function usage
|
||||
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 y): --find_multipaths <y|n>"
|
||||
+ echo "Set find_multipaths (Default y): --find_multipaths <yes|no|strict|greedy|smart>"
|
||||
echo "Set default property blacklist (Default y): --property_blacklist <y|n>"
|
||||
echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign <y|n>"
|
||||
echo "Load the dm-multipath modules on enable (Default y): --with_module <y|n>"
|
||||
@@ -224,8 +224,12 @@ function validate_args
|
||||
echo "--user_friendly_names must be either 'y' or 'n'"
|
||||
exit 1
|
||||
fi
|
||||
- if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then
|
||||
- echo "--find_multipaths must be either 'y' or 'n'"
|
||||
+ if [ "$FIND" = "y" ]; then
|
||||
+ FIND="yes"
|
||||
+ elif [ "$FIND" = "n" ]; then
|
||||
+ 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
|
||||
@@ -327,10 +331,11 @@ if [ "$HAVE_BLACKLIST" = "1" ]; then
|
||||
fi
|
||||
|
||||
if [ "$HAVE_DEFAULTS" = "1" ]; then
|
||||
- if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then
|
||||
- HAVE_FIND=1
|
||||
- elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then
|
||||
- HAVE_FIND=0
|
||||
+ HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p`
|
||||
+ if [ "$HAVE_FIND" = "1" ]; then
|
||||
+ HAVE_FIND="yes"
|
||||
+ elif [ "$HAVE_FIND" = "0" ]; then
|
||||
+ HAVE_FIND="no"
|
||||
fi
|
||||
if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then
|
||||
HAVE_FRIENDLY=1
|
||||
@@ -360,10 +365,10 @@ if [ -n "$SHOW_STATUS" ]; then
|
||||
else
|
||||
echo "multipath is disabled"
|
||||
fi
|
||||
- if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then
|
||||
- echo "find_multipaths is disabled"
|
||||
+ if [ -z "$HAVE_FIND" ]; then
|
||||
+ echo "find_multipaths is no"
|
||||
else
|
||||
- echo "find_multipaths is enabled"
|
||||
+ echo "find_multipaths is $HAVE_FIND"
|
||||
fi
|
||||
if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then
|
||||
echo "user_friendly_names is disabled"
|
||||
@@ -455,19 +460,14 @@ elif [ "$ENABLE" = 0 ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
-if [ "$FIND" = "n" ]; then
|
||||
- if [ "$HAVE_FIND" = 1 ]; then
|
||||
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE
|
||||
- CHANGED_CONFIG=1
|
||||
- fi
|
||||
-elif [ "$FIND" = "y" ]; then
|
||||
+if [ -n "$FIND" ]; then
|
||||
if [ -z "$HAVE_FIND" ]; then
|
||||
sed -i '/^defaults[[:space:]]*{/ a\
|
||||
- find_multipaths yes
|
||||
+ find_multipaths '"$FIND"'
|
||||
' $TMPFILE
|
||||
CHANGED_CONFIG=1
|
||||
- elif [ "$HAVE_FIND" = 0 ]; then
|
||||
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE
|
||||
+ elif [ "$FIND" != "$HAVE_FIND" ]; then
|
||||
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE
|
||||
CHANGED_CONFIG=1
|
||||
fi
|
||||
fi
|
||||
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
|
||||
index b82961d6..83515eb4 100644
|
||||
--- a/multipath/mpathconf.8
|
||||
+++ b/multipath/mpathconf.8
|
||||
@@ -38,9 +38,9 @@ If
|
||||
already exists, mpathconf will edit it. If it does not exist, mpathconf will
|
||||
create a default file with
|
||||
.B user_friendly_names
|
||||
-and
|
||||
+set and
|
||||
.B find_multipaths
|
||||
-set. To disable these, use the
|
||||
+set to \fByes\fP. To disable these, use the
|
||||
.B --user_friendly_names n
|
||||
and
|
||||
.B --find_multipaths n
|
||||
@@ -77,13 +77,13 @@ to the
|
||||
defaults section. If set to \fBn\fP, this removes the line, if present. This
|
||||
command can be used along with any other command.
|
||||
.TP
|
||||
-.B --find_multipaths\fP { \fBy\fP | \fBn\fP }
|
||||
-If set to \fBy\fP, this adds the line
|
||||
-.B find_multipaths yes
|
||||
+.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
|
||||
.B /etc/multipath.conf
|
||||
-defaults section. If set to \fBn\fP, this removes the line, if present. This
|
||||
-command can be used along with any other command.
|
||||
+defaults section. This command can be used along with any other command.
|
||||
+\fBy\fP and \fBn\fP can be used instead of \fByes\fP and \fBno\fP.
|
||||
.TP
|
||||
.B --property_blacklist \fP { \fBy\fP | \fBn\fP }
|
||||
If set to \fBy\fP, this adds the line
|
||||
--
|
||||
2.17.2
|
||||
|
@ -1,7 +1,7 @@
|
||||
Summary: Tools to manage multipath devices using device-mapper
|
||||
Name: device-mapper-multipath
|
||||
Version: 0.8.4
|
||||
Release: 2%{?dist}
|
||||
Release: 9%{?dist}
|
||||
License: GPLv2
|
||||
Group: System Environment/Base
|
||||
URL: http://christophe.varoqui.free.fr/
|
||||
@ -34,6 +34,44 @@ Patch00020: 0020-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
|
||||
Patch00021: 0021-libmultipath-remove-_blacklist_exceptions-functions.patch
|
||||
Patch00022: 0022-libmultipath-fix-parser-issue-with-comments-in-strin.patch
|
||||
Patch00023: 0023-libmultipath-invert-regexes-that-start-with-exclamat.patch
|
||||
Patch00024: 0024-libmultipath-make-dm_get_map-status-return-codes-sym.patch
|
||||
Patch00025: 0025-multipathd-fix-check_path-errors-with-removed-map.patch
|
||||
Patch00026: 0026-libmultipath-make-dm_flush_maps-only-return-0-on-suc.patch
|
||||
Patch00027: 0027-multipathd-add-del-maps-multipathd-command.patch
|
||||
Patch00028: 0028-multipath-make-flushing-maps-work-like-other-command.patch
|
||||
Patch00029: 0029-multipath-delegate-flushing-maps-to-multipathd.patch
|
||||
Patch00030: 0030-multipath-add-option-to-skip-multipathd-delegation.patch
|
||||
Patch00031: 0031-libmultipath-fix-sysfs-dev_loss_tmo-parsing.patch
|
||||
Patch00032: 0032-kpartx-read-devices-with-direct-IO.patch
|
||||
Patch00033: 0033-kpartx-handle-alternate-bsd-disklabel-location.patch
|
||||
Patch00034: 0034-libmultipath-fix-checker-detection-for-nvme-devices.patch
|
||||
Patch00035: 0035-Makefile.inc-trim-extra-information-from-systemd-ver.patch
|
||||
Patch00036: 0036-kpartx-fix-Wsign-compare-error.patch
|
||||
Patch00037: 0037-libmultipath-count-pending-paths-as-active-on-loads.patch
|
||||
Patch00038: 0038-multipath-deal-with-failures-flushing-maps.patch
|
||||
Patch00039: 0039-libmultipath-factor-out-code-to-get-vpd-page-data.patch
|
||||
Patch00040: 0040-libmultipath-limit-reading-0xc9-vpd-page.patch
|
||||
Patch00041: 0041-libmultipath-add-device-to-hwtable.c.patch
|
||||
Patch00042: 0042-libmultipath-move-fast_io_fail-defines-to-structs.h.patch
|
||||
Patch00043: 0043-libmultipath-add-eh_deadline-multipath.conf-paramete.patch
|
||||
Patch00044: 0044-libmultipath-don-t-dlclose-tur-checker-DSO.patch
|
||||
Patch00045: 0045-libmultipath-warn-about-missing-braces-at-end-of-mul.patch
|
||||
Patch00046: 0046-libmultipath-ignore-multipaths-sections-without-wwid.patch
|
||||
Patch00047: 0047-tests-fix-missing-priority-blacklist-test.patch
|
||||
Patch00048: 0048-mpathpersist-Fix-Register-and-Ignore-with-0x00-SARK.patch
|
||||
Patch00049: 0049-mpathpersist-update-prkeys-file-on-changing-registra.patch
|
||||
Patch00050: 0050-multipathd-Fix-multipathd-stopping-on-shutdown.patch
|
||||
Patch00051: 0051-multipath.conf.5-Improve-checker_timeout-description.patch
|
||||
Patch00052: 0052-libmultipath-check-for-null-wwid-before-strcmp.patch
|
||||
Patch00053: 0053-libmultipath-make-find_err_path_by_dev-static.patch
|
||||
Patch00054: 0054-multipathd-avoid-io_err_stat-crash-during-shutdown.patch
|
||||
Patch00055: 0055-multipathd-avoid-io_err_stat-ABBA-deadlock.patch
|
||||
Patch00056: 0056-multipathd-use-get_monotonic_time-in-io_err_stat-cod.patch
|
||||
Patch00057: 0057-multipathd-combine-free_io_err_stat_path-and-destroy.patch
|
||||
Patch00058: 0058-multipathd-cleanup-logging-for-marginal-paths.patch
|
||||
Patch00059: 0059-libmpathpersist-fix-thread-safety-of-default-functio.patch
|
||||
Patch00060: 0060-kpartx-free-loop-device-after-listing-partitions.patch
|
||||
Patch00061: 0061-RH-fix-find_multipaths-in-mpathconf.patch
|
||||
|
||||
# runtime
|
||||
Requires: %{name}-libs = %{version}-%{release}
|
||||
@ -235,6 +273,101 @@ fi
|
||||
%{_pkgconfdir}/libdmmp.pc
|
||||
|
||||
%changelog
|
||||
* Wed Feb 10 2021 Benjamin Marzinski <bmarzins@redhat.com> 0.8.4-9
|
||||
- Add 0060-kpartx-free-loop-device-after-listing-partitions.patch
|
||||
* Fixes bz #1925490
|
||||
- Add 0061-RH-fix-find_multipaths-in-mpathconf.patch
|
||||
* Fixes bz #1921651
|
||||
- Resolves: bz #1921651, #1925490
|
||||
|
||||
* Wed Jan 27 2021 Benjamin Marzinski <bmarzins@redhat.com> 0.8.4-7
|
||||
- Add 0052-libmultipath-check-for-null-wwid-before-strcmp.patch
|
||||
* Missing part of fix for bz #1897815
|
||||
- Add 0053-libmultipath-make-find_err_path_by_dev-static.patch
|
||||
- Add 0054-multipathd-avoid-io_err_stat-crash-during-shutdown.patch
|
||||
- Add 0055-multipathd-avoid-io_err_stat-ABBA-deadlock.patch
|
||||
- Add 0056-multipathd-use-get_monotonic_time-in-io_err_stat-cod.patch
|
||||
- Add 0057-multipathd-combine-free_io_err_stat_path-and-destroy.patch
|
||||
- Add 0058-multipathd-cleanup-logging-for-marginal-paths.patch
|
||||
* The above 6 patches fix bz #1920795
|
||||
- Add 0059-libmpathpersist-fix-thread-safety-of-default-functio.patch
|
||||
* Fixes bz #1913549
|
||||
- Resolves: bz #1897815, #1913549, #1920795
|
||||
|
||||
* Tue Dec 15 2020 Benjamin Marzinski <bmarzins@redhat.com> 0.8.4-6
|
||||
- Add 0050-multipathd-Fix-multipathd-stopping-on-shutdown.patch
|
||||
* Fixes bz #1892496
|
||||
- Add 0051-multipath.conf.5-Improve-checker_timeout-description.patch
|
||||
* Fixes bz #1906073
|
||||
- Resolves: bz #1892496, #1906073
|
||||
|
||||
* Tue Nov 10 2020 Benjamin Marzinski <bmarzins@redhat.com> 0.8.4-6
|
||||
- Add 0039-libmultipath-factor-out-code-to-get-vpd-page-data.patch
|
||||
- Add 0040-libmultipath-limit-reading-0xc9-vpd-page.patch
|
||||
* Only check for rdac support on configured devices, or devices where
|
||||
vpd page 0x00 indicates support for vpd page 0xc9
|
||||
* Fixes bz #1877415
|
||||
- Add 0041-libmultipath-add-device-to-hwtable.c.patch
|
||||
* Add support for Fujitsu Eternus AB/HB
|
||||
* Fixes bz #1857429
|
||||
- Add 0042-libmultipath-move-fast_io_fail-defines-to-structs.h.patch
|
||||
- Add 0043-libmultipath-add-eh_deadline-multipath.conf-paramete.patch
|
||||
* Fixes bz #1819897
|
||||
- Add 0044-libmultipath-don-t-dlclose-tur-checker-DSO.patch
|
||||
* Fixes bz #1875384
|
||||
- Add 0045-libmultipath-warn-about-missing-braces-at-end-of-mul.patch
|
||||
* Fixes bz #1897530
|
||||
- Add 0046-libmultipath-ignore-multipaths-sections-without-wwid.patch
|
||||
* Fixes bz #1897815
|
||||
- Add 0047-tests-fix-missing-priority-blacklist-test.patch
|
||||
- Add 0048-mpathpersist-Fix-Register-and-Ignore-with-0x00-SARK.patch
|
||||
* Make mpathpersist Register and Ignore command clear the registration
|
||||
with a 0x0 SARK, like sg_persist does.
|
||||
* Fixes bz #1894103
|
||||
- Add 0049-mpathpersist-update-prkeys-file-on-changing-registra.patch
|
||||
* Fixes bz #1900522
|
||||
* The above 11 patches have all been submitted upstream
|
||||
- Resolves: bz #1819897, #1857429, #1875384, #1877415, #1894103, #1897530
|
||||
- Resolves: bz #1897815, #1900522
|
||||
|
||||
* Mon Jul 13 2020 Benjamin Marzinski <bmarzins@redhat.com> 0.8.4-5
|
||||
- Add 0038-multipath-deal-with-failures-flushing-maps.patch
|
||||
* Don't print "fail" if multipath needs to failback to removing
|
||||
a device itself.
|
||||
* Fixes bz #1845875
|
||||
- Modify multipath_conf_syntax CI test
|
||||
* It started failing because "multpath -F" can now start multipathd
|
||||
via the socket, and the test expected multipathd to not be running
|
||||
- Resolves: bz #1845875
|
||||
|
||||
* Fri Jul 10 2020 Benjamin Marzinski <bmarzins@redhat.com> 0.8.4-4
|
||||
- Add 0037-libmultipath-count-pending-paths-as-active-on-loads.patch
|
||||
* make udev treat the device as having paths, so it will run kpartx
|
||||
* Fixes bz #1846866
|
||||
- Resolves: bz #1846866
|
||||
|
||||
* Mon Jul 6 2020 Benjamin Marzinski <bmarzins@redhat.com> 0.8.4-3
|
||||
- Add 0024-libmultipath-make-dm_get_map-status-return-codes-sym.patch
|
||||
- Add 0025-multipathd-fix-check_path-errors-with-removed-map.patch
|
||||
- Add 0026-libmultipath-make-dm_flush_maps-only-return-0-on-suc.patch
|
||||
- Add 0027-multipathd-add-del-maps-multipathd-command.patch
|
||||
- Add 0028-multipath-make-flushing-maps-work-like-other-command.patch
|
||||
- Add 0029-multipath-delegate-flushing-maps-to-multipathd.patch
|
||||
- Add 0030-multipath-add-option-to-skip-multipathd-delegation.patch
|
||||
* The above 7 patches fix bz #1845875. Multipath now attempts to
|
||||
delegate device removal to multipathd, and multipathd handles
|
||||
external device removal better.
|
||||
- Add 0031-libmultipath-fix-sysfs-dev_loss_tmo-parsing.patch
|
||||
* Fixes bz #1852843
|
||||
- Add 0032-kpartx-read-devices-with-direct-IO.patch
|
||||
* Fixes bz #1814858
|
||||
- Add 0033-kpartx-handle-alternate-bsd-disklabel-location.patch
|
||||
- Add 0034-libmultipath-fix-checker-detection-for-nvme-devices.patch
|
||||
* fixes bz #1845915
|
||||
- Add 0035-Makefile.inc-trim-extra-information-from-systemd-ver.patch
|
||||
- Add 0036-kpartx-fix-Wsign-compare-error.patch
|
||||
- Resolves: bz #1814858, #1845875, #1845915, #1852843
|
||||
|
||||
* Tue Jun 9 2020 Benjamin Marzinski <bmarzins@redhat.com> 0.8.4-2
|
||||
- Add 0021-libmultipath-remove-_blacklist_exceptions-functions.patch
|
||||
- Add 0022-libmultipath-fix-parser-issue-with-comments-in-strin.patch
|
||||
@ -482,7 +615,7 @@ fi
|
||||
- Rename files
|
||||
* Previous patches 0007-0014 are now patches 0008-0015
|
||||
|
||||
* Tue Apr 02 2018 Björn Esser <besser82@fedoraproject.org> - 0.7.6-1.git1cb704b
|
||||
* Mon Apr 02 2018 Benjamin Marzinski <bmarzins@redhat.com> - 0.7.6-1.git1cb704b
|
||||
- Update Source to the latest upstream commit
|
||||
* Previous patches 0001-0014 are included in this commit
|
||||
* Previous patches 0015-0022 are now patches 0007-0014
|
||||
|
Loading…
Reference in New Issue
Block a user