RHEL 9.0.0 Alpha bootstrap
The content of this branch was automatically imported from Fedora ELN with the following as its source: https://src.fedoraproject.org/rpms/device-mapper-multipath#2cf40b2f98808e3533e915c0a204b885d9da5e43
This commit is contained in:
parent
295eb4a3cc
commit
de5fe16817
22
.gitignore
vendored
22
.gitignore
vendored
@ -0,0 +1,22 @@
|
|||||||
|
multipath-tools-091027.tar.gz
|
||||||
|
/multipath-tools-120123.tgz
|
||||||
|
/multipath-tools-120613.tgz
|
||||||
|
/multipath-tools-120821.tgz
|
||||||
|
/multipath-tools-130222.tgz
|
||||||
|
/multipath-tools-f21166a.tgz
|
||||||
|
/multipath.conf
|
||||||
|
/multipath-tools-git847cc43.tgz
|
||||||
|
/multipath-tools-0.7.3.tgz
|
||||||
|
/multipath-tools-07e7bd5.tgz
|
||||||
|
/multipath-tools-1cb704b.tgz
|
||||||
|
/multipath-tools-0.7.7.tgz
|
||||||
|
/multipath-tools-ef6d98b.tgz
|
||||||
|
/multipath-tools-1a8625a.tgz
|
||||||
|
/multipath-tools-b80318b.tgz
|
||||||
|
/multipath-tools-0.7.8.tgz
|
||||||
|
/multipath-tools-0.7.9.tgz
|
||||||
|
/multipath-tools-17a6101.tgz
|
||||||
|
/multipath-tools-2df6110.tgz
|
||||||
|
/multipath-tools-0.8.0.tgz
|
||||||
|
/multipath-tools-0.8.2.tgz
|
||||||
|
/multipath-tools-0.8.4.tgz
|
@ -0,0 +1,35 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Fri, 6 Mar 2020 21:50:30 +0100
|
||||||
|
Subject: [PATCH] libmpathpersist: limit PRIN allocation length to 8192 bytes
|
||||||
|
|
||||||
|
Some targets (notably the qemu-pr-helper) don't support PERSISTENT
|
||||||
|
RESERVE IN commands with more than 8192 bytes allocation length.
|
||||||
|
While I have found no explicit requirement in the SCSI specs that
|
||||||
|
the allocation lengh may not exceed 8k, an 8k limit is also enforced
|
||||||
|
by sg_persist(8), and actually by mpathpersist itself for the
|
||||||
|
--allocation-length option, but not for the auto-determined length.
|
||||||
|
|
||||||
|
Fix that.
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_pr_ioctl.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_pr_ioctl.c b/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
index 74b26b0c..1a28cba7 100644
|
||||||
|
--- a/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
+++ b/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
@@ -543,5 +543,7 @@ int get_prin_length(int rq_servact)
|
||||||
|
mx_resp_len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
+ if (mx_resp_len > MPATH_MAX_PARAM_LEN)
|
||||||
|
+ mx_resp_len = MPATH_MAX_PARAM_LEN;
|
||||||
|
return mx_resp_len;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,93 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Fri, 6 Mar 2020 23:33:04 +0100
|
||||||
|
Subject: [PATCH] libmpathpersist: format_transportids(): avoid PROUT overflow
|
||||||
|
|
||||||
|
This limits the PERSISTENT RESERVE OUT data size to max. 8192 bytes.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_pr_ioctl.c | 31 +++++++++++++++++++++++++++++--
|
||||||
|
1 file changed, 29 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_pr_ioctl.c b/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
index 1a28cba7..c78e8000 100644
|
||||||
|
--- a/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
+++ b/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
@@ -1,5 +1,6 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
@@ -138,38 +139,64 @@ retry :
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Helper macro to avoid overflow of prout_param_descriptor in
|
||||||
|
+ * format_transportids(). Data must not be written past
|
||||||
|
+ * MPATH_MAX_PARAM_LEN bytes from struct prout_param_descriptor.
|
||||||
|
+ */
|
||||||
|
+#define check_overflow(ofs, n, start, label) \
|
||||||
|
+ do { \
|
||||||
|
+ if ((ofs) + (n) + \
|
||||||
|
+ offsetof(struct prout_param_descriptor, private_buffer) \
|
||||||
|
+ > MPATH_MAX_PARAM_LEN) \
|
||||||
|
+ { \
|
||||||
|
+ (ofs) = (start); \
|
||||||
|
+ goto label; \
|
||||||
|
+ } \
|
||||||
|
+ } while(0)
|
||||||
|
+
|
||||||
|
uint32_t format_transportids(struct prout_param_descriptor *paramp)
|
||||||
|
{
|
||||||
|
unsigned int i = 0, len;
|
||||||
|
uint32_t buff_offset = 4;
|
||||||
|
- memset(paramp->private_buffer, 0, MPATH_MAX_PARAM_LEN);
|
||||||
|
+ memset(paramp->private_buffer, 0, sizeof(paramp->private_buffer));
|
||||||
|
for (i=0; i < paramp->num_transportid; i++ )
|
||||||
|
{
|
||||||
|
+ uint32_t start_offset = buff_offset;
|
||||||
|
+
|
||||||
|
+ check_overflow(buff_offset, 1, start_offset, end_loop);
|
||||||
|
paramp->private_buffer[buff_offset] = (uint8_t)((paramp->trnptid_list[i]->format_code & 0xff)|
|
||||||
|
(paramp->trnptid_list[i]->protocol_id & 0xff));
|
||||||
|
buff_offset += 1;
|
||||||
|
switch(paramp->trnptid_list[i]->protocol_id)
|
||||||
|
{
|
||||||
|
case MPATH_PROTOCOL_ID_FC:
|
||||||
|
+ check_overflow(buff_offset, 7 + 8 + 8,
|
||||||
|
+ start_offset, end_loop);
|
||||||
|
buff_offset += 7;
|
||||||
|
memcpy(¶mp->private_buffer[buff_offset], ¶mp->trnptid_list[i]->n_port_name, 8);
|
||||||
|
buff_offset +=8 ;
|
||||||
|
buff_offset +=8 ;
|
||||||
|
break;
|
||||||
|
case MPATH_PROTOCOL_ID_SAS:
|
||||||
|
+ check_overflow(buff_offset, 3 + 12,
|
||||||
|
+ start_offset, end_loop);
|
||||||
|
buff_offset += 3;
|
||||||
|
memcpy(¶mp->private_buffer[buff_offset], ¶mp->trnptid_list[i]->sas_address, 8);
|
||||||
|
buff_offset += 12;
|
||||||
|
break;
|
||||||
|
case MPATH_PROTOCOL_ID_ISCSI:
|
||||||
|
- buff_offset += 1;
|
||||||
|
len = (paramp->trnptid_list[i]->iscsi_name[1] & 0xff)+2;
|
||||||
|
+ check_overflow(buff_offset, 1 + len,
|
||||||
|
+ start_offset, end_loop);
|
||||||
|
+ buff_offset += 1;
|
||||||
|
memcpy(¶mp->private_buffer[buff_offset], ¶mp->trnptid_list[i]->iscsi_name,len);
|
||||||
|
buff_offset += len ;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
+end_loop:
|
||||||
|
buff_offset -= 4;
|
||||||
|
paramp->private_buffer[0] = (unsigned char)((buff_offset >> 24) & 0xff);
|
||||||
|
paramp->private_buffer[1] = (unsigned char)((buff_offset >> 16) & 0xff);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Fri, 6 Mar 2020 23:46:47 +0100
|
||||||
|
Subject: [PATCH] libmpathpersist: mpath_format_readfullstatus(): use real
|
||||||
|
buffer size
|
||||||
|
|
||||||
|
This changes no semantics, but it will allow changing the size of
|
||||||
|
prin_readfd.private_buffer in a follow-up patch.
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_pr_ioctl.c | 12 ++++++++----
|
||||||
|
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_pr_ioctl.c b/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
index c78e8000..fadc9e10 100644
|
||||||
|
--- a/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
+++ b/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
@@ -238,6 +238,8 @@ static void mpath_format_readfullstatus(struct prin_resp *pr_buff)
|
||||||
|
uint32_t additional_length, k, tid_len_len = 0;
|
||||||
|
char tempbuff[MPATH_MAX_PARAM_LEN];
|
||||||
|
struct prin_fulldescr fdesc;
|
||||||
|
+ static const int pbuf_size =
|
||||||
|
+ sizeof(pr_buff->prin_descriptor.prin_readfd.private_buffer);
|
||||||
|
|
||||||
|
convert_be32_to_cpu(&pr_buff->prin_descriptor.prin_readfd.prgeneration);
|
||||||
|
convert_be32_to_cpu(&pr_buff->prin_descriptor.prin_readfd.number_of_descriptor);
|
||||||
|
@@ -249,16 +251,18 @@ static void mpath_format_readfullstatus(struct prin_resp *pr_buff)
|
||||||
|
}
|
||||||
|
|
||||||
|
additional_length = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
|
||||||
|
- if (additional_length > MPATH_MAX_PARAM_LEN) {
|
||||||
|
+ if (additional_length > pbuf_size) {
|
||||||
|
condlog(3, "PRIN length %u exceeds max length %d", additional_length,
|
||||||
|
- MPATH_MAX_PARAM_LEN);
|
||||||
|
+ pbuf_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&fdesc, 0, sizeof(struct prin_fulldescr));
|
||||||
|
|
||||||
|
- memcpy( tempbuff, pr_buff->prin_descriptor.prin_readfd.private_buffer,MPATH_MAX_PARAM_LEN );
|
||||||
|
- memset(&pr_buff->prin_descriptor.prin_readfd.private_buffer, 0, MPATH_MAX_PARAM_LEN);
|
||||||
|
+ memcpy( tempbuff, pr_buff->prin_descriptor.prin_readfd.private_buffer,
|
||||||
|
+ pbuf_size);
|
||||||
|
+ memset(&pr_buff->prin_descriptor.prin_readfd.private_buffer, 0,
|
||||||
|
+ pbuf_size);
|
||||||
|
|
||||||
|
p =(unsigned char *)tempbuff;
|
||||||
|
ppbuff = (char *)pr_buff->prin_descriptor.prin_readfd.private_buffer;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
42
0004-libmultipath-assign-variable-to-make-gcc-happy.patch
Normal file
42
0004-libmultipath-assign-variable-to-make-gcc-happy.patch
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 25 Mar 2020 23:22:46 -0500
|
||||||
|
Subject: [PATCH] libmultipath: assign variable to make gcc happy
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
There is nothing wrong with is_queueing not being set at the start
|
||||||
|
of __set_no_path_retry(), it will always get set before it is accessed,
|
||||||
|
but gcc 8.2.1 is failing with
|
||||||
|
|
||||||
|
structs_vec.c: In function ‘__set_no_path_retry’:
|
||||||
|
structs_vec.c:339:7: error: ‘is_queueing’ may be used uninitialized in
|
||||||
|
this function [-Werror=maybe-uninitialized]
|
||||||
|
bool is_queueing;
|
||||||
|
^~~~~~~~~~~
|
||||||
|
|
||||||
|
so, assign a value to make it happy.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/structs_vec.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
||||||
|
index 3dbbaa0f..077f2e42 100644
|
||||||
|
--- a/libmultipath/structs_vec.c
|
||||||
|
+++ b/libmultipath/structs_vec.c
|
||||||
|
@@ -336,7 +336,7 @@ static void leave_recovery_mode(struct multipath *mpp)
|
||||||
|
|
||||||
|
void __set_no_path_retry(struct multipath *mpp, bool check_features)
|
||||||
|
{
|
||||||
|
- bool is_queueing;
|
||||||
|
+ bool is_queueing = false; /* assign a value to make gcc happy */
|
||||||
|
|
||||||
|
check_features = check_features && mpp->features != NULL;
|
||||||
|
if (check_features)
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
66
0005-libmutipath-don-t-close-fd-on-dm_lib_release.patch
Normal file
66
0005-libmutipath-don-t-close-fd-on-dm_lib_release.patch
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 25 Mar 2020 23:22:47 -0500
|
||||||
|
Subject: [PATCH] libmutipath: don't close fd on dm_lib_release
|
||||||
|
|
||||||
|
If dm_hold_control_open() isn't set, when dm_lib_release() is called, it
|
||||||
|
will close the control fd. The control fd will get re-opened on the next
|
||||||
|
dm_task_run() call, but if there is a dm_task_run() call already
|
||||||
|
in progress in another thread, it can fail. Since many of the
|
||||||
|
device-mapper callouts happen with the vecs lock held, this wasn't too
|
||||||
|
noticeable, but there is code that calls dm_task_run() without the
|
||||||
|
vecs lock held, notably the dmevent waiter code.
|
||||||
|
|
||||||
|
Since, as Martin pointed out, dm_hold_control_open() hasn't always
|
||||||
|
existed in libdevmapper, check if it's supported on compilation,
|
||||||
|
and update the version requirements if so.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/Makefile | 4 ++++
|
||||||
|
libmultipath/devmapper.c | 7 ++++++-
|
||||||
|
2 files changed, 10 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
|
||||||
|
index e5651e49..ad690a49 100644
|
||||||
|
--- a/libmultipath/Makefile
|
||||||
|
+++ b/libmultipath/Makefile
|
||||||
|
@@ -36,6 +36,10 @@ ifneq ($(call check_func,dm_task_deferred_remove,/usr/include/libdevmapper.h),0)
|
||||||
|
CFLAGS += -DLIBDM_API_DEFERRED
|
||||||
|
endif
|
||||||
|
|
||||||
|
+ifneq ($(call check_func,dm_hold_control_dev,/usr/include/libdevmapper.h),0)
|
||||||
|
+ CFLAGS += -DLIBDM_API_HOLD_CONTROL
|
||||||
|
+endif
|
||||||
|
+
|
||||||
|
OBJS = memory.o parser.o vector.o devmapper.o callout.o \
|
||||||
|
hwtable.o blacklist.o util.o dmparser.o config.o \
|
||||||
|
structs.o discovery.o propsel.o dict.o \
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index bed8ddc6..13a1cf53 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -108,7 +108,9 @@ dm_lib_prereq (void)
|
||||||
|
{
|
||||||
|
char version[64];
|
||||||
|
int v[3];
|
||||||
|
-#if defined(LIBDM_API_DEFERRED)
|
||||||
|
+#if defined(LIBDM_API_HOLD_CONTROL)
|
||||||
|
+ int minv[3] = {1, 2, 111};
|
||||||
|
+#elif defined(LIBDM_API_DEFERRED)
|
||||||
|
int minv[3] = {1, 2, 89};
|
||||||
|
#elif defined(DM_SUBSYSTEM_UDEV_FLAG0)
|
||||||
|
int minv[3] = {1, 2, 82};
|
||||||
|
@@ -254,6 +256,9 @@ void libmp_dm_init(void)
|
||||||
|
memcpy(conf->version, version, sizeof(version));
|
||||||
|
put_multipath_config(conf);
|
||||||
|
dm_init(verbosity);
|
||||||
|
+#ifdef LIBDM_API_HOLD_CONTROL
|
||||||
|
+ dm_hold_control_dev(1);
|
||||||
|
+#endif
|
||||||
|
dm_udev_set_sync_support(libmp_dm_udev_sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 25 Mar 2020 23:22:48 -0500
|
||||||
|
Subject: [PATCH] libmultipath: allow force reload with no active paths
|
||||||
|
|
||||||
|
If the partition information has changed on multipath devices (say,
|
||||||
|
because it was updated on another node that has access to the same
|
||||||
|
storage), users expect that running "multipathd reconfigure" will update
|
||||||
|
that. However, if the checkers for the multipath device are pending for
|
||||||
|
too long when the the device is reconfigured, multipathd will give up
|
||||||
|
waiting for them, and refuse to reload the device, since there are no
|
||||||
|
active paths. This means that no kpartx update will be triggered.
|
||||||
|
|
||||||
|
Multipath is fully capable of reloading a multipath device that has no
|
||||||
|
active paths. This has been possible for years. If multipath is supposed
|
||||||
|
to reload the device, it should do so, even if there are no active paths.
|
||||||
|
|
||||||
|
Generally, when multipath is force reloaded, kpartx will be updated.
|
||||||
|
However when a device is reloaded with no paths, the udev rules won't
|
||||||
|
run kpartx. But they also weren't running kpartx when the first valid
|
||||||
|
path appeared, even though the dm activation rules get run in this case.
|
||||||
|
This changes 11-dm-mpath.rules to run kpartx when a device goes from no
|
||||||
|
usable paths to having usable paths.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/configure.c | 6 ------
|
||||||
|
multipath/11-dm-mpath.rules | 2 +-
|
||||||
|
2 files changed, 1 insertion(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||||||
|
index c95848a0..96c79610 100644
|
||||||
|
--- a/libmultipath/configure.c
|
||||||
|
+++ b/libmultipath/configure.c
|
||||||
|
@@ -710,12 +710,6 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (pathcount(mpp, PATH_UP) == 0) {
|
||||||
|
- mpp->action = ACT_IMPOSSIBLE;
|
||||||
|
- condlog(3, "%s: set ACT_IMPOSSIBLE (no usable path)",
|
||||||
|
- mpp->alias);
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
if (force_reload) {
|
||||||
|
mpp->force_udev_reload = 1;
|
||||||
|
mpp->action = ACT_RELOAD;
|
||||||
|
diff --git a/multipath/11-dm-mpath.rules b/multipath/11-dm-mpath.rules
|
||||||
|
index 07320a14..cd522e8c 100644
|
||||||
|
--- a/multipath/11-dm-mpath.rules
|
||||||
|
+++ b/multipath/11-dm-mpath.rules
|
||||||
|
@@ -75,7 +75,7 @@ ENV{MPATH_DEVICE_READY}=="0", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
|
||||||
|
ENV{MPATH_DEVICE_READY}!="0", ENV{.MPATH_DEVICE_READY_OLD}=="0",\
|
||||||
|
ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}",\
|
||||||
|
ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="",\
|
||||||
|
- ENV{DM_ACTIVATION}="1"
|
||||||
|
+ ENV{DM_ACTIVATION}="1", ENV{MPATH_UNCHANGED}="0"
|
||||||
|
|
||||||
|
# The code to check multipath state ends here. We need to set
|
||||||
|
# properties and symlinks regardless whether the map is usable or
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Fri, 3 Apr 2020 13:03:01 +0200
|
||||||
|
Subject: [PATCH] kpartx.rules: honor DM_UDEV_DISABLE_OTHER_RULES_FLAG
|
||||||
|
|
||||||
|
10-dm.rules sets DM_UDEV_DISABLE_OTHER_RULES_FLAG for spurious
|
||||||
|
events that should be ignored by other layers. This means devices
|
||||||
|
with DISK_RO set, and devices that have never been set up properly
|
||||||
|
by device-mapper before. This flag should be respected by kpartx.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
kpartx/kpartx.rules | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
|
||||||
|
index 8f990494..f1bf31ca 100644
|
||||||
|
--- a/kpartx/kpartx.rules
|
||||||
|
+++ b/kpartx/kpartx.rules
|
||||||
|
@@ -7,6 +7,7 @@
|
||||||
|
KERNEL!="dm-*", GOTO="kpartx_end"
|
||||||
|
ACTION!="add|change", GOTO="kpartx_end"
|
||||||
|
ENV{DM_UUID}!="?*", GOTO="kpartx_end"
|
||||||
|
+ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="kpartx_end"
|
||||||
|
|
||||||
|
# Create dm tables for partitions on multipath devices.
|
||||||
|
ENV{DM_UUID}!="mpath-?*", GOTO="mpath_kpartx_end"
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,43 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 2 Apr 2020 18:12:48 +0200
|
||||||
|
Subject: [PATCH] kpartx.rules: check for skip_kpartx on synthetic uevents
|
||||||
|
|
||||||
|
The current test to detect "spurious" uevents, and thus whether to
|
||||||
|
import DM_SUBSYSTEM_UDEV_FLAG1 (the flag for the "skip_kpartx" option)
|
||||||
|
from the udev db is wrong. In 10-dm.rules, DM_UDEV_PRIMARY_SOURCE_FLAG
|
||||||
|
is imported from the db if it isn't set, meaning that it's always 1
|
||||||
|
for active maps. The only events for which DM_SUBSYSTEM_UDEV_FLAG1
|
||||||
|
must not be loaded from the db are the real "primary" events, which
|
||||||
|
are "change" events with DM_ACTIVATION=="1".
|
||||||
|
|
||||||
|
11-dm-mpath.rules resets DM_ACTIVATION to 0 if nothing should change in upper
|
||||||
|
layers. In this case importing DM_SUBSYSTEM_UDEV_FLAG1 is correct, too. kpartx
|
||||||
|
will not be called anyway, because 11-dm-mpath.rules also sets MPATH_UNCHANGED=1.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
kpartx/kpartx.rules | 7 +++++--
|
||||||
|
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
|
||||||
|
index f1bf31ca..d7527d7d 100644
|
||||||
|
--- a/kpartx/kpartx.rules
|
||||||
|
+++ b/kpartx/kpartx.rules
|
||||||
|
@@ -13,8 +13,11 @@ ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="kpartx_end"
|
||||||
|
ENV{DM_UUID}!="mpath-?*", GOTO="mpath_kpartx_end"
|
||||||
|
|
||||||
|
# DM_SUBSYSTEM_UDEV_FLAG1 is the "skip_kpartx" flag.
|
||||||
|
-# For events not generated by libdevmapper, we need to fetch it from db.
|
||||||
|
-ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", IMPORT{db}="DM_SUBSYSTEM_UDEV_FLAG1"
|
||||||
|
+# For events not generated by libdevmapper, we need to fetch it from db:
|
||||||
|
+# - "change" events with DM_ACTIVATION!="1" (e.g. partition table changes)
|
||||||
|
+# - "add" events for which rules are not disabled ("coldplug" case)
|
||||||
|
+ENV{DM_ACTIVATION}!="1", IMPORT{db}="DM_SUBSYSTEM_UDEV_FLAG1"
|
||||||
|
+ACTION=="add", IMPORT{db}="DM_SUBSYSTEM_UDEV_FLAG1"
|
||||||
|
ENV{DM_SUBSYSTEM_UDEV_FLAG1}=="1", GOTO="mpath_kpartx_end"
|
||||||
|
|
||||||
|
# 11-dm-mpath.rules sets MPATH_UNCHANGED for events that can be ignored.
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
31
0009-libmpathpersist-depend-on-libmultipath.patch
Normal file
31
0009-libmpathpersist-depend-on-libmultipath.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Hesse <mail@eworm.de>
|
||||||
|
Date: Wed, 6 May 2020 09:35:47 +0200
|
||||||
|
Subject: [PATCH] libmpathpersist: depend on libmultipath
|
||||||
|
|
||||||
|
Without this the build fails with:
|
||||||
|
|
||||||
|
/usr/bin/ld: cannot find -lmultipath
|
||||||
|
|
||||||
|
Signed-off-by: Christian Hesse <mail@eworm.de>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 1dee3680..ba1d73ba 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -28,7 +28,7 @@ all: $(BUILDDIRS)
|
||||||
|
$(BUILDDIRS):
|
||||||
|
$(MAKE) -C $@
|
||||||
|
|
||||||
|
-multipath multipathd mpathpersist: libmultipath
|
||||||
|
+libmpathpersist multipath multipathd mpathpersist: libmultipath
|
||||||
|
mpathpersist: libmpathpersist
|
||||||
|
|
||||||
|
$(BUILDDIRS.clean):
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 14:24:37 +0200
|
||||||
|
Subject: [PATCH] multipath-tools: Makefile: more dependency fixes for parallel
|
||||||
|
build
|
||||||
|
|
||||||
|
Extend the late fixes from Christian.
|
||||||
|
|
||||||
|
Cc: Christian Hesse <mail@eworm.de>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile | 5 +++--
|
||||||
|
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index ba1d73ba..fec3b73b 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -28,8 +28,9 @@ all: $(BUILDDIRS)
|
||||||
|
$(BUILDDIRS):
|
||||||
|
$(MAKE) -C $@
|
||||||
|
|
||||||
|
-libmpathpersist multipath multipathd mpathpersist: libmultipath
|
||||||
|
-mpathpersist: libmpathpersist
|
||||||
|
+libmultipath libdmmp: libmpathcmd
|
||||||
|
+libmpathpersist multipath multipathd: libmultipath
|
||||||
|
+mpathpersist multipathd: libmpathpersist
|
||||||
|
|
||||||
|
$(BUILDDIRS.clean):
|
||||||
|
$(MAKE) -C ${@:.clean=} clean
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,44 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 15:27:34 +0200
|
||||||
|
Subject: [PATCH] multipath-tools: Makefile.inc: separate out OPTFLAGS
|
||||||
|
|
||||||
|
OPTFLAGS is what distribution builds would typically override. That
|
||||||
|
should not include the warning flags we use.
|
||||||
|
|
||||||
|
Moreover, in the definition of CFLAGS, put $(CFLAGS) first to make it
|
||||||
|
easier for the user to spot her input in the build logs.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile.inc | 12 ++++++------
|
||||||
|
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
|
index d4d1e0dd..7a59db85 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -93,14 +93,14 @@ STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
|
||||||
|
ERROR_DISCARDED_QUALIFIERS := $(call TEST_CC_OPTION,-Werror=discarded-qualifiers,)
|
||||||
|
WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered,)
|
||||||
|
|
||||||
|
-OPTFLAGS = -O2 -g -pipe -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int \
|
||||||
|
+OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
|
||||||
|
+WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int \
|
||||||
|
-Werror=implicit-function-declaration -Werror=format-security \
|
||||||
|
- $(WNOCLOBBERED) \
|
||||||
|
- -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
|
||||||
|
- $(STACKPROT) --param=ssp-buffer-size=4
|
||||||
|
+ $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS)
|
||||||
|
CPPFLAGS := -Wp,-D_FORTIFY_SOURCE=2
|
||||||
|
-CFLAGS := $(OPTFLAGS) -DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
|
||||||
|
- -MMD -MP $(CFLAGS)
|
||||||
|
+CFLAGS := $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
|
||||||
|
+ -DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
|
||||||
|
+ -MMD -MP
|
||||||
|
BIN_CFLAGS = -fPIE -DPIE
|
||||||
|
LIB_CFLAGS = -fPIC
|
||||||
|
SHARED_FLAGS = -shared
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 16:00:04 +0200
|
||||||
|
Subject: [PATCH] multipath-tools: Makefile.inc: allow user settings for
|
||||||
|
LDFLAGS
|
||||||
|
|
||||||
|
This allows e.g. setting LDFLAGS="-m32 -Wl,-b,elf32-i386" to compile
|
||||||
|
for a 32bit target on a 64bit system.
|
||||||
|
|
||||||
|
Note that, like CFLAGS, the variable needs to be set in the environment,
|
||||||
|
not on the "make" command line.
|
||||||
|
|
||||||
|
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 7a59db85..671dd1ca 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -104,7 +104,7 @@ CFLAGS := $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
|
||||||
|
BIN_CFLAGS = -fPIE -DPIE
|
||||||
|
LIB_CFLAGS = -fPIC
|
||||||
|
SHARED_FLAGS = -shared
|
||||||
|
-LDFLAGS = -Wl,-z,relro -Wl,-z,now
|
||||||
|
+LDFLAGS := $(LDFLAGS) -Wl,-z,relro -Wl,-z,now
|
||||||
|
BIN_LDFLAGS = -pie
|
||||||
|
|
||||||
|
# Check whether a function with name $1 has been declared in header file $2.
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 17:19:37 +0200
|
||||||
|
Subject: [PATCH] multipath-tools: Makefile.inc: set -Wno-error=clobbered
|
||||||
|
|
||||||
|
We need to ignore -Wclobbered because gcc has trouble dealing with glibc's
|
||||||
|
implementation of pthread_cleanup_push().
|
||||||
|
|
||||||
|
For some variants of gcc, -Wno-clobbered alone isn't enough if -Werror is also
|
||||||
|
set. Compilation with -Wno-error=clobbered works, though.
|
||||||
|
|
||||||
|
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 671dd1ca..e7256e3a 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -91,7 +91,7 @@ TEST_CC_OPTION = $(shell \
|
||||||
|
|
||||||
|
STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
|
||||||
|
ERROR_DISCARDED_QUALIFIERS := $(call TEST_CC_OPTION,-Werror=discarded-qualifiers,)
|
||||||
|
-WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered,)
|
||||||
|
+WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered -Wno-error=clobbered,)
|
||||||
|
|
||||||
|
OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
|
||||||
|
WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int \
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,90 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 16:02:25 +0200
|
||||||
|
Subject: [PATCH] libmultipath: discovery.c: use %z qualifier for size_t
|
||||||
|
|
||||||
|
Otherwise compilation for 32bit targets spits out warnings.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 16 ++++++++--------
|
||||||
|
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index ee3290cd..ffec5162 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -986,7 +986,7 @@ parse_vpd_pg80(const unsigned char *in, char *out, size_t out_len)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len >= out_len) {
|
||||||
|
- condlog(2, "vpd pg80 overflow, %lu/%lu bytes required",
|
||||||
|
+ condlog(2, "vpd pg80 overflow, %zu/%zu bytes required",
|
||||||
|
len + 1, out_len);
|
||||||
|
len = out_len - 1;
|
||||||
|
}
|
||||||
|
@@ -1087,7 +1087,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
|
||||||
|
len = sprintf(out, "%d", vpd_type);
|
||||||
|
if (2 * vpd_len >= out_len - len) {
|
||||||
|
- condlog(1, "%s: WWID overflow, type %d, %lu/%lu bytes required",
|
||||||
|
+ condlog(1, "%s: WWID overflow, type %d, %zu/%zu bytes required",
|
||||||
|
__func__, vpd_type,
|
||||||
|
2 * vpd_len + len + 1, out_len);
|
||||||
|
vpd_len = (out_len - len - 1) / 2;
|
||||||
|
@@ -1096,7 +1096,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
len += sprintf(out + len,
|
||||||
|
"%02x", vpd[i]);
|
||||||
|
} else if (vpd_type == 0x8 && vpd_len < 4) {
|
||||||
|
- condlog(1, "%s: VPD length %lu too small for designator type 8",
|
||||||
|
+ condlog(1, "%s: VPD length %zu too small for designator type 8",
|
||||||
|
__func__, vpd_len);
|
||||||
|
return -EINVAL;
|
||||||
|
} else if (vpd_type == 0x8) {
|
||||||
|
@@ -1112,7 +1112,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
while (len > 2 && vpd[len - 2] == '\0')
|
||||||
|
--len;
|
||||||
|
if (len > out_len - 1) {
|
||||||
|
- condlog(1, "%s: WWID overflow, type 8/%c, %lu/%lu bytes required",
|
||||||
|
+ condlog(1, "%s: WWID overflow, type 8/%c, %zu/%zu bytes required",
|
||||||
|
__func__, out[0], len + 1, out_len);
|
||||||
|
len = out_len - 1;
|
||||||
|
}
|
||||||
|
@@ -1136,7 +1136,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
while ((p = memchr(vpd, ' ', vpd_len))) {
|
||||||
|
p_len = p - vpd;
|
||||||
|
if (len + p_len > out_len - 1) {
|
||||||
|
- condlog(1, "%s: WWID overflow, type 1, %lu/%lu bytes required",
|
||||||
|
+ condlog(1, "%s: WWID overflow, type 1, %zu/%zu bytes required",
|
||||||
|
__func__, len + p_len, out_len);
|
||||||
|
p_len = out_len - len - 1;
|
||||||
|
}
|
||||||
|
@@ -1162,7 +1162,7 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
|
||||||
|
p_len = vpd_len;
|
||||||
|
if (p_len > 0 && len < out_len - 1) {
|
||||||
|
if (len + p_len > out_len - 1) {
|
||||||
|
- condlog(1, "%s: WWID overflow, type 1, %lu/%lu bytes required",
|
||||||
|
+ condlog(1, "%s: WWID overflow, type 1, %zu/%zu bytes required",
|
||||||
|
__func__, len + p_len + 1, out_len);
|
||||||
|
p_len = out_len - len - 1;
|
||||||
|
}
|
||||||
|
@@ -1186,14 +1186,14 @@ parse_vpd_c0_hp3par(const unsigned char *in, size_t in_len,
|
||||||
|
|
||||||
|
memset(out, 0x0, out_len);
|
||||||
|
if (in_len <= 4 || (in[4] > 3 && in_len < 44)) {
|
||||||
|
- condlog(3, "HP/3PAR vendor specific VPD page length too short: %lu", in_len);
|
||||||
|
+ condlog(3, "HP/3PAR vendor specific VPD page length too short: %zu", in_len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (in[4] <= 3) /* revision must be > 3 to have Vomlume Name */
|
||||||
|
return -ENODATA;
|
||||||
|
len = get_unaligned_be32(&in[40]);
|
||||||
|
if (len > out_len || len + 44 > in_len) {
|
||||||
|
- condlog(3, "HP/3PAR vendor specific Volume name too long: %lu",
|
||||||
|
+ condlog(3, "HP/3PAR vendor specific Volume name too long: %zu",
|
||||||
|
len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
198
0015-libmultipath-eliminate-more-signed-unsigned-comparis.patch
Normal file
198
0015-libmultipath-eliminate-more-signed-unsigned-comparis.patch
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 16:03:58 +0200
|
||||||
|
Subject: [PATCH] libmultipath: eliminate more signed/unsigned comparisons
|
||||||
|
|
||||||
|
Fix some more compiler warnings about signed/unsigned comparison.
|
||||||
|
I've observed these only on 32bit builds, therefore they went unnoticed
|
||||||
|
before.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_pr_ioctl.c | 2 +-
|
||||||
|
libmultipath/print.c | 12 ++++++------
|
||||||
|
libmultipath/prioritizers/alua_spc3.h | 2 +-
|
||||||
|
multipathd/cli_handlers.c | 20 ++++++++++----------
|
||||||
|
multipathd/main.c | 2 +-
|
||||||
|
5 files changed, 19 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_pr_ioctl.c b/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
index fadc9e10..126601c3 100644
|
||||||
|
--- a/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
+++ b/libmpathpersist/mpath_pr_ioctl.c
|
||||||
|
@@ -238,7 +238,7 @@ static void mpath_format_readfullstatus(struct prin_resp *pr_buff)
|
||||||
|
uint32_t additional_length, k, tid_len_len = 0;
|
||||||
|
char tempbuff[MPATH_MAX_PARAM_LEN];
|
||||||
|
struct prin_fulldescr fdesc;
|
||||||
|
- static const int pbuf_size =
|
||||||
|
+ static const unsigned int pbuf_size =
|
||||||
|
sizeof(pr_buff->prin_descriptor.prin_readfd.private_buffer);
|
||||||
|
|
||||||
|
convert_be32_to_cpu(&pr_buff->prin_descriptor.prin_readfd.prgeneration);
|
||||||
|
diff --git a/libmultipath/print.c b/libmultipath/print.c
|
||||||
|
index b944ef32..298b3764 100644
|
||||||
|
--- a/libmultipath/print.c
|
||||||
|
+++ b/libmultipath/print.c
|
||||||
|
@@ -1958,25 +1958,25 @@ char *snprint_config(const struct config *conf, int *len,
|
||||||
|
}
|
||||||
|
|
||||||
|
c = reply + snprint_defaults(conf, reply, maxlen);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += snprint_blacklist(conf, c, reply + maxlen - c);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += snprint_blacklist_except(conf, c, reply + maxlen - c);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += snprint_hwtable(conf, c, reply + maxlen - c,
|
||||||
|
hwtable ? hwtable : conf->hwtable);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += snprint_overrides(conf, c, reply + maxlen - c,
|
||||||
|
conf->overrides);
|
||||||
|
- if ((c - reply) == maxlen)
|
||||||
|
+ if (c == reply + maxlen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (VECTOR_SIZE(conf->mptable) > 0 ||
|
||||||
|
@@ -1984,7 +1984,7 @@ char *snprint_config(const struct config *conf, int *len,
|
||||||
|
c += snprint_mptable(conf, c, reply + maxlen - c,
|
||||||
|
mpvec);
|
||||||
|
|
||||||
|
- if ((c - reply) < maxlen) {
|
||||||
|
+ if (c < reply + maxlen) {
|
||||||
|
if (len)
|
||||||
|
*len = c - reply;
|
||||||
|
return reply;
|
||||||
|
diff --git a/libmultipath/prioritizers/alua_spc3.h b/libmultipath/prioritizers/alua_spc3.h
|
||||||
|
index 18b495ef..7ba2cf4c 100644
|
||||||
|
--- a/libmultipath/prioritizers/alua_spc3.h
|
||||||
|
+++ b/libmultipath/prioritizers/alua_spc3.h
|
||||||
|
@@ -284,7 +284,7 @@ struct rtpg_data {
|
||||||
|
#define RTPG_FOR_EACH_PORT_GROUP(p, g) \
|
||||||
|
for( \
|
||||||
|
g = &(p->data[0]); \
|
||||||
|
- (((char *) g) - ((char *) p)) < get_unaligned_be32(p->length); \
|
||||||
|
+ ((char *) g) < ((char *) p) + get_unaligned_be32(p->length); \
|
||||||
|
g = (struct rtpg_tpg_dscr *) ( \
|
||||||
|
((char *) g) + \
|
||||||
|
sizeof(struct rtpg_tpg_dscr) + \
|
||||||
|
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
|
||||||
|
index 7d878c88..31c3d9fd 100644
|
||||||
|
--- a/multipathd/cli_handlers.c
|
||||||
|
+++ b/multipathd/cli_handlers.c
|
||||||
|
@@ -66,7 +66,7 @@ show_paths (char ** r, int * len, struct vectors * vecs, char * style,
|
||||||
|
c += snprint_foreign_paths(c, reply + maxlen - c,
|
||||||
|
style, pretty);
|
||||||
|
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -102,7 +102,7 @@ show_path (char ** r, int * len, struct vectors * vecs, struct path *pp,
|
||||||
|
|
||||||
|
c += snprint_path(c, reply + maxlen - c, style, pp, 0);
|
||||||
|
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -131,7 +131,7 @@ show_map_topology (char ** r, int * len, struct multipath * mpp,
|
||||||
|
c = reply;
|
||||||
|
|
||||||
|
c += snprint_multipath_topology(c, reply + maxlen - c, mpp, 2);
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -171,7 +171,7 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs)
|
||||||
|
}
|
||||||
|
c += snprint_foreign_topology(c, reply + maxlen - c, 2);
|
||||||
|
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -209,7 +209,7 @@ show_maps_json (char ** r, int * len, struct vectors * vecs)
|
||||||
|
c = reply;
|
||||||
|
|
||||||
|
c += snprint_multipath_topology_json(c, maxlen, vecs);
|
||||||
|
- again = ((c - reply) == maxlen);
|
||||||
|
+ again = (c == reply + maxlen);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -238,7 +238,7 @@ show_map_json (char ** r, int * len, struct multipath * mpp,
|
||||||
|
c = reply;
|
||||||
|
|
||||||
|
c += snprint_multipath_map_json(c, maxlen, mpp);
|
||||||
|
- again = ((c - reply) == maxlen);
|
||||||
|
+ again = (c == reply + maxlen);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -487,7 +487,7 @@ show_map (char ** r, int *len, struct multipath * mpp, char * style,
|
||||||
|
c += snprint_multipath(c, reply + maxlen - c, style,
|
||||||
|
mpp, pretty);
|
||||||
|
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -533,7 +533,7 @@ show_maps (char ** r, int *len, struct vectors * vecs, char * style,
|
||||||
|
}
|
||||||
|
c += snprint_foreign_multipaths(c, reply + maxlen - c,
|
||||||
|
style, pretty);
|
||||||
|
- again = ((c - reply) == (maxlen - 1));
|
||||||
|
+ again = (c == reply + maxlen - 1);
|
||||||
|
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
@@ -1297,7 +1297,7 @@ show_blacklist (char ** r, int * len)
|
||||||
|
|
||||||
|
c = reply;
|
||||||
|
c += snprint_blacklist_report(conf, c, maxlen);
|
||||||
|
- again = ((c - reply) == maxlen);
|
||||||
|
+ again = (c == reply + maxlen);
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
@@ -1339,7 +1339,7 @@ show_devices (char ** r, int * len, struct vectors *vecs)
|
||||||
|
|
||||||
|
c = reply;
|
||||||
|
c += snprint_devices(conf, c, maxlen, vecs);
|
||||||
|
- again = ((c - reply) == maxlen);
|
||||||
|
+ again = (c == reply + maxlen);
|
||||||
|
REALLOC_REPLY(reply, again, maxlen);
|
||||||
|
}
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 8baf9abe..6b7db2c0 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -2374,7 +2374,7 @@ checkerloop (void *ap)
|
||||||
|
conf = get_multipath_config();
|
||||||
|
max_checkint = conf->max_checkint;
|
||||||
|
put_multipath_config(conf);
|
||||||
|
- if (diff_time.tv_sec > max_checkint)
|
||||||
|
+ if (diff_time.tv_sec > (time_t)max_checkint)
|
||||||
|
condlog(1, "path checkers took longer "
|
||||||
|
"than %lu seconds, consider "
|
||||||
|
"increasing max_polling_interval",
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
48
0016-libmultipath-set_uint-fix-parsing-for-32bit.patch
Normal file
48
0016-libmultipath-set_uint-fix-parsing-for-32bit.patch
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 22:22:25 +0200
|
||||||
|
Subject: [PATCH] libmultipath: set_uint: fix parsing for 32bit
|
||||||
|
|
||||||
|
On architectures where sizeof(long) == sizeof(int), the code wouldn't
|
||||||
|
work as intended. Use strtoul instead. As strtoul happily parses
|
||||||
|
negative numbers as input, require the number to begin with a digit.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 11 +++++++----
|
||||||
|
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 3e25e74f..0e9ea387 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -60,19 +60,22 @@ static int
|
||||||
|
set_uint(vector strvec, void *ptr)
|
||||||
|
{
|
||||||
|
unsigned int *uint_ptr = (unsigned int *)ptr;
|
||||||
|
- char *buff, *eptr;
|
||||||
|
- long res;
|
||||||
|
+ char *buff, *eptr, *p;
|
||||||
|
+ unsigned long res;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
buff = set_value(strvec);
|
||||||
|
if (!buff)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- res = strtol(buff, &eptr, 10);
|
||||||
|
+ p = buff;
|
||||||
|
+ while (isspace(*p))
|
||||||
|
+ p++;
|
||||||
|
+ res = strtoul(p, &eptr, 10);
|
||||||
|
if (eptr > buff)
|
||||||
|
while (isspace(*eptr))
|
||||||
|
eptr++;
|
||||||
|
- if (*buff == '\0' || *eptr != '\0' || res < 0 || res > UINT_MAX) {
|
||||||
|
+ if (*buff == '\0' || *eptr != '\0' || !isdigit(*p) || res > UINT_MAX) {
|
||||||
|
condlog(1, "%s: invalid value for %s: \"%s\"",
|
||||||
|
__func__, (char*)VECTOR_SLOT(strvec, 0), buff);
|
||||||
|
rc = 1;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,28 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 18:24:19 +0200
|
||||||
|
Subject: [PATCH] multipath-tools tests/Makefile: add -lmpathcmd to LIBDEPS
|
||||||
|
|
||||||
|
Make sure the linker finds libmpathcmd.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
tests/Makefile | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/tests/Makefile b/tests/Makefile
|
||||||
|
index 77ff3249..028c9ea7 100644
|
||||||
|
--- a/tests/Makefile
|
||||||
|
+++ b/tests/Makefile
|
||||||
|
@@ -10,7 +10,7 @@ W_MISSING_INITIALIZERS := $(call TEST_MISSING_INITIALIZERS)
|
||||||
|
|
||||||
|
CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir) \
|
||||||
|
-Wno-unused-parameter $(W_MISSING_INITIALIZERS)
|
||||||
|
-LIBDEPS += -L$(multipathdir) -lmultipath -lcmocka
|
||||||
|
+LIBDEPS += -L$(multipathdir) -L$(mpathcmddir) -lmultipath -lmpathcmd -lcmocka
|
||||||
|
|
||||||
|
TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \
|
||||||
|
alias directio
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,34 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 23:44:19 +0200
|
||||||
|
Subject: [PATCH] multipath tools tests/Makefile: Fix OBJDEPS for hwtable-test
|
||||||
|
|
||||||
|
OBJDEPS needs to list object files that _call_ functions we want
|
||||||
|
to wrap, but it should _not_ list the object files where these
|
||||||
|
functions are defined; otherwise the linker might resolve these
|
||||||
|
symbols before they can be wrapped.
|
||||||
|
|
||||||
|
(Observed on i586 with gcc 9.3.1, ld 2.34.0, where wrapping
|
||||||
|
prio_getprio() doesn't work with prio.o in OBJDEPS).
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
tests/Makefile | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/tests/Makefile b/tests/Makefile
|
||||||
|
index 028c9ea7..1b8706a7 100644
|
||||||
|
--- a/tests/Makefile
|
||||||
|
+++ b/tests/Makefile
|
||||||
|
@@ -41,7 +41,7 @@ endif
|
||||||
|
dmevents-test_LIBDEPS = -lpthread -ldevmapper -lurcu
|
||||||
|
hwtable-test_TESTDEPS := test-lib.o
|
||||||
|
hwtable-test_OBJDEPS := ../libmultipath/discovery.o ../libmultipath/blacklist.o \
|
||||||
|
- ../libmultipath/prio.o ../libmultipath/callout.o ../libmultipath/structs.o
|
||||||
|
+ ../libmultipath/structs.o
|
||||||
|
hwtable-test_LIBDEPS := -ludev -lpthread -ldl
|
||||||
|
blacklist-test_TESTDEPS := test-log.o
|
||||||
|
blacklist-test_OBJDEPS := ../libmultipath/blacklist.o
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 11 May 2020 23:43:02 +0200
|
||||||
|
Subject: [PATCH] multipath-tools tests/test-lib.c: drop
|
||||||
|
__wrap_is_claimed_by_foreign
|
||||||
|
|
||||||
|
is_claimed_by_foreign() is an inline function and can't be wrapped.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
tests/test-lib.c | 6 ------
|
||||||
|
1 file changed, 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/tests/test-lib.c b/tests/test-lib.c
|
||||||
|
index 59275163..00bae58e 100644
|
||||||
|
--- a/tests/test-lib.c
|
||||||
|
+++ b/tests/test-lib.c
|
||||||
|
@@ -56,12 +56,6 @@ int __wrap_execute_program(char *path, char *value, int len)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool __wrap_is_claimed_by_foreign(struct udev_device *ud)
|
||||||
|
-{
|
||||||
|
- condlog(5, "%s: %p", __func__, ud);
|
||||||
|
- return false;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
struct udev_list_entry
|
||||||
|
*__wrap_udev_device_get_properties_list_entry(struct udev_device *ud)
|
||||||
|
{
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,29 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 12 May 2020 00:11:39 +0200
|
||||||
|
Subject: [PATCH] multipath-tools tests/directio: fix -Wmaybe-uninitalized
|
||||||
|
warning
|
||||||
|
|
||||||
|
Initialize aio_grp to satisfy gcc.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
tests/directio.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/tests/directio.c b/tests/directio.c
|
||||||
|
index 3cd7a520..66aaf0eb 100644
|
||||||
|
--- a/tests/directio.c
|
||||||
|
+++ b/tests/directio.c
|
||||||
|
@@ -316,7 +316,7 @@ static void test_init_free(void **state)
|
||||||
|
{
|
||||||
|
int i, count = 0;
|
||||||
|
struct checker c[4096] = {0};
|
||||||
|
- struct aio_group *aio_grp;
|
||||||
|
+ struct aio_group *aio_grp = NULL;
|
||||||
|
|
||||||
|
assert_true(list_empty(&aio_grp_list));
|
||||||
|
will_return(__wrap_io_setup, 0);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
83
0021-libmultipath-move-libsg-into-libmultipath.patch
Normal file
83
0021-libmultipath-move-libsg-into-libmultipath.patch
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 12 May 2020 16:46:15 +0200
|
||||||
|
Subject: [PATCH] libmultipath: move libsg into libmultipath
|
||||||
|
|
||||||
|
sg_read() is called from readsector0 and emc_clariion. Move it
|
||||||
|
to libmultipath/, where all common code resides.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/Makefile | 3 ++-
|
||||||
|
libmultipath/checkers/Makefile | 6 +++---
|
||||||
|
libmultipath/{checkers => }/libsg.c | 0
|
||||||
|
libmultipath/{checkers => }/libsg.h | 0
|
||||||
|
libmultipath/prioritizers/Makefile | 2 +-
|
||||||
|
5 files changed, 6 insertions(+), 5 deletions(-)
|
||||||
|
rename libmultipath/{checkers => }/libsg.c (100%)
|
||||||
|
rename libmultipath/{checkers => }/libsg.h (100%)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
|
||||||
|
index ad690a49..f19b7ad2 100644
|
||||||
|
--- a/libmultipath/Makefile
|
||||||
|
+++ b/libmultipath/Makefile
|
||||||
|
@@ -47,7 +47,8 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
|
||||||
|
switchgroup.o uxsock.o print.o alias.o log_pthread.o \
|
||||||
|
log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
|
||||||
|
lock.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o \
|
||||||
|
- io_err_stat.o dm-generic.o generic.o foreign.o nvme-lib.o
|
||||||
|
+ io_err_stat.o dm-generic.o generic.o foreign.o nvme-lib.o \
|
||||||
|
+ libsg.o
|
||||||
|
|
||||||
|
all: $(LIBS)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/checkers/Makefile b/libmultipath/checkers/Makefile
|
||||||
|
index 02caea64..01c04510 100644
|
||||||
|
--- a/libmultipath/checkers/Makefile
|
||||||
|
+++ b/libmultipath/checkers/Makefile
|
||||||
|
@@ -17,10 +17,10 @@ LIBS= \
|
||||||
|
|
||||||
|
all: $(LIBS)
|
||||||
|
|
||||||
|
-libcheckdirectio.so: libsg.o directio.o
|
||||||
|
+libcheckdirectio.so: directio.o
|
||||||
|
$(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -laio
|
||||||
|
|
||||||
|
-libcheck%.so: libsg.o %.o
|
||||||
|
+libcheck%.so: %.o
|
||||||
|
$(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^
|
||||||
|
|
||||||
|
install:
|
||||||
|
@@ -32,7 +32,7 @@ uninstall:
|
||||||
|
clean: dep_clean
|
||||||
|
$(RM) core *.a *.o *.gz *.so
|
||||||
|
|
||||||
|
-OBJS := $(LIBS:libcheck%.so=%.o) libsg.o directio.o
|
||||||
|
+OBJS := $(LIBS:libcheck%.so=%.o)
|
||||||
|
.SECONDARY: $(OBJS)
|
||||||
|
|
||||||
|
include $(wildcard $(OBJS:.o=.d))
|
||||||
|
diff --git a/libmultipath/checkers/libsg.c b/libmultipath/libsg.c
|
||||||
|
similarity index 100%
|
||||||
|
rename from libmultipath/checkers/libsg.c
|
||||||
|
rename to libmultipath/libsg.c
|
||||||
|
diff --git a/libmultipath/checkers/libsg.h b/libmultipath/libsg.h
|
||||||
|
similarity index 100%
|
||||||
|
rename from libmultipath/checkers/libsg.h
|
||||||
|
rename to libmultipath/libsg.h
|
||||||
|
diff --git a/libmultipath/prioritizers/Makefile b/libmultipath/prioritizers/Makefile
|
||||||
|
index 9d0fe03c..fc6e0e0c 100644
|
||||||
|
--- a/libmultipath/prioritizers/Makefile
|
||||||
|
+++ b/libmultipath/prioritizers/Makefile
|
||||||
|
@@ -28,7 +28,7 @@ endif
|
||||||
|
|
||||||
|
all: $(LIBS)
|
||||||
|
|
||||||
|
-libpriopath_latency.so: path_latency.o ../checkers/libsg.o
|
||||||
|
+libpriopath_latency.so: path_latency.o
|
||||||
|
$(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ -lm
|
||||||
|
|
||||||
|
libprio%.so: %.o
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
32
0022-multipath-tools-Makefile-add-install-dependency.patch
Normal file
32
0022-multipath-tools-Makefile-add-install-dependency.patch
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 12 May 2020 22:13:51 +0200
|
||||||
|
Subject: [PATCH] multipath-tools Makefile: add install dependency
|
||||||
|
|
||||||
|
$(libdir) must exist before running "make install" on prioritizer, checker,
|
||||||
|
and foreign libraries.
|
||||||
|
|
||||||
|
Cc: Christian Hesse <mail@eworm.de>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index fec3b73b..8bcaba66 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -32,6 +32,10 @@ libmultipath libdmmp: libmpathcmd
|
||||||
|
libmpathpersist multipath multipathd: libmultipath
|
||||||
|
mpathpersist multipathd: libmpathpersist
|
||||||
|
|
||||||
|
+libmultipath/checkers.install \
|
||||||
|
+ libmultipath/prioritizers.install \
|
||||||
|
+ libmultipath/foreign.install: libmultipath.install
|
||||||
|
+
|
||||||
|
$(BUILDDIRS.clean):
|
||||||
|
$(MAKE) -C ${@:.clean=} clean
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
89
0023-libmultipath-make-libmp_dm_init-optional.patch
Normal file
89
0023-libmultipath-make-libmp_dm_init-optional.patch
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 19 May 2020 12:08:40 -0500
|
||||||
|
Subject: [PATCH] libmultipath: make libmp_dm_init optional
|
||||||
|
|
||||||
|
Move dm_initialized out of libmp_dm_task_create(), and add
|
||||||
|
a function skip_libmp_dm_init() so that users of libmultipath can skip
|
||||||
|
initializing device-mapper. This is needed for other programs that
|
||||||
|
use libmultipath (or a library that depends on it) but want to control
|
||||||
|
how device-mapper is set up.
|
||||||
|
|
||||||
|
Also make dm_prereq a global function.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/devmapper.c | 17 +++++++++++++----
|
||||||
|
libmultipath/devmapper.h | 3 ++-
|
||||||
|
2 files changed, 15 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index 13a1cf53..7ed494a1 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -33,6 +33,8 @@
|
||||||
|
#define MAX_WAIT 5
|
||||||
|
#define LOOPS_PER_SEC 5
|
||||||
|
|
||||||
|
+static pthread_once_t dm_initialized = PTHREAD_ONCE_INIT;
|
||||||
|
+
|
||||||
|
static int dm_conf_verbosity;
|
||||||
|
|
||||||
|
#ifdef LIBDM_API_DEFERRED
|
||||||
|
@@ -229,7 +231,7 @@ dm_tgt_prereq (unsigned int *ver)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int dm_prereq(unsigned int *v)
|
||||||
|
+int dm_prereq(unsigned int *v)
|
||||||
|
{
|
||||||
|
if (dm_lib_prereq())
|
||||||
|
return 1;
|
||||||
|
@@ -243,7 +245,7 @@ void libmp_udev_set_sync_support(int on)
|
||||||
|
libmp_dm_udev_sync = !!on;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void libmp_dm_init(void)
|
||||||
|
+static void libmp_dm_init(void)
|
||||||
|
{
|
||||||
|
struct config *conf;
|
||||||
|
int verbosity;
|
||||||
|
@@ -262,11 +264,18 @@ void libmp_dm_init(void)
|
||||||
|
dm_udev_set_sync_support(libmp_dm_udev_sync);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void _do_skip_libmp_dm_init(void)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void skip_libmp_dm_init(void)
|
||||||
|
+{
|
||||||
|
+ pthread_once(&dm_initialized, _do_skip_libmp_dm_init);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct dm_task*
|
||||||
|
libmp_dm_task_create(int task)
|
||||||
|
{
|
||||||
|
- static pthread_once_t dm_initialized = PTHREAD_ONCE_INIT;
|
||||||
|
-
|
||||||
|
pthread_once(&dm_initialized, libmp_dm_init);
|
||||||
|
return dm_task_create(task);
|
||||||
|
}
|
||||||
|
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
|
||||||
|
index 7557a86b..17fc9faf 100644
|
||||||
|
--- a/libmultipath/devmapper.h
|
||||||
|
+++ b/libmultipath/devmapper.h
|
||||||
|
@@ -28,7 +28,8 @@
|
||||||
|
#define UUID_PREFIX_LEN (sizeof(UUID_PREFIX) - 1)
|
||||||
|
|
||||||
|
void dm_init(int verbosity);
|
||||||
|
-void libmp_dm_init(void);
|
||||||
|
+int dm_prereq(unsigned int *v);
|
||||||
|
+void skip_libmp_dm_init(void);
|
||||||
|
void libmp_udev_set_sync_support(int on);
|
||||||
|
struct dm_task *libmp_dm_task_create(int task);
|
||||||
|
int dm_drv_version (unsigned int * version);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
108
0024-libmultipath-make-sysfs_is_multipathed-able-to-retur.patch
Normal file
108
0024-libmultipath-make-sysfs_is_multipathed-able-to-retur.patch
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 19 May 2020 12:08:41 -0500
|
||||||
|
Subject: [PATCH] libmultipath: make sysfs_is_multipathed able to return wwid
|
||||||
|
|
||||||
|
sysfs_is_multipathed reads the wwid of the dm device holding a path to
|
||||||
|
check if its a multipath device. Add code to optinally set pp->wwid to
|
||||||
|
that wwid. This will be used by a future patch.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/sysfs.c | 24 +++++++++++++++++++-----
|
||||||
|
libmultipath/sysfs.h | 2 +-
|
||||||
|
multipath/main.c | 7 ++++---
|
||||||
|
3 files changed, 24 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
|
||||||
|
index 62ec2ed7..12a82d95 100644
|
||||||
|
--- a/libmultipath/sysfs.c
|
||||||
|
+++ b/libmultipath/sysfs.c
|
||||||
|
@@ -295,7 +295,7 @@ static int select_dm_devs(const struct dirent *di)
|
||||||
|
return fnmatch("dm-*", di->d_name, FNM_FILE_NAME) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool sysfs_is_multipathed(const struct path *pp)
|
||||||
|
+bool sysfs_is_multipathed(struct path *pp, bool set_wwid)
|
||||||
|
{
|
||||||
|
char pathbuf[PATH_MAX];
|
||||||
|
struct scandir_result sr;
|
||||||
|
@@ -325,7 +325,7 @@ bool sysfs_is_multipathed(const struct path *pp)
|
||||||
|
for (i = 0; i < r && !found; i++) {
|
||||||
|
long fd;
|
||||||
|
int nr;
|
||||||
|
- char uuid[6];
|
||||||
|
+ char uuid[WWID_SIZE + UUID_PREFIX_LEN];
|
||||||
|
|
||||||
|
if (safe_snprintf(pathbuf + n, sizeof(pathbuf) - n,
|
||||||
|
"/%s/dm/uuid", di[i]->d_name))
|
||||||
|
@@ -339,12 +339,26 @@ bool sysfs_is_multipathed(const struct path *pp)
|
||||||
|
|
||||||
|
pthread_cleanup_push(close_fd, (void *)fd);
|
||||||
|
nr = read(fd, uuid, sizeof(uuid));
|
||||||
|
- if (nr == sizeof(uuid) && !memcmp(uuid, "mpath-", sizeof(uuid)))
|
||||||
|
+ if (nr > (int)UUID_PREFIX_LEN &&
|
||||||
|
+ !memcmp(uuid, UUID_PREFIX, UUID_PREFIX_LEN))
|
||||||
|
found = true;
|
||||||
|
else if (nr < 0) {
|
||||||
|
- condlog(1, "%s: error reading from %s: %s",
|
||||||
|
- __func__, pathbuf, strerror(errno));
|
||||||
|
+ condlog(1, "%s: error reading from %s: %m",
|
||||||
|
+ __func__, pathbuf);
|
||||||
|
}
|
||||||
|
+ if (found && set_wwid) {
|
||||||
|
+ nr -= UUID_PREFIX_LEN;
|
||||||
|
+ memcpy(pp->wwid, uuid + UUID_PREFIX_LEN, nr);
|
||||||
|
+ if (nr == WWID_SIZE) {
|
||||||
|
+ condlog(4, "%s: overflow while reading from %s",
|
||||||
|
+ __func__, pathbuf);
|
||||||
|
+ pp->wwid[0] = '\0';
|
||||||
|
+ } else {
|
||||||
|
+ pp->wwid[nr] = '\0';
|
||||||
|
+ strchop(pp->wwid);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
}
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h
|
||||||
|
index 9ae30b39..72b39ab2 100644
|
||||||
|
--- a/libmultipath/sysfs.h
|
||||||
|
+++ b/libmultipath/sysfs.h
|
||||||
|
@@ -14,5 +14,5 @@ ssize_t sysfs_bin_attr_get_value(struct udev_device *dev, const char *attr_name,
|
||||||
|
unsigned char * value, size_t value_len);
|
||||||
|
int sysfs_get_size (struct path *pp, unsigned long long * size);
|
||||||
|
int sysfs_check_holders(char * check_devt, char * new_devt);
|
||||||
|
-bool sysfs_is_multipathed(const struct path *pp);
|
||||||
|
+bool sysfs_is_multipathed(struct path *pp, bool set_wwid);
|
||||||
|
#endif
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index cf9d2a28..545ead87 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -638,7 +638,8 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||||
|
* Shortcut for find_multipaths smart:
|
||||||
|
* Quick check if path is already multipathed.
|
||||||
|
*/
|
||||||
|
- if (sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0))) {
|
||||||
|
+ if (sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0),
|
||||||
|
+ false)) {
|
||||||
|
r = RTVL_YES;
|
||||||
|
goto print_valid;
|
||||||
|
}
|
||||||
|
@@ -747,8 +748,8 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||||
|
/*
|
||||||
|
* Check if we raced with multipathd
|
||||||
|
*/
|
||||||
|
- r = sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0)) ?
|
||||||
|
- RTVL_YES : RTVL_NO;
|
||||||
|
+ r = sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0),
|
||||||
|
+ false) ? RTVL_YES : RTVL_NO;
|
||||||
|
}
|
||||||
|
goto print_valid;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
777
0025-multipath-centralize-validation-code.patch
Normal file
777
0025-multipath-centralize-validation-code.patch
Normal file
@ -0,0 +1,777 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 19 May 2020 12:08:42 -0500
|
||||||
|
Subject: [PATCH] multipath: centralize validation code
|
||||||
|
|
||||||
|
This code pulls the multipath path validation code out of configure(),
|
||||||
|
and puts it into its own function, check_path_valid(). This function
|
||||||
|
calls a new libmultipath function, is_path_valid() to check just path
|
||||||
|
requested. This seperation exists so that is_path_valid() can be reused
|
||||||
|
by future code. This code will give almost the same answer as the
|
||||||
|
existing code, with the exception that now, if a device is currently
|
||||||
|
multipathed, it will always be a valid multipath path.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/Makefile | 2 +-
|
||||||
|
libmultipath/devmapper.c | 45 ++++++
|
||||||
|
libmultipath/devmapper.h | 1 +
|
||||||
|
libmultipath/structs.h | 24 +---
|
||||||
|
libmultipath/valid.c | 118 ++++++++++++++++
|
||||||
|
libmultipath/valid.h | 42 ++++++
|
||||||
|
libmultipath/wwids.c | 10 +-
|
||||||
|
multipath/main.c | 296 +++++++++++++++++----------------------
|
||||||
|
8 files changed, 343 insertions(+), 195 deletions(-)
|
||||||
|
create mode 100644 libmultipath/valid.c
|
||||||
|
create mode 100644 libmultipath/valid.h
|
||||||
|
|
||||||
|
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
|
||||||
|
index f19b7ad2..e5dac5ea 100644
|
||||||
|
--- a/libmultipath/Makefile
|
||||||
|
+++ b/libmultipath/Makefile
|
||||||
|
@@ -48,7 +48,7 @@ OBJS = memory.o parser.o vector.o devmapper.o callout.o \
|
||||||
|
log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
|
||||||
|
lock.o file.o wwids.o prioritizers/alua_rtpg.o prkey.o \
|
||||||
|
io_err_stat.o dm-generic.o generic.o foreign.o nvme-lib.o \
|
||||||
|
- libsg.o
|
||||||
|
+ libsg.o valid.o
|
||||||
|
|
||||||
|
all: $(LIBS)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index 7ed494a1..27d52398 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -770,6 +770,51 @@ out:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Return
|
||||||
|
+ * 1 : map with uuid exists
|
||||||
|
+ * 0 : map with uuid doesn't exist
|
||||||
|
+ * -1 : error
|
||||||
|
+ */
|
||||||
|
+int
|
||||||
|
+dm_map_present_by_uuid(const char *uuid)
|
||||||
|
+{
|
||||||
|
+ struct dm_task *dmt;
|
||||||
|
+ struct dm_info info;
|
||||||
|
+ char prefixed_uuid[WWID_SIZE + UUID_PREFIX_LEN];
|
||||||
|
+ int r = -1;
|
||||||
|
+
|
||||||
|
+ if (!uuid || uuid[0] == '\0')
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ if (safe_sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid))
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ dm_task_no_open_count(dmt);
|
||||||
|
+
|
||||||
|
+ if (!dm_task_set_uuid(dmt, prefixed_uuid))
|
||||||
|
+ goto out_task;
|
||||||
|
+
|
||||||
|
+ if (!dm_task_run(dmt))
|
||||||
|
+ goto out_task;
|
||||||
|
+
|
||||||
|
+ if (!dm_task_get_info(dmt, &info))
|
||||||
|
+ goto out_task;
|
||||||
|
+
|
||||||
|
+ r = !!info.exists;
|
||||||
|
+
|
||||||
|
+out_task:
|
||||||
|
+ dm_task_destroy(dmt);
|
||||||
|
+out:
|
||||||
|
+ if (r < 0)
|
||||||
|
+ condlog(3, "%s: dm command failed in %s: %s", uuid,
|
||||||
|
+ __FUNCTION__, strerror(errno));
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
dm_dev_t (const char * mapname, char * dev_t, int len)
|
||||||
|
{
|
||||||
|
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
|
||||||
|
index 17fc9faf..5ed7edc5 100644
|
||||||
|
--- a/libmultipath/devmapper.h
|
||||||
|
+++ b/libmultipath/devmapper.h
|
||||||
|
@@ -39,6 +39,7 @@ int dm_simplecmd_noflush (int, const char *, uint16_t);
|
||||||
|
int dm_addmap_create (struct multipath *mpp, char *params);
|
||||||
|
int dm_addmap_reload (struct multipath *mpp, char *params, int flush);
|
||||||
|
int dm_map_present (const char *);
|
||||||
|
+int dm_map_present_by_uuid(const char *uuid);
|
||||||
|
int dm_get_map(const char *, unsigned long long *, char *);
|
||||||
|
int dm_get_status(const char *, char *);
|
||||||
|
int dm_type(const char *, char *);
|
||||||
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||||
|
index 9bd39eb1..d69bc2e9 100644
|
||||||
|
--- a/libmultipath/structs.h
|
||||||
|
+++ b/libmultipath/structs.h
|
||||||
|
@@ -101,29 +101,13 @@ enum yes_no_undef_states {
|
||||||
|
YNU_YES,
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define _FIND_MULTIPATHS_F (1 << 1)
|
||||||
|
-#define _FIND_MULTIPATHS_I (1 << 2)
|
||||||
|
-#define _FIND_MULTIPATHS_N (1 << 3)
|
||||||
|
-/*
|
||||||
|
- * _FIND_MULTIPATHS_F must have the same value as YNU_YES.
|
||||||
|
- * Generate a compile time error if that isn't the case.
|
||||||
|
- */
|
||||||
|
-extern char ___error1___[-(_FIND_MULTIPATHS_F != YNU_YES)];
|
||||||
|
-
|
||||||
|
-#define find_multipaths_on(conf) \
|
||||||
|
- (!!((conf)->find_multipaths & _FIND_MULTIPATHS_F))
|
||||||
|
-#define ignore_wwids_on(conf) \
|
||||||
|
- (!!((conf)->find_multipaths & _FIND_MULTIPATHS_I))
|
||||||
|
-#define ignore_new_devs_on(conf) \
|
||||||
|
- (!!((conf)->find_multipaths & _FIND_MULTIPATHS_N))
|
||||||
|
-
|
||||||
|
enum find_multipaths_states {
|
||||||
|
FIND_MULTIPATHS_UNDEF = YNU_UNDEF,
|
||||||
|
FIND_MULTIPATHS_OFF = YNU_NO,
|
||||||
|
- FIND_MULTIPATHS_ON = _FIND_MULTIPATHS_F,
|
||||||
|
- FIND_MULTIPATHS_GREEDY = _FIND_MULTIPATHS_I,
|
||||||
|
- FIND_MULTIPATHS_SMART = _FIND_MULTIPATHS_F|_FIND_MULTIPATHS_I,
|
||||||
|
- FIND_MULTIPATHS_STRICT = _FIND_MULTIPATHS_F|_FIND_MULTIPATHS_N,
|
||||||
|
+ FIND_MULTIPATHS_ON = YNU_YES,
|
||||||
|
+ FIND_MULTIPATHS_GREEDY,
|
||||||
|
+ FIND_MULTIPATHS_SMART,
|
||||||
|
+ FIND_MULTIPATHS_STRICT,
|
||||||
|
__FIND_MULTIPATHS_LAST,
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/libmultipath/valid.c b/libmultipath/valid.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..456b1f6e
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libmultipath/valid.c
|
||||||
|
@@ -0,0 +1,118 @@
|
||||||
|
+/*
|
||||||
|
+ Copyright (c) 2020 Benjamin Marzinski, IBM
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU General Public License
|
||||||
|
+ as published by the Free Software Foundation; either version 2
|
||||||
|
+ of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ GNU General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU General Public License
|
||||||
|
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
+ */
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <libudev.h>
|
||||||
|
+
|
||||||
|
+#include "vector.h"
|
||||||
|
+#include "config.h"
|
||||||
|
+#include "debug.h"
|
||||||
|
+#include "util.h"
|
||||||
|
+#include "devmapper.h"
|
||||||
|
+#include "discovery.h"
|
||||||
|
+#include "wwids.h"
|
||||||
|
+#include "sysfs.h"
|
||||||
|
+#include "blacklist.h"
|
||||||
|
+#include "mpath_cmd.h"
|
||||||
|
+#include "valid.h"
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+is_path_valid(const char *name, struct config *conf, struct path *pp,
|
||||||
|
+ bool check_multipathd)
|
||||||
|
+{
|
||||||
|
+ int r;
|
||||||
|
+ int fd;
|
||||||
|
+
|
||||||
|
+ if (!pp || !name || !conf)
|
||||||
|
+ return PATH_IS_ERROR;
|
||||||
|
+
|
||||||
|
+ if (conf->find_multipaths <= FIND_MULTIPATHS_UNDEF ||
|
||||||
|
+ conf->find_multipaths >= __FIND_MULTIPATHS_LAST)
|
||||||
|
+ return PATH_IS_ERROR;
|
||||||
|
+
|
||||||
|
+ if (safe_sprintf(pp->dev, "%s", name))
|
||||||
|
+ return PATH_IS_ERROR;
|
||||||
|
+
|
||||||
|
+ if (sysfs_is_multipathed(pp, true)) {
|
||||||
|
+ if (pp->wwid[0] == '\0')
|
||||||
|
+ return PATH_IS_ERROR;
|
||||||
|
+ return PATH_IS_VALID_NO_CHECK;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * "multipath -u" may be run before the daemon is started. In this
|
||||||
|
+ * case, systemd might own the socket but might delay multipathd
|
||||||
|
+ * startup until some other unit (udev settle!) has finished
|
||||||
|
+ * starting. With many LUNs, the listen backlog may be exceeded, which
|
||||||
|
+ * would cause connect() to block. This causes udev workers calling
|
||||||
|
+ * "multipath -u" to hang, and thus creates a deadlock, until "udev
|
||||||
|
+ * settle" times out. To avoid this, call connect() in non-blocking
|
||||||
|
+ * mode here, and take EAGAIN as indication for a filled-up systemd
|
||||||
|
+ * backlog.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ if (check_multipathd) {
|
||||||
|
+ fd = __mpath_connect(1);
|
||||||
|
+ if (fd < 0) {
|
||||||
|
+ if (errno != EAGAIN && !systemd_service_enabled(name)) {
|
||||||
|
+ condlog(3, "multipathd not running or enabled");
|
||||||
|
+ return PATH_IS_NOT_VALID;
|
||||||
|
+ }
|
||||||
|
+ } else
|
||||||
|
+ mpath_disconnect(fd);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pp->udev = udev_device_new_from_subsystem_sysname(udev, "block", name);
|
||||||
|
+ if (!pp->udev)
|
||||||
|
+ return PATH_IS_ERROR;
|
||||||
|
+
|
||||||
|
+ r = pathinfo(pp, conf, DI_SYSFS | DI_WWID | DI_BLACKLIST);
|
||||||
|
+ if (r == PATHINFO_SKIPPED)
|
||||||
|
+ return PATH_IS_NOT_VALID;
|
||||||
|
+ else if (r)
|
||||||
|
+ return PATH_IS_ERROR;
|
||||||
|
+
|
||||||
|
+ if (pp->wwid[0] == '\0')
|
||||||
|
+ return PATH_IS_NOT_VALID;
|
||||||
|
+
|
||||||
|
+ if (pp->udev && pp->uid_attribute &&
|
||||||
|
+ filter_property(conf, pp->udev, 3, pp->uid_attribute) > 0)
|
||||||
|
+ return PATH_IS_NOT_VALID;
|
||||||
|
+
|
||||||
|
+ r = is_failed_wwid(pp->wwid);
|
||||||
|
+ if (r != WWID_IS_NOT_FAILED) {
|
||||||
|
+ if (r == WWID_IS_FAILED)
|
||||||
|
+ return PATH_IS_NOT_VALID;
|
||||||
|
+ return PATH_IS_ERROR;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (conf->find_multipaths == FIND_MULTIPATHS_GREEDY)
|
||||||
|
+ return PATH_IS_VALID;
|
||||||
|
+
|
||||||
|
+ if (check_wwids_file(pp->wwid, 0) == 0)
|
||||||
|
+ return PATH_IS_VALID_NO_CHECK;
|
||||||
|
+
|
||||||
|
+ if (dm_map_present_by_uuid(pp->wwid) == 1)
|
||||||
|
+ return PATH_IS_VALID;
|
||||||
|
+
|
||||||
|
+ /* all these act like FIND_MULTIPATHS_STRICT for finding if a
|
||||||
|
+ * path is valid */
|
||||||
|
+ if (conf->find_multipaths != FIND_MULTIPATHS_SMART)
|
||||||
|
+ return PATH_IS_NOT_VALID;
|
||||||
|
+
|
||||||
|
+ return PATH_IS_MAYBE_VALID;
|
||||||
|
+}
|
||||||
|
diff --git a/libmultipath/valid.h b/libmultipath/valid.h
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..ce1c7cbf
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libmultipath/valid.h
|
||||||
|
@@ -0,0 +1,42 @@
|
||||||
|
+/*
|
||||||
|
+ Copyright (c) 2020 Benjamin Marzinski, IBM
|
||||||
|
+
|
||||||
|
+ This program is free software; you can redistribute it and/or
|
||||||
|
+ modify it under the terms of the GNU General Public License
|
||||||
|
+ as published by the Free Software Foundation; either version 2
|
||||||
|
+ of the License, or (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ GNU General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU General Public License
|
||||||
|
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
+ */
|
||||||
|
+#ifndef _VALID_H
|
||||||
|
+#define _VALID_H
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * PATH_IS_VALID_NO_CHECK is returned when multipath should claim
|
||||||
|
+ * the path, regardless of whether is has been released to systemd
|
||||||
|
+ * already.
|
||||||
|
+ * PATH_IS_VALID is returned by is_path_valid, when the path is
|
||||||
|
+ * valid only if it hasn't been released to systemd already.
|
||||||
|
+ * PATH_IS_MAYBE_VALID is returned when the the path would be valid
|
||||||
|
+ * if other paths with the same wwid existed. It is up to the caller
|
||||||
|
+ * to check for these other paths.
|
||||||
|
+ */
|
||||||
|
+enum is_path_valid_result {
|
||||||
|
+ PATH_IS_ERROR = -1,
|
||||||
|
+ PATH_IS_NOT_VALID,
|
||||||
|
+ PATH_IS_VALID,
|
||||||
|
+ PATH_IS_VALID_NO_CHECK,
|
||||||
|
+ PATH_IS_MAYBE_VALID,
|
||||||
|
+ PATH_MAX_VALID_RESULT, /* only for bounds checking */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int is_path_valid(const char *name, struct config *conf, struct path *pp,
|
||||||
|
+ bool check_multipathd);
|
||||||
|
+
|
||||||
|
+#endif /* _VALID_D */
|
||||||
|
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
|
||||||
|
index 28a2150d..637cb0ab 100644
|
||||||
|
--- a/libmultipath/wwids.c
|
||||||
|
+++ b/libmultipath/wwids.c
|
||||||
|
@@ -289,19 +289,19 @@ out:
|
||||||
|
int
|
||||||
|
should_multipath(struct path *pp1, vector pathvec, vector mpvec)
|
||||||
|
{
|
||||||
|
- int i, ignore_new_devs, find_multipaths;
|
||||||
|
+ int i, find_multipaths;
|
||||||
|
struct path *pp2;
|
||||||
|
struct config *conf;
|
||||||
|
|
||||||
|
conf = get_multipath_config();
|
||||||
|
- ignore_new_devs = ignore_new_devs_on(conf);
|
||||||
|
- find_multipaths = find_multipaths_on(conf);
|
||||||
|
+ find_multipaths = conf->find_multipaths;
|
||||||
|
put_multipath_config(conf);
|
||||||
|
- if (!find_multipaths && !ignore_new_devs)
|
||||||
|
+ if (find_multipaths == FIND_MULTIPATHS_OFF ||
|
||||||
|
+ find_multipaths == FIND_MULTIPATHS_GREEDY)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
condlog(4, "checking if %s should be multipathed", pp1->dev);
|
||||||
|
- if (!ignore_new_devs) {
|
||||||
|
+ if (find_multipaths != FIND_MULTIPATHS_STRICT) {
|
||||||
|
char tmp_wwid[WWID_SIZE];
|
||||||
|
struct multipath *mp = find_mp_by_wwid(mpvec, pp1->wwid);
|
||||||
|
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 545ead87..953fab27 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -63,21 +63,18 @@
|
||||||
|
#include "propsel.h"
|
||||||
|
#include "time-util.h"
|
||||||
|
#include "file.h"
|
||||||
|
+#include "valid.h"
|
||||||
|
|
||||||
|
int logsink;
|
||||||
|
struct udev *udev;
|
||||||
|
struct config *multipath_conf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
- * Return values of configure(), print_cmd_valid(), and main().
|
||||||
|
- * RTVL_{YES,NO} are synonyms for RTVL_{OK,FAIL} for the CMD_VALID_PATH case.
|
||||||
|
+ * Return values of configure(), check_path_valid(), and main().
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
RTVL_OK = 0,
|
||||||
|
- RTVL_YES = RTVL_OK,
|
||||||
|
RTVL_FAIL = 1,
|
||||||
|
- RTVL_NO = RTVL_FAIL,
|
||||||
|
- RTVL_MAYBE, /* only used internally, never returned */
|
||||||
|
RTVL_RETRY, /* returned by configure(), not by main() */
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -269,9 +266,6 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (cmd == CMD_VALID_PATH)
|
||||||
|
- continue;
|
||||||
|
-
|
||||||
|
dm_get_map(mpp->alias, &mpp->size, params);
|
||||||
|
condlog(3, "params = %s", params);
|
||||||
|
dm_get_status(mpp->alias, status);
|
||||||
|
@@ -491,10 +485,11 @@ static int print_cmd_valid(int k, const vector pathvec,
|
||||||
|
struct timespec until;
|
||||||
|
struct path *pp;
|
||||||
|
|
||||||
|
- if (k != RTVL_YES && k != RTVL_NO && k != RTVL_MAYBE)
|
||||||
|
- return RTVL_NO;
|
||||||
|
+ if (k != PATH_IS_VALID && k != PATH_IS_NOT_VALID &&
|
||||||
|
+ k != PATH_IS_MAYBE_VALID)
|
||||||
|
+ return PATH_IS_NOT_VALID;
|
||||||
|
|
||||||
|
- if (k == RTVL_MAYBE) {
|
||||||
|
+ if (k == PATH_IS_MAYBE_VALID) {
|
||||||
|
/*
|
||||||
|
* Caller ensures that pathvec[0] is the path to
|
||||||
|
* examine.
|
||||||
|
@@ -504,7 +499,7 @@ static int print_cmd_valid(int k, const vector pathvec,
|
||||||
|
wait = find_multipaths_check_timeout(
|
||||||
|
pp, pp->find_multipaths_timeout, &until);
|
||||||
|
if (wait != FIND_MULTIPATHS_WAITING)
|
||||||
|
- k = RTVL_NO;
|
||||||
|
+ k = PATH_IS_NOT_VALID;
|
||||||
|
} else if (pathvec != NULL && (pp = VECTOR_SLOT(pathvec, 0)))
|
||||||
|
wait = find_multipaths_check_timeout(pp, 0, &until);
|
||||||
|
if (wait == FIND_MULTIPATHS_WAITING)
|
||||||
|
@@ -513,9 +508,9 @@ static int print_cmd_valid(int k, const vector pathvec,
|
||||||
|
else if (wait == FIND_MULTIPATHS_WAIT_DONE)
|
||||||
|
printf("FIND_MULTIPATHS_WAIT_UNTIL=\"0\"\n");
|
||||||
|
printf("DM_MULTIPATH_DEVICE_PATH=\"%d\"\n",
|
||||||
|
- k == RTVL_MAYBE ? 2 : k == RTVL_YES ? 1 : 0);
|
||||||
|
+ k == PATH_IS_MAYBE_VALID ? 2 : k == PATH_IS_VALID ? 1 : 0);
|
||||||
|
/* Never return RTVL_MAYBE */
|
||||||
|
- return k == RTVL_NO ? RTVL_NO : RTVL_YES;
|
||||||
|
+ return k == PATH_IS_NOT_VALID ? PATH_IS_NOT_VALID : PATH_IS_VALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -548,7 +543,6 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||||
|
int di_flag = 0;
|
||||||
|
char * refwwid = NULL;
|
||||||
|
char * dev = NULL;
|
||||||
|
- bool released = released_to_systemd();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* allocate core vectors to store paths and multipaths
|
||||||
|
@@ -573,7 +567,7 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||||
|
cmd != CMD_REMOVE_WWID &&
|
||||||
|
(filter_devnode(conf->blist_devnode,
|
||||||
|
conf->elist_devnode, dev) > 0)) {
|
||||||
|
- goto print_valid;
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -581,14 +575,10 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||||
|
* failing the translation is fatal (by policy)
|
||||||
|
*/
|
||||||
|
if (devpath) {
|
||||||
|
- int failed = get_refwwid(cmd, devpath, dev_type,
|
||||||
|
- pathvec, &refwwid);
|
||||||
|
+ get_refwwid(cmd, devpath, dev_type, pathvec, &refwwid);
|
||||||
|
if (!refwwid) {
|
||||||
|
condlog(4, "%s: failed to get wwid", devpath);
|
||||||
|
- if (failed == 2 && cmd == CMD_VALID_PATH)
|
||||||
|
- goto print_valid;
|
||||||
|
- else
|
||||||
|
- condlog(3, "scope is null");
|
||||||
|
+ condlog(3, "scope is null");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (cmd == CMD_REMOVE_WWID) {
|
||||||
|
@@ -614,53 +604,6 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
condlog(3, "scope limited to %s", refwwid);
|
||||||
|
- /* If you are ignoring the wwids file and find_multipaths is
|
||||||
|
- * set, you need to actually check if there are two available
|
||||||
|
- * paths to determine if this path should be multipathed. To
|
||||||
|
- * do this, we put off the check until after discovering all
|
||||||
|
- * the paths.
|
||||||
|
- * Paths listed in the wwids file are always considered valid.
|
||||||
|
- */
|
||||||
|
- if (cmd == CMD_VALID_PATH) {
|
||||||
|
- if (is_failed_wwid(refwwid) == WWID_IS_FAILED) {
|
||||||
|
- r = RTVL_NO;
|
||||||
|
- goto print_valid;
|
||||||
|
- }
|
||||||
|
- if ((!find_multipaths_on(conf) &&
|
||||||
|
- ignore_wwids_on(conf)) ||
|
||||||
|
- check_wwids_file(refwwid, 0) == 0)
|
||||||
|
- r = RTVL_YES;
|
||||||
|
- if (!ignore_wwids_on(conf))
|
||||||
|
- goto print_valid;
|
||||||
|
- /* At this point, either r==0 or find_multipaths_on. */
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * Shortcut for find_multipaths smart:
|
||||||
|
- * Quick check if path is already multipathed.
|
||||||
|
- */
|
||||||
|
- if (sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0),
|
||||||
|
- false)) {
|
||||||
|
- r = RTVL_YES;
|
||||||
|
- goto print_valid;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * DM_MULTIPATH_DEVICE_PATH=="0" means that we have
|
||||||
|
- * been called for this device already, and have
|
||||||
|
- * released it to systemd. Unless the device is now
|
||||||
|
- * already multipathed (see above), we can't try to
|
||||||
|
- * grab it, because setting SYSTEMD_READY=0 would
|
||||||
|
- * cause file systems to be unmounted.
|
||||||
|
- * Leave DM_MULTIPATH_DEVICE_PATH="0".
|
||||||
|
- */
|
||||||
|
- if (released) {
|
||||||
|
- r = RTVL_NO;
|
||||||
|
- goto print_valid;
|
||||||
|
- }
|
||||||
|
- if (r == RTVL_YES)
|
||||||
|
- goto print_valid;
|
||||||
|
- /* find_multipaths_on: Fall through to path detection */
|
||||||
|
- }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -701,59 +644,6 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (cmd == CMD_VALID_PATH) {
|
||||||
|
- struct path *pp;
|
||||||
|
- int fd;
|
||||||
|
-
|
||||||
|
- /* This only happens if find_multipaths and
|
||||||
|
- * ignore_wwids is set, and the path is not in WWIDs
|
||||||
|
- * file, not currently multipathed, and has
|
||||||
|
- * never been released to systemd.
|
||||||
|
- * If there is currently a multipath device matching
|
||||||
|
- * the refwwid, or there is more than one path matching
|
||||||
|
- * the refwwid, then the path is valid */
|
||||||
|
- if (VECTOR_SIZE(curmp) != 0) {
|
||||||
|
- r = RTVL_YES;
|
||||||
|
- goto print_valid;
|
||||||
|
- } else if (VECTOR_SIZE(pathvec) > 1)
|
||||||
|
- r = RTVL_YES;
|
||||||
|
- else
|
||||||
|
- r = RTVL_MAYBE;
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * If opening the path with O_EXCL fails, the path
|
||||||
|
- * is in use (e.g. mounted during initramfs processing).
|
||||||
|
- * We know that it's not used by dm-multipath.
|
||||||
|
- * We may not set SYSTEMD_READY=0 on such devices, it
|
||||||
|
- * might cause systemd to umount the device.
|
||||||
|
- * Use O_RDONLY, because udevd would trigger another
|
||||||
|
- * uevent for close-after-write.
|
||||||
|
- *
|
||||||
|
- * The O_EXCL check is potentially dangerous, because it may
|
||||||
|
- * race with other tasks trying to access the device. Therefore
|
||||||
|
- * this code is only executed if the path hasn't been released
|
||||||
|
- * to systemd earlier (see above).
|
||||||
|
- *
|
||||||
|
- * get_refwwid() above stores the path we examine in slot 0.
|
||||||
|
- */
|
||||||
|
- pp = VECTOR_SLOT(pathvec, 0);
|
||||||
|
- fd = open(udev_device_get_devnode(pp->udev),
|
||||||
|
- O_RDONLY|O_EXCL);
|
||||||
|
- if (fd >= 0)
|
||||||
|
- close(fd);
|
||||||
|
- else {
|
||||||
|
- condlog(3, "%s: path %s is in use: %s",
|
||||||
|
- __func__, pp->dev,
|
||||||
|
- strerror(errno));
|
||||||
|
- /*
|
||||||
|
- * Check if we raced with multipathd
|
||||||
|
- */
|
||||||
|
- r = sysfs_is_multipathed(VECTOR_SLOT(pathvec, 0),
|
||||||
|
- false) ? RTVL_YES : RTVL_NO;
|
||||||
|
- }
|
||||||
|
- goto print_valid;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
if (cmd != CMD_CREATE && cmd != CMD_DRY_RUN) {
|
||||||
|
r = RTVL_OK;
|
||||||
|
goto out;
|
||||||
|
@@ -766,10 +656,6 @@ configure (struct config *conf, enum mpath_cmds cmd,
|
||||||
|
conf->force_reload, cmd);
|
||||||
|
r = rc == CP_RETRY ? RTVL_RETRY : rc == CP_OK ? RTVL_OK : RTVL_FAIL;
|
||||||
|
|
||||||
|
-print_valid:
|
||||||
|
- if (cmd == CMD_VALID_PATH)
|
||||||
|
- r = print_cmd_valid(r, pathvec, conf);
|
||||||
|
-
|
||||||
|
out:
|
||||||
|
if (refwwid)
|
||||||
|
FREE(refwwid);
|
||||||
|
@@ -780,6 +666,112 @@ out:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+check_path_valid(const char *name, struct config *conf, bool is_uevent)
|
||||||
|
+{
|
||||||
|
+ int fd, r = PATH_IS_ERROR;
|
||||||
|
+ struct path *pp = NULL;
|
||||||
|
+ vector pathvec = NULL;
|
||||||
|
+
|
||||||
|
+ pp = alloc_path();
|
||||||
|
+ if (!pp)
|
||||||
|
+ return RTVL_FAIL;
|
||||||
|
+
|
||||||
|
+ r = is_path_valid(name, conf, pp, is_uevent);
|
||||||
|
+ if (r <= PATH_IS_ERROR || r >= PATH_MAX_VALID_RESULT)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ /* set path values if is_path_valid() didn't */
|
||||||
|
+ if (!pp->udev)
|
||||||
|
+ pp->udev = udev_device_new_from_subsystem_sysname(udev, "block",
|
||||||
|
+ name);
|
||||||
|
+ if (!pp->udev)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ if (!strlen(pp->dev_t)) {
|
||||||
|
+ dev_t devt = udev_device_get_devnum(pp->udev);
|
||||||
|
+ if (major(devt) == 0 && minor(devt) == 0)
|
||||||
|
+ goto fail;
|
||||||
|
+ snprintf(pp->dev_t, BLK_DEV_SIZE, "%d:%d", major(devt),
|
||||||
|
+ minor(devt));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pathvec = vector_alloc();
|
||||||
|
+ if (!pathvec)
|
||||||
|
+ goto fail;
|
||||||
|
+
|
||||||
|
+ if (store_path(pathvec, pp) != 0) {
|
||||||
|
+ free_path(pp);
|
||||||
|
+ goto fail;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((r == PATH_IS_VALID || r == PATH_IS_MAYBE_VALID) &&
|
||||||
|
+ released_to_systemd())
|
||||||
|
+ r = PATH_IS_NOT_VALID;
|
||||||
|
+
|
||||||
|
+ /* This state is only used to skip the released_to_systemd() check */
|
||||||
|
+ if (r == PATH_IS_VALID_NO_CHECK)
|
||||||
|
+ r = PATH_IS_VALID;
|
||||||
|
+
|
||||||
|
+ if (r != PATH_IS_MAYBE_VALID)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If opening the path with O_EXCL fails, the path
|
||||||
|
+ * is in use (e.g. mounted during initramfs processing).
|
||||||
|
+ * We know that it's not used by dm-multipath.
|
||||||
|
+ * We may not set SYSTEMD_READY=0 on such devices, it
|
||||||
|
+ * might cause systemd to umount the device.
|
||||||
|
+ * Use O_RDONLY, because udevd would trigger another
|
||||||
|
+ * uevent for close-after-write.
|
||||||
|
+ *
|
||||||
|
+ * The O_EXCL check is potentially dangerous, because it may
|
||||||
|
+ * race with other tasks trying to access the device. Therefore
|
||||||
|
+ * this code is only executed if the path hasn't been released
|
||||||
|
+ * to systemd earlier (see above).
|
||||||
|
+ */
|
||||||
|
+ fd = open(udev_device_get_devnode(pp->udev), O_RDONLY|O_EXCL);
|
||||||
|
+ if (fd >= 0)
|
||||||
|
+ close(fd);
|
||||||
|
+ else {
|
||||||
|
+ condlog(3, "%s: path %s is in use: %m", __func__, pp->dev);
|
||||||
|
+ /* Check if we raced with multipathd */
|
||||||
|
+ if (sysfs_is_multipathed(pp, false))
|
||||||
|
+ r = PATH_IS_VALID;
|
||||||
|
+ else
|
||||||
|
+ r = PATH_IS_NOT_VALID;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* For find_multipaths = SMART, if there is more than one path
|
||||||
|
+ * matching the refwwid, then the path is valid */
|
||||||
|
+ if (path_discovery(pathvec, DI_SYSFS | DI_WWID) < 0)
|
||||||
|
+ goto fail;
|
||||||
|
+ filter_pathvec(pathvec, pp->wwid);
|
||||||
|
+ if (VECTOR_SIZE(pathvec) > 1)
|
||||||
|
+ r = PATH_IS_VALID;
|
||||||
|
+ else
|
||||||
|
+ r = PATH_IS_MAYBE_VALID;
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ r = print_cmd_valid(r, pathvec, conf);
|
||||||
|
+ free_pathvec(pathvec, FREE_PATHS);
|
||||||
|
+ /*
|
||||||
|
+ * multipath -u must exit with status 0, otherwise udev won't
|
||||||
|
+ * import its output.
|
||||||
|
+ */
|
||||||
|
+ if (!is_uevent && r == PATH_IS_NOT_VALID)
|
||||||
|
+ return RTVL_FAIL;
|
||||||
|
+ return RTVL_OK;
|
||||||
|
+
|
||||||
|
+fail:
|
||||||
|
+ if (pathvec)
|
||||||
|
+ free_pathvec(pathvec, FREE_PATHS);
|
||||||
|
+ else
|
||||||
|
+ free_path(pp);
|
||||||
|
+ return RTVL_FAIL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
get_dev_type(char *dev) {
|
||||||
|
struct stat buf;
|
||||||
|
@@ -861,32 +853,6 @@ out:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int test_multipathd_socket(void)
|
||||||
|
-{
|
||||||
|
- int fd;
|
||||||
|
- /*
|
||||||
|
- * "multipath -u" may be run before the daemon is started. In this
|
||||||
|
- * case, systemd might own the socket but might delay multipathd
|
||||||
|
- * startup until some other unit (udev settle!) has finished
|
||||||
|
- * starting. With many LUNs, the listen backlog may be exceeded, which
|
||||||
|
- * would cause connect() to block. This causes udev workers calling
|
||||||
|
- * "multipath -u" to hang, and thus creates a deadlock, until "udev
|
||||||
|
- * settle" times out. To avoid this, call connect() in non-blocking
|
||||||
|
- * mode here, and take EAGAIN as indication for a filled-up systemd
|
||||||
|
- * backlog.
|
||||||
|
- */
|
||||||
|
-
|
||||||
|
- fd = __mpath_connect(1);
|
||||||
|
- if (fd == -1) {
|
||||||
|
- if (errno == EAGAIN)
|
||||||
|
- condlog(3, "daemon backlog exceeded");
|
||||||
|
- else
|
||||||
|
- return 0;
|
||||||
|
- } else
|
||||||
|
- close(fd);
|
||||||
|
- return 1;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
@@ -970,7 +936,11 @@ main (int argc, char *argv[])
|
||||||
|
conf->force_reload = FORCE_RELOAD_YES;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
- conf->find_multipaths |= _FIND_MULTIPATHS_I;
|
||||||
|
+ if (conf->find_multipaths == FIND_MULTIPATHS_ON ||
|
||||||
|
+ conf->find_multipaths == FIND_MULTIPATHS_STRICT)
|
||||||
|
+ conf->find_multipaths = FIND_MULTIPATHS_SMART;
|
||||||
|
+ else if (conf->find_multipaths == FIND_MULTIPATHS_OFF)
|
||||||
|
+ conf->find_multipaths = FIND_MULTIPATHS_GREEDY;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
r = dump_config(conf, NULL, NULL) ? RTVL_FAIL : RTVL_OK;
|
||||||
|
@@ -1064,15 +1034,10 @@ main (int argc, char *argv[])
|
||||||
|
condlog(0, "the -c option requires a path to check");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- if (cmd == CMD_VALID_PATH &&
|
||||||
|
- dev_type == DEV_UEVENT) {
|
||||||
|
- if (!test_multipathd_socket()) {
|
||||||
|
- condlog(3, "%s: daemon is not running", dev);
|
||||||
|
- if (!systemd_service_enabled(dev)) {
|
||||||
|
- r = print_cmd_valid(RTVL_NO, NULL, conf);
|
||||||
|
- goto out;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ if (cmd == CMD_VALID_PATH) {
|
||||||
|
+ char * name = convert_dev(dev, (dev_type == DEV_DEVNODE));
|
||||||
|
+ r = check_path_valid(name, conf, dev_type == DEV_UEVENT);
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd == CMD_REMOVE_WWID && !dev) {
|
||||||
|
@@ -1136,13 +1101,6 @@ out:
|
||||||
|
cleanup_prio();
|
||||||
|
cleanup_checkers();
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * multipath -u must exit with status 0, otherwise udev won't
|
||||||
|
- * import its output.
|
||||||
|
- */
|
||||||
|
- if (cmd == CMD_VALID_PATH && dev_type == DEV_UEVENT && r == RTVL_NO)
|
||||||
|
- r = RTVL_OK;
|
||||||
|
-
|
||||||
|
if (dev_type == DEV_UEVENT)
|
||||||
|
closelog();
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
530
0026-Unit-tests-for-is_path_valid.patch
Normal file
530
0026-Unit-tests-for-is_path_valid.patch
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 19 May 2020 12:08:43 -0500
|
||||||
|
Subject: [PATCH] Unit tests for is_path_valid()
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
tests/Makefile | 4 +-
|
||||||
|
tests/valid.c | 486 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 489 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 tests/valid.c
|
||||||
|
|
||||||
|
diff --git a/tests/Makefile b/tests/Makefile
|
||||||
|
index 1b8706a7..125553b8 100644
|
||||||
|
--- a/tests/Makefile
|
||||||
|
+++ b/tests/Makefile
|
||||||
|
@@ -13,7 +13,7 @@ CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir) \
|
||||||
|
LIBDEPS += -L$(multipathdir) -L$(mpathcmddir) -lmultipath -lmpathcmd -lcmocka
|
||||||
|
|
||||||
|
TESTS := uevent parser util dmevents hwtable blacklist unaligned vpd pgpolicy \
|
||||||
|
- alias directio
|
||||||
|
+ alias directio valid
|
||||||
|
|
||||||
|
.SILENT: $(TESTS:%=%.o)
|
||||||
|
.PRECIOUS: $(TESTS:%=%-test)
|
||||||
|
@@ -50,6 +50,8 @@ vpd-test_OBJDEPS := ../libmultipath/discovery.o
|
||||||
|
vpd-test_LIBDEPS := -ludev -lpthread -ldl
|
||||||
|
alias-test_TESTDEPS := test-log.o
|
||||||
|
alias-test_LIBDEPS := -lpthread -ldl
|
||||||
|
+valid-test_OBJDEPS := ../libmultipath/valid.o
|
||||||
|
+valid-test_LIBDEPS := -ludev -lpthread -ldl
|
||||||
|
ifneq ($(DIO_TEST_DEV),)
|
||||||
|
directio-test_LIBDEPS := -laio
|
||||||
|
endif
|
||||||
|
diff --git a/tests/valid.c b/tests/valid.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..693c72c5
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/valid.c
|
||||||
|
@@ -0,0 +1,486 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (c) 2020 Benjamin Marzinski, Redhat
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or
|
||||||
|
+ * modify it under the terms of the GNU General Public License
|
||||||
|
+ * as published by the Free Software Foundation; either version 2
|
||||||
|
+ * of the License, or (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License
|
||||||
|
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
+ *
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#define _GNU_SOURCE
|
||||||
|
+#include <stdint.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
+#include <stdarg.h>
|
||||||
|
+#include <stddef.h>
|
||||||
|
+#include <setjmp.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <cmocka.h>
|
||||||
|
+#include "globals.c"
|
||||||
|
+#include "util.h"
|
||||||
|
+#include "discovery.h"
|
||||||
|
+#include "wwids.h"
|
||||||
|
+#include "blacklist.h"
|
||||||
|
+#include "valid.h"
|
||||||
|
+
|
||||||
|
+int test_fd;
|
||||||
|
+struct udev_device {
|
||||||
|
+ int unused;
|
||||||
|
+} test_udev;
|
||||||
|
+
|
||||||
|
+bool __wrap_sysfs_is_multipathed(struct path *pp, bool set_wwid)
|
||||||
|
+{
|
||||||
|
+ bool is_multipathed = mock_type(bool);
|
||||||
|
+ assert_non_null(pp);
|
||||||
|
+ assert_int_not_equal(strlen(pp->dev), 0);
|
||||||
|
+ if (is_multipathed && set_wwid)
|
||||||
|
+ strlcpy(pp->wwid, mock_ptr_type(char *), WWID_SIZE);
|
||||||
|
+ return is_multipathed;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int __wrap___mpath_connect(int nonblocking)
|
||||||
|
+{
|
||||||
|
+ bool connected = mock_type(bool);
|
||||||
|
+ assert_int_equal(nonblocking, 1);
|
||||||
|
+ if (connected)
|
||||||
|
+ return test_fd;
|
||||||
|
+ errno = mock_type(int);
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int __wrap_systemd_service_enabled(const char *dev)
|
||||||
|
+{
|
||||||
|
+ return (int)mock_type(bool);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* There's no point in checking the return value here */
|
||||||
|
+int __wrap_mpath_disconnect(int fd)
|
||||||
|
+{
|
||||||
|
+ assert_int_equal(fd, test_fd);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct udev_device *__wrap_udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname)
|
||||||
|
+{
|
||||||
|
+ bool passed = mock_type(bool);
|
||||||
|
+ assert_string_equal(sysname, mock_ptr_type(char *));
|
||||||
|
+ if (passed)
|
||||||
|
+ return &test_udev;
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int __wrap_pathinfo(struct path *pp, struct config *conf, int mask)
|
||||||
|
+{
|
||||||
|
+ int ret = mock_type(int);
|
||||||
|
+ assert_string_equal(pp->dev, mock_ptr_type(char *));
|
||||||
|
+ assert_int_equal(mask, DI_SYSFS | DI_WWID | DI_BLACKLIST);
|
||||||
|
+ if (ret == PATHINFO_OK) {
|
||||||
|
+ pp->uid_attribute = "ID_TEST";
|
||||||
|
+ strlcpy(pp->wwid, mock_ptr_type(char *), WWID_SIZE);
|
||||||
|
+ } else
|
||||||
|
+ memset(pp->wwid, 0, WWID_SIZE);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int __wrap_filter_property(struct config *conf, struct udev_device *udev,
|
||||||
|
+ int lvl, const char *uid_attribute)
|
||||||
|
+{
|
||||||
|
+ int ret = mock_type(int);
|
||||||
|
+ assert_string_equal(uid_attribute, "ID_TEST");
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int __wrap_is_failed_wwid(const char *wwid)
|
||||||
|
+{
|
||||||
|
+ int ret = mock_type(int);
|
||||||
|
+ assert_string_equal(wwid, mock_ptr_type(char *));
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int __wrap_check_wwids_file(char *wwid, int write_wwid)
|
||||||
|
+{
|
||||||
|
+ bool passed = mock_type(bool);
|
||||||
|
+ assert_int_equal(write_wwid, 0);
|
||||||
|
+ assert_string_equal(wwid, mock_ptr_type(char *));
|
||||||
|
+ if (passed)
|
||||||
|
+ return 0;
|
||||||
|
+ else
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int __wrap_dm_map_present_by_uuid(const char *uuid)
|
||||||
|
+{
|
||||||
|
+ int ret = mock_type(int);
|
||||||
|
+ assert_string_equal(uuid, mock_ptr_type(char *));
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+enum {
|
||||||
|
+ STAGE_IS_MULTIPATHED,
|
||||||
|
+ STAGE_CHECK_MULTIPATHD,
|
||||||
|
+ STAGE_GET_UDEV_DEVICE,
|
||||||
|
+ STAGE_PATHINFO,
|
||||||
|
+ STAGE_FILTER_PROPERTY,
|
||||||
|
+ STAGE_IS_FAILED,
|
||||||
|
+ STAGE_CHECK_WWIDS,
|
||||||
|
+ STAGE_UUID_PRESENT,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+enum {
|
||||||
|
+ CHECK_MPATHD_RUNNING,
|
||||||
|
+ CHECK_MPATHD_EAGAIN,
|
||||||
|
+ CHECK_MPATHD_ENABLED,
|
||||||
|
+ CHECK_MPATHD_SKIP,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* setup the test to continue past the given stage in is_path_valid() */
|
||||||
|
+static void setup_passing(char *name, char *wwid, unsigned int check_multipathd,
|
||||||
|
+ unsigned int stage)
|
||||||
|
+{
|
||||||
|
+ will_return(__wrap_sysfs_is_multipathed, false);
|
||||||
|
+ if (stage == STAGE_IS_MULTIPATHED)
|
||||||
|
+ return;
|
||||||
|
+ if (check_multipathd == CHECK_MPATHD_RUNNING)
|
||||||
|
+ will_return(__wrap___mpath_connect, true);
|
||||||
|
+ else if (check_multipathd == CHECK_MPATHD_EAGAIN) {
|
||||||
|
+ will_return(__wrap___mpath_connect, false);
|
||||||
|
+ will_return(__wrap___mpath_connect, EAGAIN);
|
||||||
|
+ } else if (check_multipathd == CHECK_MPATHD_ENABLED) {
|
||||||
|
+ will_return(__wrap___mpath_connect, false);
|
||||||
|
+ will_return(__wrap___mpath_connect, ECONNREFUSED);
|
||||||
|
+ will_return(__wrap_systemd_service_enabled, true);
|
||||||
|
+ }
|
||||||
|
+ /* nothing for CHECK_MPATHD_SKIP */
|
||||||
|
+ if (stage == STAGE_CHECK_MULTIPATHD)
|
||||||
|
+ return;
|
||||||
|
+ will_return(__wrap_udev_device_new_from_subsystem_sysname, true);
|
||||||
|
+ will_return(__wrap_udev_device_new_from_subsystem_sysname,
|
||||||
|
+ name);
|
||||||
|
+ if (stage == STAGE_GET_UDEV_DEVICE)
|
||||||
|
+ return;
|
||||||
|
+ will_return(__wrap_pathinfo, PATHINFO_OK);
|
||||||
|
+ will_return(__wrap_pathinfo, name);
|
||||||
|
+ will_return(__wrap_pathinfo, wwid);
|
||||||
|
+ if (stage == STAGE_PATHINFO)
|
||||||
|
+ return;
|
||||||
|
+ will_return(__wrap_filter_property, MATCH_PROPERTY_BLIST_EXCEPT);
|
||||||
|
+ if (stage == STAGE_FILTER_PROPERTY)
|
||||||
|
+ return;
|
||||||
|
+ will_return(__wrap_is_failed_wwid, WWID_IS_NOT_FAILED);
|
||||||
|
+ will_return(__wrap_is_failed_wwid, wwid);
|
||||||
|
+ if (stage == STAGE_IS_FAILED)
|
||||||
|
+ return;
|
||||||
|
+ will_return(__wrap_check_wwids_file, false);
|
||||||
|
+ will_return(__wrap_check_wwids_file, wwid);
|
||||||
|
+ if (stage == STAGE_CHECK_WWIDS)
|
||||||
|
+ return;
|
||||||
|
+ will_return(__wrap_dm_map_present_by_uuid, 0);
|
||||||
|
+ will_return(__wrap_dm_map_present_by_uuid, wwid);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_bad_arguments(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char too_long[FILE_NAME_SIZE + 1];
|
||||||
|
+
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ /* test NULL pointers */
|
||||||
|
+ assert_int_equal(is_path_valid("test", &conf, NULL, true),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+ assert_int_equal(is_path_valid("test", NULL, &pp, true),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+ assert_int_equal(is_path_valid(NULL, &conf, &pp, true),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+ /* test undefined find_multipaths */
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_UNDEF;
|
||||||
|
+ assert_int_equal(is_path_valid("test", &conf, &pp, true),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+ /* test name too long */
|
||||||
|
+ memset(too_long, 'x', sizeof(too_long));
|
||||||
|
+ too_long[sizeof(too_long) - 1] = '\0';
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+ assert_int_equal(is_path_valid(too_long, &conf, &pp, true),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_sysfs_is_multipathed(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char *name = "test";
|
||||||
|
+ char *wwid = "test_wwid";
|
||||||
|
+
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+ /* test for already existing multiapthed device */
|
||||||
|
+ will_return(__wrap_sysfs_is_multipathed, true);
|
||||||
|
+ will_return(__wrap_sysfs_is_multipathed, wwid);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
|
||||||
|
+ PATH_IS_VALID_NO_CHECK);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ assert_string_equal(pp.wwid, wwid);
|
||||||
|
+ /* test for wwid device with empty wwid */
|
||||||
|
+ will_return(__wrap_sysfs_is_multipathed, true);
|
||||||
|
+ will_return(__wrap_sysfs_is_multipathed, "");
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_check_multipathd(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char *name = "test";
|
||||||
|
+
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+ /* test failed check to see if multipathd is active */
|
||||||
|
+ will_return(__wrap_sysfs_is_multipathed, false);
|
||||||
|
+ will_return(__wrap___mpath_connect, false);
|
||||||
|
+ will_return(__wrap___mpath_connect, ECONNREFUSED);
|
||||||
|
+ will_return(__wrap_systemd_service_enabled, false);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ /* test pass because service is enabled. fail getting udev */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ setup_passing(name, NULL, CHECK_MPATHD_ENABLED, STAGE_CHECK_MULTIPATHD);
|
||||||
|
+ will_return(__wrap_udev_device_new_from_subsystem_sysname, false);
|
||||||
|
+ will_return(__wrap_udev_device_new_from_subsystem_sysname,
|
||||||
|
+ name);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ /* test pass because connect returned EAGAIN. fail getting udev */
|
||||||
|
+ setup_passing(name, NULL, CHECK_MPATHD_EAGAIN, STAGE_CHECK_MULTIPATHD);
|
||||||
|
+ will_return(__wrap_udev_device_new_from_subsystem_sysname, false);
|
||||||
|
+ will_return(__wrap_udev_device_new_from_subsystem_sysname,
|
||||||
|
+ name);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+ /* test pass because connect succeeded. fail getting udev */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ setup_passing(name, NULL, CHECK_MPATHD_RUNNING, STAGE_CHECK_MULTIPATHD);
|
||||||
|
+ will_return(__wrap_udev_device_new_from_subsystem_sysname, false);
|
||||||
|
+ will_return(__wrap_udev_device_new_from_subsystem_sysname,
|
||||||
|
+ name);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_pathinfo(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char *name = "test";
|
||||||
|
+
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+ /* Test pathinfo blacklisting device */
|
||||||
|
+ setup_passing(name, NULL, CHECK_MPATHD_SKIP, STAGE_GET_UDEV_DEVICE);
|
||||||
|
+ will_return(__wrap_pathinfo, PATHINFO_SKIPPED);
|
||||||
|
+ will_return(__wrap_pathinfo, name);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ assert_ptr_equal(pp.udev, &test_udev);
|
||||||
|
+ /* Test pathinfo failing */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ setup_passing(name, NULL, CHECK_MPATHD_SKIP, STAGE_GET_UDEV_DEVICE);
|
||||||
|
+ will_return(__wrap_pathinfo, PATHINFO_FAILED);
|
||||||
|
+ will_return(__wrap_pathinfo, name);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+ /* Test blank wwid */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ setup_passing(name, NULL, CHECK_MPATHD_SKIP, STAGE_GET_UDEV_DEVICE);
|
||||||
|
+ will_return(__wrap_pathinfo, PATHINFO_OK);
|
||||||
|
+ will_return(__wrap_pathinfo, name);
|
||||||
|
+ will_return(__wrap_pathinfo, "");
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_filter_property(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char *name = "test";
|
||||||
|
+ char *wwid = "test-wwid";
|
||||||
|
+
|
||||||
|
+ /* test blacklist property */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_PATHINFO);
|
||||||
|
+ will_return(__wrap_filter_property, MATCH_PROPERTY_BLIST);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+ assert_ptr_equal(pp.udev, &test_udev);
|
||||||
|
+ assert_string_equal(pp.wwid, wwid);
|
||||||
|
+ /* test missing property */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_PATHINFO);
|
||||||
|
+ will_return(__wrap_filter_property, MATCH_PROPERTY_BLIST_MISSING);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+ /* test MATCH_NOTHING fail on is_failed_wwid */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_PATHINFO);
|
||||||
|
+ will_return(__wrap_filter_property, MATCH_NOTHING);
|
||||||
|
+ will_return(__wrap_is_failed_wwid, WWID_IS_FAILED);
|
||||||
|
+ will_return(__wrap_is_failed_wwid, wwid);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_is_failed_wwid(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char *name = "test";
|
||||||
|
+ char *wwid = "test-wwid";
|
||||||
|
+
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+ /* Test wwid failed */
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_FILTER_PROPERTY);
|
||||||
|
+ will_return(__wrap_is_failed_wwid, WWID_IS_FAILED);
|
||||||
|
+ will_return(__wrap_is_failed_wwid, wwid);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ assert_ptr_equal(pp.udev, &test_udev);
|
||||||
|
+ assert_string_equal(pp.wwid, wwid);
|
||||||
|
+ /* test is_failed_wwid error */
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_FILTER_PROPERTY);
|
||||||
|
+ will_return(__wrap_is_failed_wwid, WWID_FAILED_ERROR);
|
||||||
|
+ will_return(__wrap_is_failed_wwid, wwid);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_ERROR);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_greedy(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char *name = "test";
|
||||||
|
+ char *wwid = "test-wwid";
|
||||||
|
+
|
||||||
|
+ /* test greedy success with checking multipathd */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_GREEDY;
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_RUNNING, STAGE_IS_FAILED);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
|
||||||
|
+ PATH_IS_VALID);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ assert_ptr_equal(pp.udev, &test_udev);
|
||||||
|
+ assert_string_equal(pp.wwid, wwid);
|
||||||
|
+ /* test greedy success without checking multiapthd */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_IS_FAILED);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_VALID);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_check_wwids(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char *name = "test";
|
||||||
|
+ char *wwid = "test-wwid";
|
||||||
|
+
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_EAGAIN, STAGE_IS_FAILED);
|
||||||
|
+ will_return(__wrap_check_wwids_file, true);
|
||||||
|
+ will_return(__wrap_check_wwids_file, wwid);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
|
||||||
|
+ PATH_IS_VALID_NO_CHECK);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ assert_ptr_equal(pp.udev, &test_udev);
|
||||||
|
+ assert_string_equal(pp.wwid, wwid);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test_check_uuid_present(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char *name = "test";
|
||||||
|
+ char *wwid = "test-wwid";
|
||||||
|
+
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_ENABLED, STAGE_CHECK_WWIDS);
|
||||||
|
+ will_return(__wrap_dm_map_present_by_uuid, 1);
|
||||||
|
+ will_return(__wrap_dm_map_present_by_uuid, wwid);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, true),
|
||||||
|
+ PATH_IS_VALID);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ assert_ptr_equal(pp.udev, &test_udev);
|
||||||
|
+ assert_string_equal(pp.wwid, wwid);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static void test_find_multipaths(void **state)
|
||||||
|
+{
|
||||||
|
+ struct path pp;
|
||||||
|
+ char *name = "test";
|
||||||
|
+ char *wwid = "test-wwid";
|
||||||
|
+
|
||||||
|
+ /* test find_multipaths = FIND_MULTIPATHS_STRICT */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_UUID_PRESENT);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ assert_ptr_equal(pp.udev, &test_udev);
|
||||||
|
+ assert_string_equal(pp.wwid, wwid);
|
||||||
|
+ /* test find_multipaths = FIND_MULTIPATHS_OFF */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_OFF;
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_UUID_PRESENT);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+ /* test find_multipaths = FIND_MULTIPATHS_ON */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_ON;
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_UUID_PRESENT);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_NOT_VALID);
|
||||||
|
+ /* test find_multipaths = FIND_MULTIPATHS_SMART */
|
||||||
|
+ memset(&pp, 0, sizeof(pp));
|
||||||
|
+ conf.find_multipaths = FIND_MULTIPATHS_SMART;
|
||||||
|
+ setup_passing(name, wwid, CHECK_MPATHD_SKIP, STAGE_UUID_PRESENT);
|
||||||
|
+ assert_int_equal(is_path_valid(name, &conf, &pp, false),
|
||||||
|
+ PATH_IS_MAYBE_VALID);
|
||||||
|
+ assert_string_equal(pp.dev, name);
|
||||||
|
+ assert_ptr_equal(pp.udev, &test_udev);
|
||||||
|
+ assert_string_equal(pp.wwid, wwid);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int test_valid(void)
|
||||||
|
+{
|
||||||
|
+ const struct CMUnitTest tests[] = {
|
||||||
|
+ cmocka_unit_test(test_bad_arguments),
|
||||||
|
+ cmocka_unit_test(test_sysfs_is_multipathed),
|
||||||
|
+ cmocka_unit_test(test_check_multipathd),
|
||||||
|
+ cmocka_unit_test(test_pathinfo),
|
||||||
|
+ cmocka_unit_test(test_filter_property),
|
||||||
|
+ cmocka_unit_test(test_is_failed_wwid),
|
||||||
|
+ cmocka_unit_test(test_greedy),
|
||||||
|
+ cmocka_unit_test(test_check_wwids),
|
||||||
|
+ cmocka_unit_test(test_check_uuid_present),
|
||||||
|
+ cmocka_unit_test(test_find_multipaths),
|
||||||
|
+ };
|
||||||
|
+ return cmocka_run_group_tests(tests, NULL, NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int main(void)
|
||||||
|
+{
|
||||||
|
+ int ret = 0;
|
||||||
|
+ ret += test_valid();
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
205
0027-libmultipath-simplify-failed-wwid-code.patch
Normal file
205
0027-libmultipath-simplify-failed-wwid-code.patch
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 19 May 2020 12:08:44 -0500
|
||||||
|
Subject: [PATCH] libmultipath: simplify failed wwid code
|
||||||
|
|
||||||
|
The (is|mark|unmark)_failed_wwid code is needlessly complicated.
|
||||||
|
Locking a file is necssary if multiple processes could otherwise be
|
||||||
|
writing to it at the same time. That is not the case with the
|
||||||
|
failed_wwids files. They can simply be empty files in a directory. Even
|
||||||
|
with all the locking in place, two processes accessing or modifying a
|
||||||
|
file at the same time will still race. And even without the locking, if
|
||||||
|
two processes try to access or modify a file at the same time, they will
|
||||||
|
both see a reasonable result, and will leave the files in a valid state
|
||||||
|
afterwards.
|
||||||
|
|
||||||
|
Instead of doing all the locking work (which made it necessary to write
|
||||||
|
a file, even just to check if a file existed), simply check for files
|
||||||
|
with lstat(), create them with open(), and remove them with unlink().
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/wwids.c | 131 ++++++++++++++++++-------------------------
|
||||||
|
1 file changed, 56 insertions(+), 75 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
|
||||||
|
index 637cb0ab..aab5da8a 100644
|
||||||
|
--- a/libmultipath/wwids.c
|
||||||
|
+++ b/libmultipath/wwids.c
|
||||||
|
@@ -6,6 +6,7 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
+#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "checkers.h"
|
||||||
|
@@ -348,109 +349,89 @@ remember_wwid(char *wwid)
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char shm_dir[] = MULTIPATH_SHM_BASE "failed_wwids";
|
||||||
|
-static const char shm_lock[] = ".lock";
|
||||||
|
-static const char shm_header[] = "multipath shm lock file, don't edit";
|
||||||
|
-static char _shm_lock_path[sizeof(shm_dir)+sizeof(shm_lock)];
|
||||||
|
-static const char *shm_lock_path = &_shm_lock_path[0];
|
||||||
|
|
||||||
|
-static void init_shm_paths(void)
|
||||||
|
+static void print_failed_wwid_result(const char * msg, const char *wwid, int r)
|
||||||
|
{
|
||||||
|
- snprintf(_shm_lock_path, sizeof(_shm_lock_path),
|
||||||
|
- "%s/%s", shm_dir, shm_lock);
|
||||||
|
+ switch(r) {
|
||||||
|
+ case WWID_FAILED_ERROR:
|
||||||
|
+ condlog(1, "%s: %s: %m", msg, wwid);
|
||||||
|
+ return;
|
||||||
|
+ case WWID_IS_FAILED:
|
||||||
|
+ case WWID_IS_NOT_FAILED:
|
||||||
|
+ condlog(4, "%s: %s is %s", msg, wwid,
|
||||||
|
+ r == WWID_IS_FAILED ? "failed" : "good");
|
||||||
|
+ return;
|
||||||
|
+ case WWID_FAILED_CHANGED:
|
||||||
|
+ condlog(3, "%s: %s", msg, wwid);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
-static pthread_once_t shm_path_once = PTHREAD_ONCE_INIT;
|
||||||
|
-
|
||||||
|
-static int multipath_shm_open(bool rw)
|
||||||
|
+int is_failed_wwid(const char *wwid)
|
||||||
|
{
|
||||||
|
- int fd;
|
||||||
|
- int can_write;
|
||||||
|
-
|
||||||
|
- pthread_once(&shm_path_once, init_shm_paths);
|
||||||
|
- fd = open_file(shm_lock_path, &can_write, shm_header);
|
||||||
|
+ struct stat st;
|
||||||
|
+ char path[PATH_MAX];
|
||||||
|
+ int r;
|
||||||
|
|
||||||
|
- if (fd >= 0 && rw && !can_write) {
|
||||||
|
- close(fd);
|
||||||
|
- condlog(1, "failed to open %s for writing", shm_dir);
|
||||||
|
+ if (safe_sprintf(path, "%s/%s", shm_dir, wwid)) {
|
||||||
|
+ condlog(1, "%s: path name overflow", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return fd;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void multipath_shm_close(void *arg)
|
||||||
|
-{
|
||||||
|
- long fd = (long)arg;
|
||||||
|
+ if (lstat(path, &st) == 0)
|
||||||
|
+ r = WWID_IS_FAILED;
|
||||||
|
+ else if (errno == ENOENT)
|
||||||
|
+ r = WWID_IS_NOT_FAILED;
|
||||||
|
+ else
|
||||||
|
+ r = WWID_FAILED_ERROR;
|
||||||
|
|
||||||
|
- close(fd);
|
||||||
|
- unlink(shm_lock_path);
|
||||||
|
+ print_failed_wwid_result("is_failed", wwid, r);
|
||||||
|
+ return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int _failed_wwid_op(const char *wwid, bool rw,
|
||||||
|
- int (*func)(const char *), const char *msg)
|
||||||
|
+int mark_failed_wwid(const char *wwid)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
- long lockfd;
|
||||||
|
- int r = -1;
|
||||||
|
+ int r, fd;
|
||||||
|
|
||||||
|
if (safe_sprintf(path, "%s/%s", shm_dir, wwid)) {
|
||||||
|
condlog(1, "%s: path name overflow", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- lockfd = multipath_shm_open(rw);
|
||||||
|
- if (lockfd == -1)
|
||||||
|
+ if (ensure_directories_exist(path, 0700) < 0) {
|
||||||
|
+ condlog(1, "%s: can't setup directories", __func__);
|
||||||
|
return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- pthread_cleanup_push(multipath_shm_close, (void *)lockfd);
|
||||||
|
- r = func(path);
|
||||||
|
- pthread_cleanup_pop(1);
|
||||||
|
-
|
||||||
|
- if (r == WWID_FAILED_ERROR)
|
||||||
|
- condlog(1, "%s: %s: %s", msg, wwid, strerror(errno));
|
||||||
|
- else if (r == WWID_FAILED_CHANGED)
|
||||||
|
- condlog(3, "%s: %s", msg, wwid);
|
||||||
|
- else if (!rw)
|
||||||
|
- condlog(4, "%s: %s is %s", msg, wwid,
|
||||||
|
- r == WWID_IS_FAILED ? "failed" : "good");
|
||||||
|
+ fd = open(path, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR);
|
||||||
|
+ if (fd >= 0) {
|
||||||
|
+ close(fd);
|
||||||
|
+ r = WWID_FAILED_CHANGED;
|
||||||
|
+ } else if (errno == EEXIST)
|
||||||
|
+ r = WWID_FAILED_UNCHANGED;
|
||||||
|
+ else
|
||||||
|
+ r = WWID_FAILED_ERROR;
|
||||||
|
|
||||||
|
+ print_failed_wwid_result("mark_failed", wwid, r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int _is_failed(const char *path)
|
||||||
|
+int unmark_failed_wwid(const char *wwid)
|
||||||
|
{
|
||||||
|
- struct stat st;
|
||||||
|
+ char path[PATH_MAX];
|
||||||
|
+ int r;
|
||||||
|
|
||||||
|
- if (lstat(path, &st) == 0)
|
||||||
|
- return WWID_IS_FAILED;
|
||||||
|
+ if (safe_sprintf(path, "%s/%s", shm_dir, wwid)) {
|
||||||
|
+ condlog(1, "%s: path name overflow", __func__);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (unlink(path) == 0)
|
||||||
|
+ r = WWID_FAILED_CHANGED;
|
||||||
|
else if (errno == ENOENT)
|
||||||
|
- return WWID_IS_NOT_FAILED;
|
||||||
|
+ r = WWID_FAILED_UNCHANGED;
|
||||||
|
else
|
||||||
|
- return WWID_FAILED_ERROR;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int _mark_failed(const char *path)
|
||||||
|
-{
|
||||||
|
- /* Called from _failed_wwid_op: we know that shm_lock_path exists */
|
||||||
|
- if (_is_failed(path) == WWID_IS_FAILED)
|
||||||
|
- return WWID_FAILED_UNCHANGED;
|
||||||
|
- return (link(shm_lock_path, path) == 0 ? WWID_FAILED_CHANGED :
|
||||||
|
- WWID_FAILED_ERROR);
|
||||||
|
-}
|
||||||
|
+ r = WWID_FAILED_ERROR;
|
||||||
|
|
||||||
|
-static int _unmark_failed(const char *path)
|
||||||
|
-{
|
||||||
|
- if (_is_failed(path) == WWID_IS_NOT_FAILED)
|
||||||
|
- return WWID_FAILED_UNCHANGED;
|
||||||
|
- return (unlink(path) == 0 ? WWID_FAILED_CHANGED : WWID_FAILED_ERROR);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-#define declare_failed_wwid_op(op, rw) \
|
||||||
|
-int op ## _wwid(const char *wwid) \
|
||||||
|
-{ \
|
||||||
|
- return _failed_wwid_op(wwid, (rw), _ ## op, #op); \
|
||||||
|
+ print_failed_wwid_result("unmark_failed", wwid, r);
|
||||||
|
+ return r;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
-declare_failed_wwid_op(is_failed, false)
|
||||||
|
-declare_failed_wwid_op(mark_failed, true)
|
||||||
|
-declare_failed_wwid_op(unmark_failed, true)
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,96 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 19 May 2020 12:08:45 -0500
|
||||||
|
Subject: [PATCH] libmultipath: use atomic linkat() in mark_failed_wwid()
|
||||||
|
|
||||||
|
This keeps (almost) the simplicity of the previous patch, while
|
||||||
|
making sure that the return value of mark_failed_wwid()
|
||||||
|
(WWID_FAILED_CHANGED vs. WWID_FAILED_UNCHANGED) is correct, even
|
||||||
|
if several processes access this WWID at the same time.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/wwids.c | 42 +++++++++++++++++++++++++++++-------------
|
||||||
|
1 file changed, 29 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
|
||||||
|
index aab5da8a..61d9c39e 100644
|
||||||
|
--- a/libmultipath/wwids.c
|
||||||
|
+++ b/libmultipath/wwids.c
|
||||||
|
@@ -374,7 +374,7 @@ int is_failed_wwid(const char *wwid)
|
||||||
|
|
||||||
|
if (safe_sprintf(path, "%s/%s", shm_dir, wwid)) {
|
||||||
|
condlog(1, "%s: path name overflow", __func__);
|
||||||
|
- return -1;
|
||||||
|
+ return WWID_FAILED_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lstat(path, &st) == 0)
|
||||||
|
@@ -390,27 +390,43 @@ int is_failed_wwid(const char *wwid)
|
||||||
|
|
||||||
|
int mark_failed_wwid(const char *wwid)
|
||||||
|
{
|
||||||
|
- char path[PATH_MAX];
|
||||||
|
- int r, fd;
|
||||||
|
+ char tmpfile[WWID_SIZE + 2 * sizeof(long) + 1];
|
||||||
|
+ int r = WWID_FAILED_ERROR, fd, dfd;
|
||||||
|
|
||||||
|
- if (safe_sprintf(path, "%s/%s", shm_dir, wwid)) {
|
||||||
|
- condlog(1, "%s: path name overflow", __func__);
|
||||||
|
- return -1;
|
||||||
|
+ dfd = open(shm_dir, O_RDONLY|O_DIRECTORY);
|
||||||
|
+ if (dfd == -1 && errno == ENOENT) {
|
||||||
|
+ char path[sizeof(shm_dir) + 2];
|
||||||
|
+
|
||||||
|
+ /* arg for ensure_directories_exist() must not end with "/" */
|
||||||
|
+ safe_sprintf(path, "%s/_", shm_dir);
|
||||||
|
+ ensure_directories_exist(path, 0700);
|
||||||
|
+ dfd = open(shm_dir, O_RDONLY|O_DIRECTORY);
|
||||||
|
}
|
||||||
|
- if (ensure_directories_exist(path, 0700) < 0) {
|
||||||
|
- condlog(1, "%s: can't setup directories", __func__);
|
||||||
|
- return -1;
|
||||||
|
+ if (dfd == -1) {
|
||||||
|
+ condlog(1, "%s: can't setup %s: %m", __func__, shm_dir);
|
||||||
|
+ return WWID_FAILED_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
- fd = open(path, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR);
|
||||||
|
- if (fd >= 0) {
|
||||||
|
+ safe_sprintf(tmpfile, "%s.%lx", wwid, (long)getpid());
|
||||||
|
+ fd = openat(dfd, tmpfile, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR);
|
||||||
|
+ if (fd >= 0)
|
||||||
|
close(fd);
|
||||||
|
+ else
|
||||||
|
+ goto out_closedir;
|
||||||
|
+
|
||||||
|
+ if (linkat(dfd, tmpfile, dfd, wwid, 0) == 0)
|
||||||
|
r = WWID_FAILED_CHANGED;
|
||||||
|
- } else if (errno == EEXIST)
|
||||||
|
+ else if (errno == EEXIST)
|
||||||
|
r = WWID_FAILED_UNCHANGED;
|
||||||
|
else
|
||||||
|
r = WWID_FAILED_ERROR;
|
||||||
|
|
||||||
|
+ if (unlinkat(dfd, tmpfile, 0) == -1)
|
||||||
|
+ condlog(2, "%s: failed to unlink %s/%s: %m",
|
||||||
|
+ __func__, shm_dir, tmpfile);
|
||||||
|
+
|
||||||
|
+out_closedir:
|
||||||
|
+ close(dfd);
|
||||||
|
print_failed_wwid_result("mark_failed", wwid, r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
@@ -422,7 +438,7 @@ int unmark_failed_wwid(const char *wwid)
|
||||||
|
|
||||||
|
if (safe_sprintf(path, "%s/%s", shm_dir, wwid)) {
|
||||||
|
condlog(1, "%s: path name overflow", __func__);
|
||||||
|
- return -1;
|
||||||
|
+ return WWID_FAILED_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlink(path) == 0)
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
41
0029-fix-boolean-value-with-json-c-0.14.patch
Normal file
41
0029-fix-boolean-value-with-json-c-0.14.patch
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "mail@eworm.de" <mail@eworm.de>
|
||||||
|
Date: Sat, 25 Apr 2020 21:11:13 +0200
|
||||||
|
Subject: [PATCH] fix boolean value with json-c 0.14
|
||||||
|
|
||||||
|
Upstream json-c removed the TRUE and FALSE defines in commit
|
||||||
|
0992aac61f8b087efd7094e9ac2b84fa9c040fcd.
|
||||||
|
|
||||||
|
[mwilck]: Use stdbool.h, and keep the log message unchanged.
|
||||||
|
|
||||||
|
Signed-off-by: Christian Hesse <mail@eworm.de>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libdmmp/libdmmp_private.h | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libdmmp/libdmmp_private.h b/libdmmp/libdmmp_private.h
|
||||||
|
index ac85b63f..b1a6ddea 100644
|
||||||
|
--- a/libdmmp/libdmmp_private.h
|
||||||
|
+++ b/libdmmp/libdmmp_private.h
|
||||||
|
@@ -30,6 +30,7 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
+#include <stdbool.h>
|
||||||
|
#include <json.h>
|
||||||
|
|
||||||
|
#include "libdmmp/libdmmp.h"
|
||||||
|
@@ -82,7 +83,7 @@ static out_type func_name(struct dmmp_context *ctx, const char *var_name) { \
|
||||||
|
do { \
|
||||||
|
json_type j_type = json_type_null; \
|
||||||
|
json_object *j_obj_tmp = NULL; \
|
||||||
|
- if (json_object_object_get_ex(j_obj, key, &j_obj_tmp) != TRUE) { \
|
||||||
|
+ if (json_object_object_get_ex(j_obj, key, &j_obj_tmp) != true) { \
|
||||||
|
_error(ctx, "Invalid JSON output from multipathd IPC: " \
|
||||||
|
"key '%s' not found", key); \
|
||||||
|
rc = DMMP_ERR_IPC_ERROR; \
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,46 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 4 Jun 2020 18:20:06 -0500
|
||||||
|
Subject: [PATCH] libmultipath: fix condlog NULL argument in uevent_get_env_var
|
||||||
|
|
||||||
|
uevent_get_env_var() could call condlog with p == NULL. On gcc 10,
|
||||||
|
this triggers warnings like:
|
||||||
|
|
||||||
|
In file included from uevent.c:47:
|
||||||
|
In function 'uevent_get_env_var',
|
||||||
|
inlined from 'uevent_get_wwid' at uevent.c:170:8:
|
||||||
|
debug.h:13:2: error: '%s' directive argument is null
|
||||||
|
[-Werror=format-overflow=]
|
||||||
|
13 | dlog(logsink, prio, fmt "\n", ##args)
|
||||||
|
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
uevent.c:132:2: note: in expansion of macro 'condlog'
|
||||||
|
132 | condlog(4, "%s: %s -> '%s'", __func__, attr, p);
|
||||||
|
| ^~~~~~~
|
||||||
|
uevent.c: In function 'uevent_get_wwid':
|
||||||
|
uevent.c:132:25: note: format string is defined here
|
||||||
|
132 | condlog(4, "%s: %s -> '%s'", __func__, attr, p);
|
||||||
|
| ^~
|
||||||
|
|
||||||
|
If p is NULL, use "(null)" instead.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/uevent.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c
|
||||||
|
index d38e8a7f..e0d13b11 100644
|
||||||
|
--- a/libmultipath/uevent.c
|
||||||
|
+++ b/libmultipath/uevent.c
|
||||||
|
@@ -129,7 +129,7 @@ static const char* uevent_get_env_var(const struct uevent *uev,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- condlog(4, "%s: %s -> '%s'", __func__, attr, p);
|
||||||
|
+ condlog(4, "%s: %s -> '%s'", __func__, attr, p ?: "(null)");
|
||||||
|
return p;
|
||||||
|
|
||||||
|
invalid:
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Wed, 21 Aug 2019 16:07:12 +0200
|
||||||
|
Subject: [PATCH] libmultipath: set "enable_foreign" to NONE by default
|
||||||
|
|
||||||
|
This has been requested by NetApp.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/defaults.h | 4 ++--
|
||||||
|
multipath/multipath.conf.5 | 5 +++--
|
||||||
|
2 files changed, 5 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
|
||||||
|
index e5ee6afe..01a501bd 100644
|
||||||
|
--- a/libmultipath/defaults.h
|
||||||
|
+++ b/libmultipath/defaults.h
|
||||||
|
@@ -50,8 +50,8 @@
|
||||||
|
#define DEFAULT_FIND_MULTIPATHS_TIMEOUT -10
|
||||||
|
#define DEFAULT_UNKNOWN_FIND_MULTIPATHS_TIMEOUT 1
|
||||||
|
#define DEFAULT_ALL_TG_PT ALL_TG_PT_OFF
|
||||||
|
-/* Enable all foreign libraries by default */
|
||||||
|
-#define DEFAULT_ENABLE_FOREIGN ""
|
||||||
|
+/* Enable no foreign libraries by default */
|
||||||
|
+#define DEFAULT_ENABLE_FOREIGN "NONE"
|
||||||
|
|
||||||
|
#define CHECKINT_UNDEF UINT_MAX
|
||||||
|
#define DEFAULT_CHECKINT 5
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 05a5e8ff..28cea88c 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -1228,10 +1228,11 @@ Enables or disables foreign libraries (see section
|
||||||
|
.I FOREIGN MULTIPATH SUPPORT
|
||||||
|
below). The value is a regular expression; foreign libraries are loaded
|
||||||
|
if their name (e.g. \(dqnvme\(dq) matches the expression. By default,
|
||||||
|
-all foreign libraries are enabled.
|
||||||
|
+no foreign libraries are enabled. Set this to \(dqnvme\(dq to enable NVMe native
|
||||||
|
+multipath support, or \(dq.*\(dq to enable all foreign libraries.
|
||||||
|
.RS
|
||||||
|
.TP
|
||||||
|
-The default is: \fB\(dq\(dq\fR (the empty regular expression)
|
||||||
|
+The default is: \fB\(dqNONE\(dq\fR
|
||||||
|
.RE
|
||||||
|
.
|
||||||
|
.
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,89 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 2 Mar 2020 22:43:27 +0100
|
||||||
|
Subject: [PATCH] multipath: add "-e" option to enable foreign libraries
|
||||||
|
|
||||||
|
As we have set "enable_foreign" to "NONE" now by default, users
|
||||||
|
may find it useful to be able to switch on foreign multipath display
|
||||||
|
with an extra command line option even if foreign libraries are
|
||||||
|
not enabled in multipath.conf. Currently this makes only sense
|
||||||
|
with "multipath -ll", as the nvme library (and foreign libraries
|
||||||
|
in general) support only the display of status information.
|
||||||
|
|
||||||
|
Suggested-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/main.c | 11 ++++++++++-
|
||||||
|
multipath/multipath.8 | 6 ++++++
|
||||||
|
2 files changed, 16 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 953fab27..c4740fab 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -145,6 +145,7 @@ usage (char * progname)
|
||||||
|
" -h print this usage text\n"
|
||||||
|
" -l show multipath topology (sysfs and DM info)\n"
|
||||||
|
" -ll show multipath topology (maximum info)\n"
|
||||||
|
+ " -e enable foreign libraries with -l/-ll\n"
|
||||||
|
" -f flush a multipath device map\n"
|
||||||
|
" -F flush all multipath device maps\n"
|
||||||
|
" -a add a device wwid to the wwids file\n"
|
||||||
|
@@ -865,6 +866,7 @@ main (int argc, char *argv[])
|
||||||
|
char *dev = NULL;
|
||||||
|
struct config *conf;
|
||||||
|
int retries = -1;
|
||||||
|
+ bool enable_foreign = false;
|
||||||
|
|
||||||
|
udev = udev_new();
|
||||||
|
logsink = 0;
|
||||||
|
@@ -874,7 +876,7 @@ main (int argc, char *argv[])
|
||||||
|
multipath_conf = conf;
|
||||||
|
conf->retrigger_tries = 0;
|
||||||
|
conf->force_sync = 1;
|
||||||
|
- while ((arg = getopt(argc, argv, ":adcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
+ while ((arg = getopt(argc, argv, ":adcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
switch(arg) {
|
||||||
|
case 1: printf("optarg : %s\n",optarg);
|
||||||
|
break;
|
||||||
|
@@ -971,6 +973,9 @@ main (int argc, char *argv[])
|
||||||
|
case 'R':
|
||||||
|
retries = atoi(optarg);
|
||||||
|
break;
|
||||||
|
+ case 'e':
|
||||||
|
+ enable_foreign = true;
|
||||||
|
+ break;
|
||||||
|
case ':':
|
||||||
|
fprintf(stderr, "Missing option argument\n");
|
||||||
|
usage(argv[0]);
|
||||||
|
@@ -1022,6 +1027,10 @@ main (int argc, char *argv[])
|
||||||
|
condlog(0, "failed to initialize prioritizers");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if ((cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG) && enable_foreign)
|
||||||
|
+ conf->enable_foreign = "";
|
||||||
|
+
|
||||||
|
/* Failing here is non-fatal */
|
||||||
|
init_foreign(conf->multipath_dir, conf->enable_foreign);
|
||||||
|
if (cmd == CMD_USABLE_PATHS) {
|
||||||
|
diff --git a/multipath/multipath.8 b/multipath/multipath.8
|
||||||
|
index 9cdd05a3..6fb8645a 100644
|
||||||
|
--- a/multipath/multipath.8
|
||||||
|
+++ b/multipath/multipath.8
|
||||||
|
@@ -223,6 +223,12 @@ The verbosity level also controls the level of log and debug messages printed to
|
||||||
|
Dry run, do not create or update devmaps.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
+.B \-e
|
||||||
|
+Enable all foreign libraries. This overrides the
|
||||||
|
+.I enable_foreign
|
||||||
|
+option from \fBmultipath.conf(5)\fR.
|
||||||
|
+.
|
||||||
|
+.TP
|
||||||
|
.B \-i
|
||||||
|
Ignore WWIDs file when processing devices. If
|
||||||
|
\fIfind_multipaths strict\fR or \fIfind_multipaths no\fR is set in
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
139
0033-libmultipath-remove-_blacklist_exceptions-functions.patch
Normal file
139
0033-libmultipath-remove-_blacklist_exceptions-functions.patch
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 9 Jun 2020 16:35:27 -0500
|
||||||
|
Subject: [PATCH] libmultipath: remove _blacklist_exceptions functions
|
||||||
|
|
||||||
|
_blacklist_exceptions() and _blacklist_exceptions_device() are exactly
|
||||||
|
the same as _blacklist() and _blacklist_device(), so remove them, and
|
||||||
|
give the remaining functions to a more general name.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/blacklist.c | 62 ++++++++++------------------------------
|
||||||
|
1 file changed, 15 insertions(+), 47 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
|
||||||
|
index 00e8dbdb..c21a0e27 100644
|
||||||
|
--- a/libmultipath/blacklist.c
|
||||||
|
+++ b/libmultipath/blacklist.c
|
||||||
|
@@ -101,21 +101,8 @@ int set_ble_device(vector blist, char * vendor, char * product, int origin)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-_blacklist_exceptions (vector elist, const char * str)
|
||||||
|
-{
|
||||||
|
- int i;
|
||||||
|
- struct blentry * ele;
|
||||||
|
-
|
||||||
|
- vector_foreach_slot (elist, ele, i) {
|
||||||
|
- if (!regexec(&ele->regex, str, 0, NULL, 0))
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-int
|
||||||
|
-_blacklist (vector blist, const char * str)
|
||||||
|
+static int
|
||||||
|
+match_reglist (vector blist, const char * str)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct blentry * ble;
|
||||||
|
@@ -127,28 +114,9 @@ _blacklist (vector blist, const char * str)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-_blacklist_exceptions_device(const struct _vector *elist, const char * vendor,
|
||||||
|
- const char * product)
|
||||||
|
-{
|
||||||
|
- int i;
|
||||||
|
- struct blentry_device * ble;
|
||||||
|
-
|
||||||
|
- vector_foreach_slot (elist, ble, i) {
|
||||||
|
- if (!ble->vendor && !ble->product)
|
||||||
|
- continue;
|
||||||
|
- if ((!ble->vendor ||
|
||||||
|
- !regexec(&ble->vendor_reg, vendor, 0, NULL, 0)) &&
|
||||||
|
- (!ble->product ||
|
||||||
|
- !regexec(&ble->product_reg, product, 0, NULL, 0)))
|
||||||
|
- return 1;
|
||||||
|
- }
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-int
|
||||||
|
-_blacklist_device (const struct _vector *blist, const char * vendor,
|
||||||
|
- const char * product)
|
||||||
|
+static int
|
||||||
|
+match_reglist_device (const struct _vector *blist, const char * vendor,
|
||||||
|
+ const char * product)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct blentry_device * ble;
|
||||||
|
@@ -300,9 +268,9 @@ filter_device (vector blist, vector elist, char * vendor, char * product,
|
||||||
|
int r = MATCH_NOTHING;
|
||||||
|
|
||||||
|
if (vendor && product) {
|
||||||
|
- if (_blacklist_exceptions_device(elist, vendor, product))
|
||||||
|
+ if (match_reglist_device(elist, vendor, product))
|
||||||
|
r = MATCH_DEVICE_BLIST_EXCEPT;
|
||||||
|
- else if (_blacklist_device(blist, vendor, product))
|
||||||
|
+ else if (match_reglist_device(blist, vendor, product))
|
||||||
|
r = MATCH_DEVICE_BLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -316,9 +284,9 @@ filter_devnode (vector blist, vector elist, char * dev)
|
||||||
|
int r = MATCH_NOTHING;
|
||||||
|
|
||||||
|
if (dev) {
|
||||||
|
- if (_blacklist_exceptions(elist, dev))
|
||||||
|
+ if (match_reglist(elist, dev))
|
||||||
|
r = MATCH_DEVNODE_BLIST_EXCEPT;
|
||||||
|
- else if (_blacklist(blist, dev))
|
||||||
|
+ else if (match_reglist(blist, dev))
|
||||||
|
r = MATCH_DEVNODE_BLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -332,9 +300,9 @@ filter_wwid (vector blist, vector elist, char * wwid, char * dev)
|
||||||
|
int r = MATCH_NOTHING;
|
||||||
|
|
||||||
|
if (wwid) {
|
||||||
|
- if (_blacklist_exceptions(elist, wwid))
|
||||||
|
+ if (match_reglist(elist, wwid))
|
||||||
|
r = MATCH_WWID_BLIST_EXCEPT;
|
||||||
|
- else if (_blacklist(blist, wwid))
|
||||||
|
+ else if (match_reglist(blist, wwid))
|
||||||
|
r = MATCH_WWID_BLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -351,9 +319,9 @@ filter_protocol(vector blist, vector elist, struct path * pp)
|
||||||
|
if (pp) {
|
||||||
|
snprint_path_protocol(buf, sizeof(buf), pp);
|
||||||
|
|
||||||
|
- if (_blacklist_exceptions(elist, buf))
|
||||||
|
+ if (match_reglist(elist, buf))
|
||||||
|
r = MATCH_PROTOCOL_BLIST_EXCEPT;
|
||||||
|
- else if (_blacklist(blist, buf))
|
||||||
|
+ else if (match_reglist(blist, buf))
|
||||||
|
r = MATCH_PROTOCOL_BLIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -422,11 +390,11 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl,
|
||||||
|
if (check_missing_prop && !strcmp(env, uid_attribute))
|
||||||
|
uid_attr_seen = true;
|
||||||
|
|
||||||
|
- if (_blacklist_exceptions(conf->elist_property, env)) {
|
||||||
|
+ if (match_reglist(conf->elist_property, env)) {
|
||||||
|
r = MATCH_PROPERTY_BLIST_EXCEPT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- if (_blacklist(conf->blist_property, env)) {
|
||||||
|
+ if (match_reglist(conf->blist_property, env)) {
|
||||||
|
r = MATCH_PROPERTY_BLIST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,95 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 9 Jun 2020 16:35:28 -0500
|
||||||
|
Subject: [PATCH] libmultipath: fix parser issue with comments in strings
|
||||||
|
|
||||||
|
If a quoted string starts with '#' or '!', the parser will stop
|
||||||
|
parsing the line, thinking that it's a comment. It should only
|
||||||
|
be checking for comments outside of quoted strings. Fixed this and
|
||||||
|
added unit tests to verify it.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/parser.c | 4 +++-
|
||||||
|
tests/parser.c | 42 ++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
2 files changed, 45 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index d478b177..11a6168c 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -300,8 +300,10 @@ alloc_strvec(char *string)
|
||||||
|
(isspace((int) *cp) || !isascii((int) *cp)))
|
||||||
|
&& *cp != '\0')
|
||||||
|
cp++;
|
||||||
|
- if (*cp == '\0' || *cp == '!' || *cp == '#')
|
||||||
|
+ if (*cp == '\0' ||
|
||||||
|
+ (!in_string && (*cp == '!' || *cp == '#'))) {
|
||||||
|
return strvec;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
vector_free(strvec);
|
||||||
|
diff --git a/tests/parser.c b/tests/parser.c
|
||||||
|
index 29859dac..5772391e 100644
|
||||||
|
--- a/tests/parser.c
|
||||||
|
+++ b/tests/parser.c
|
||||||
|
@@ -440,6 +440,46 @@ static void test18(void **state)
|
||||||
|
free_strvec(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void test19(void **state)
|
||||||
|
+{
|
||||||
|
+#define QUOTED19 "!value"
|
||||||
|
+ vector v = alloc_strvec("key \"" QUOTED19 "\"");
|
||||||
|
+ char *val;
|
||||||
|
+
|
||||||
|
+ assert_int_equal(VECTOR_SIZE(v), 4);
|
||||||
|
+ assert_string_equal(VECTOR_SLOT(v, 0), "key");
|
||||||
|
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));
|
||||||
|
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED19);
|
||||||
|
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));
|
||||||
|
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
|
||||||
|
+
|
||||||
|
+ val = set_value(v);
|
||||||
|
+ assert_string_equal(val, QUOTED19);
|
||||||
|
+
|
||||||
|
+ free(val);
|
||||||
|
+ free_strvec(v);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void test20(void **state)
|
||||||
|
+{
|
||||||
|
+#define QUOTED20 "#value"
|
||||||
|
+ vector v = alloc_strvec("key \"" QUOTED20 "\"");
|
||||||
|
+ char *val;
|
||||||
|
+
|
||||||
|
+ assert_int_equal(VECTOR_SIZE(v), 4);
|
||||||
|
+ assert_string_equal(VECTOR_SLOT(v, 0), "key");
|
||||||
|
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));
|
||||||
|
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED20);
|
||||||
|
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));
|
||||||
|
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
|
||||||
|
+
|
||||||
|
+ val = set_value(v);
|
||||||
|
+ assert_string_equal(val, QUOTED20);
|
||||||
|
+
|
||||||
|
+ free(val);
|
||||||
|
+ free_strvec(v);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int test_config_parser(void)
|
||||||
|
{
|
||||||
|
const struct CMUnitTest tests[] = {
|
||||||
|
@@ -461,6 +501,8 @@ int test_config_parser(void)
|
||||||
|
cmocka_unit_test(test16),
|
||||||
|
cmocka_unit_test(test17),
|
||||||
|
cmocka_unit_test(test18),
|
||||||
|
+ cmocka_unit_test(test19),
|
||||||
|
+ cmocka_unit_test(test20),
|
||||||
|
};
|
||||||
|
return cmocka_run_group_tests(tests, setup, teardown);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
435
0035-libmultipath-invert-regexes-that-start-with-exclamat.patch
Normal file
435
0035-libmultipath-invert-regexes-that-start-with-exclamat.patch
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 9 Jun 2020 16:35:29 -0500
|
||||||
|
Subject: [PATCH] libmultipath: invert regexes that start with exclamation
|
||||||
|
point
|
||||||
|
|
||||||
|
The number of devices that multipath needs to blacklist keeps growing,
|
||||||
|
and the udev rules already have
|
||||||
|
|
||||||
|
KERNEL!="sd*|dasd*|nvme*", GOTO="end_mpath"
|
||||||
|
|
||||||
|
so they only work correctly with these device types. Instead of
|
||||||
|
individually blacklisting every type of device that can't be
|
||||||
|
multipathed, multipath's default blacklist should work like the udev
|
||||||
|
rule, and blacklist all devices that aren't scsi, dasd, or nvme.
|
||||||
|
Unfortunately, the c regex library doesn't support negative lookahead.
|
||||||
|
Instead, multipath should treat "!" at the beginning of
|
||||||
|
blacklist/exceptions regexes as inverse matching the rest of the regex.
|
||||||
|
If users need to match a literal '!' as the first character of their
|
||||||
|
regex, they can use "\!" instead. This allows multipath to change the
|
||||||
|
default devnode blacklist regex to "!^(sd[a-z]|dasd[a-z]|nvme[0-9])".
|
||||||
|
|
||||||
|
Extra tests have been added to the blacklist unit tests to verify the
|
||||||
|
inverse matching code and the new default blacklist.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/blacklist.c | 41 +++++++++-----
|
||||||
|
libmultipath/blacklist.h | 3 +
|
||||||
|
multipath/multipath.conf.5 | 17 ++++--
|
||||||
|
tests/blacklist.c | 110 +++++++++++++++++++++++++++++++++++++
|
||||||
|
tests/test-lib.c | 2 +-
|
||||||
|
5 files changed, 155 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
|
||||||
|
index c21a0e27..db58ccca 100644
|
||||||
|
--- a/libmultipath/blacklist.c
|
||||||
|
+++ b/libmultipath/blacklist.c
|
||||||
|
@@ -15,9 +15,24 @@
|
||||||
|
#include "structs_vec.h"
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
+char *check_invert(char *str, bool *invert)
|
||||||
|
+{
|
||||||
|
+ if (str[0] == '!') {
|
||||||
|
+ *invert = true;
|
||||||
|
+ return str + 1;
|
||||||
|
+ }
|
||||||
|
+ if (str[0] == '\\' && str[1] == '!') {
|
||||||
|
+ *invert = false;
|
||||||
|
+ return str + 1;
|
||||||
|
+ }
|
||||||
|
+ *invert = false;
|
||||||
|
+ return str;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int store_ble(vector blist, char * str, int origin)
|
||||||
|
{
|
||||||
|
struct blentry * ble;
|
||||||
|
+ char *regex_str;
|
||||||
|
|
||||||
|
if (!str)
|
||||||
|
return 0;
|
||||||
|
@@ -30,7 +45,8 @@ int store_ble(vector blist, char * str, int origin)
|
||||||
|
if (!ble)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
- if (regcomp(&ble->regex, str, REG_EXTENDED|REG_NOSUB))
|
||||||
|
+ regex_str = check_invert(str, &ble->invert);
|
||||||
|
+ if (regcomp(&ble->regex, regex_str, REG_EXTENDED|REG_NOSUB))
|
||||||
|
goto out1;
|
||||||
|
|
||||||
|
if (!vector_alloc_slot(blist))
|
||||||
|
@@ -66,6 +82,7 @@ int alloc_ble_device(vector blist)
|
||||||
|
int set_ble_device(vector blist, char * vendor, char * product, int origin)
|
||||||
|
{
|
||||||
|
struct blentry_device * ble;
|
||||||
|
+ char *regex_str;
|
||||||
|
|
||||||
|
if (!blist)
|
||||||
|
return 1;
|
||||||
|
@@ -76,7 +93,8 @@ int set_ble_device(vector blist, char * vendor, char * product, int origin)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (vendor) {
|
||||||
|
- if (regcomp(&ble->vendor_reg, vendor,
|
||||||
|
+ regex_str = check_invert(vendor, &ble->vendor_invert);
|
||||||
|
+ if (regcomp(&ble->vendor_reg, regex_str,
|
||||||
|
REG_EXTENDED|REG_NOSUB)) {
|
||||||
|
FREE(vendor);
|
||||||
|
if (product)
|
||||||
|
@@ -86,7 +104,8 @@ int set_ble_device(vector blist, char * vendor, char * product, int origin)
|
||||||
|
ble->vendor = vendor;
|
||||||
|
}
|
||||||
|
if (product) {
|
||||||
|
- if (regcomp(&ble->product_reg, product,
|
||||||
|
+ regex_str = check_invert(product, &ble->product_invert);
|
||||||
|
+ if (regcomp(&ble->product_reg, regex_str,
|
||||||
|
REG_EXTENDED|REG_NOSUB)) {
|
||||||
|
FREE(product);
|
||||||
|
if (vendor) {
|
||||||
|
@@ -108,7 +127,7 @@ match_reglist (vector blist, const char * str)
|
||||||
|
struct blentry * ble;
|
||||||
|
|
||||||
|
vector_foreach_slot (blist, ble, i) {
|
||||||
|
- if (!regexec(&ble->regex, str, 0, NULL, 0))
|
||||||
|
+ if (!!regexec(&ble->regex, str, 0, NULL, 0) == ble->invert)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
@@ -125,9 +144,11 @@ match_reglist_device (const struct _vector *blist, const char * vendor,
|
||||||
|
if (!ble->vendor && !ble->product)
|
||||||
|
continue;
|
||||||
|
if ((!ble->vendor ||
|
||||||
|
- !regexec(&ble->vendor_reg, vendor, 0, NULL, 0)) &&
|
||||||
|
+ !!regexec(&ble->vendor_reg, vendor, 0, NULL, 0) ==
|
||||||
|
+ ble->vendor_invert) &&
|
||||||
|
(!ble->product ||
|
||||||
|
- !regexec(&ble->product_reg, product, 0, NULL, 0)))
|
||||||
|
+ !!regexec(&ble->product_reg, product, 0, NULL, 0) ==
|
||||||
|
+ ble->product_invert))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
@@ -160,13 +181,7 @@ setup_default_blist (struct config * conf)
|
||||||
|
char * str;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
- str = STRDUP("^(ram|zram|raw|loop|fd|md|dm-|sr|scd|st|dcssblk)[0-9]");
|
||||||
|
- if (!str)
|
||||||
|
- return 1;
|
||||||
|
- if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
|
||||||
|
- return 1;
|
||||||
|
-
|
||||||
|
- str = STRDUP("^(td|hd|vd)[a-z]");
|
||||||
|
+ str = STRDUP("!^(sd[a-z]|dasd[a-z]|nvme[0-9])");
|
||||||
|
if (!str)
|
||||||
|
return 1;
|
||||||
|
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
|
||||||
|
diff --git a/libmultipath/blacklist.h b/libmultipath/blacklist.h
|
||||||
|
index 2d721f60..4305857d 100644
|
||||||
|
--- a/libmultipath/blacklist.h
|
||||||
|
+++ b/libmultipath/blacklist.h
|
||||||
|
@@ -20,6 +20,7 @@
|
||||||
|
struct blentry {
|
||||||
|
char * str;
|
||||||
|
regex_t regex;
|
||||||
|
+ bool invert;
|
||||||
|
int origin;
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -28,6 +29,8 @@ struct blentry_device {
|
||||||
|
char * product;
|
||||||
|
regex_t vendor_reg;
|
||||||
|
regex_t product_reg;
|
||||||
|
+ bool vendor_invert;
|
||||||
|
+ bool product_invert;
|
||||||
|
int origin;
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 28cea88c..5adaced6 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -1249,6 +1249,16 @@ being handled by multipath-tools.
|
||||||
|
.LP
|
||||||
|
.
|
||||||
|
.
|
||||||
|
+In the \fIblacklist\fR and \fIblacklist_exceptions\fR sections, starting a
|
||||||
|
+quoted value with an exclamation mark \fB"!"\fR will invert the matching
|
||||||
|
+of the rest of the regular expression. For instance, \fB"!^sd[a-z]"\fR will
|
||||||
|
+match all values that do not start with \fB"sd[a-z]"\fR. The exclamation mark
|
||||||
|
+can be escaped \fB"\\!"\fR to match a literal \fB!\fR at the start of a
|
||||||
|
+regular expression. \fBNote:\fR The exclamation mark must be inside quotes,
|
||||||
|
+otherwise it will be treated as starting a comment.
|
||||||
|
+.LP
|
||||||
|
+.
|
||||||
|
+.
|
||||||
|
The \fIblacklist_exceptions\fR section is used to revert the actions of the
|
||||||
|
\fIblacklist\fR section. This allows one to selectively include ("whitelist") devices which
|
||||||
|
would normally be excluded via the \fIblacklist\fR section. A common usage is
|
||||||
|
@@ -1265,10 +1275,9 @@ unless explicitly stated.
|
||||||
|
Regular expression matching the device nodes to be excluded/included.
|
||||||
|
.RS
|
||||||
|
.PP
|
||||||
|
-The default \fIblacklist\fR consists of the regular expressions
|
||||||
|
-"^(ram|zram|raw|loop|fd|md|dm-|sr|scd|st|dcssblk)[0-9]" and
|
||||||
|
-"^(td|hd|vd)[a-z]". This causes virtual devices, non-disk devices, and some other
|
||||||
|
-device types to be excluded from multipath handling by default.
|
||||||
|
+The default \fIblacklist\fR consists of the regular expression
|
||||||
|
+\fB"!^(sd[a-z]|dasd[a-z]|nvme[0-9])"\fR. This causes all device types other
|
||||||
|
+than scsi, dasd, and nvme to be excluded from multipath handling by default.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B wwid
|
||||||
|
diff --git a/tests/blacklist.c b/tests/blacklist.c
|
||||||
|
index 6e7c1864..d5c40898 100644
|
||||||
|
--- a/tests/blacklist.c
|
||||||
|
+++ b/tests/blacklist.c
|
||||||
|
@@ -60,20 +60,46 @@ __wrap_udev_list_entry_get_name(struct udev_list_entry *list_entry)
|
||||||
|
return *(const char **)list_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
+vector elist_property_default;
|
||||||
|
+vector blist_devnode_default;
|
||||||
|
vector blist_devnode_sdb;
|
||||||
|
+vector blist_devnode_sdb_inv;
|
||||||
|
vector blist_all;
|
||||||
|
vector blist_device_foo_bar;
|
||||||
|
+vector blist_device_foo_inv_bar;
|
||||||
|
+vector blist_device_foo_bar_inv;
|
||||||
|
vector blist_device_all;
|
||||||
|
vector blist_wwid_xyzzy;
|
||||||
|
+vector blist_wwid_xyzzy_inv;
|
||||||
|
vector blist_protocol_fcp;
|
||||||
|
+vector blist_protocol_fcp_inv;
|
||||||
|
vector blist_property_wwn;
|
||||||
|
+vector blist_property_wwn_inv;
|
||||||
|
|
||||||
|
static int setup(void **state)
|
||||||
|
{
|
||||||
|
+ struct config conf;
|
||||||
|
+
|
||||||
|
+ memset(&conf, 0, sizeof(conf));
|
||||||
|
+ conf.blist_devnode = vector_alloc();
|
||||||
|
+ if (!conf.blist_devnode)
|
||||||
|
+ return -1;
|
||||||
|
+ conf.elist_property = vector_alloc();
|
||||||
|
+ if (!conf.elist_property)
|
||||||
|
+ return -1;
|
||||||
|
+ if (setup_default_blist(&conf) != 0)
|
||||||
|
+ return -1;
|
||||||
|
+ elist_property_default = conf.elist_property;
|
||||||
|
+ blist_devnode_default = conf.blist_devnode;
|
||||||
|
+
|
||||||
|
blist_devnode_sdb = vector_alloc();
|
||||||
|
if (!blist_devnode_sdb ||
|
||||||
|
store_ble(blist_devnode_sdb, strdup("sdb"), ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_devnode_sdb_inv = vector_alloc();
|
||||||
|
+ if (!blist_devnode_sdb_inv ||
|
||||||
|
+ store_ble(blist_devnode_sdb_inv, strdup("!sdb"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
blist_all = vector_alloc();
|
||||||
|
if (!blist_all || store_ble(blist_all, strdup(".*"), ORIGIN_CONFIG))
|
||||||
|
@@ -84,6 +110,18 @@ static int setup(void **state)
|
||||||
|
set_ble_device(blist_device_foo_bar, strdup("foo"), strdup("bar"),
|
||||||
|
ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_device_foo_inv_bar = vector_alloc();
|
||||||
|
+ if (!blist_device_foo_inv_bar ||
|
||||||
|
+ alloc_ble_device(blist_device_foo_inv_bar) ||
|
||||||
|
+ set_ble_device(blist_device_foo_inv_bar, strdup("!foo"),
|
||||||
|
+ strdup("bar"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
+ blist_device_foo_bar_inv = vector_alloc();
|
||||||
|
+ if (!blist_device_foo_bar_inv ||
|
||||||
|
+ alloc_ble_device(blist_device_foo_bar_inv) ||
|
||||||
|
+ set_ble_device(blist_device_foo_bar_inv, strdup("foo"),
|
||||||
|
+ strdup("!bar"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
blist_device_all = vector_alloc();
|
||||||
|
if (!blist_device_all || alloc_ble_device(blist_device_all) ||
|
||||||
|
@@ -95,29 +133,50 @@ static int setup(void **state)
|
||||||
|
if (!blist_wwid_xyzzy ||
|
||||||
|
store_ble(blist_wwid_xyzzy, strdup("xyzzy"), ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_wwid_xyzzy_inv = vector_alloc();
|
||||||
|
+ if (!blist_wwid_xyzzy_inv ||
|
||||||
|
+ store_ble(blist_wwid_xyzzy_inv, strdup("!xyzzy"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
blist_protocol_fcp = vector_alloc();
|
||||||
|
if (!blist_protocol_fcp ||
|
||||||
|
store_ble(blist_protocol_fcp, strdup("scsi:fcp"), ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_protocol_fcp_inv = vector_alloc();
|
||||||
|
+ if (!blist_protocol_fcp_inv ||
|
||||||
|
+ store_ble(blist_protocol_fcp_inv, strdup("!scsi:fcp"),
|
||||||
|
+ ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
blist_property_wwn = vector_alloc();
|
||||||
|
if (!blist_property_wwn ||
|
||||||
|
store_ble(blist_property_wwn, strdup("ID_WWN"), ORIGIN_CONFIG))
|
||||||
|
return -1;
|
||||||
|
+ blist_property_wwn_inv = vector_alloc();
|
||||||
|
+ if (!blist_property_wwn_inv ||
|
||||||
|
+ store_ble(blist_property_wwn_inv, strdup("!ID_WWN"), ORIGIN_CONFIG))
|
||||||
|
+ return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int teardown(void **state)
|
||||||
|
{
|
||||||
|
+ free_blacklist(elist_property_default);
|
||||||
|
+ free_blacklist(blist_devnode_default);
|
||||||
|
free_blacklist(blist_devnode_sdb);
|
||||||
|
+ free_blacklist(blist_devnode_sdb_inv);
|
||||||
|
free_blacklist(blist_all);
|
||||||
|
free_blacklist_device(blist_device_foo_bar);
|
||||||
|
+ free_blacklist_device(blist_device_foo_inv_bar);
|
||||||
|
+ free_blacklist_device(blist_device_foo_bar_inv);
|
||||||
|
free_blacklist_device(blist_device_all);
|
||||||
|
free_blacklist(blist_wwid_xyzzy);
|
||||||
|
+ free_blacklist(blist_wwid_xyzzy_inv);
|
||||||
|
free_blacklist(blist_protocol_fcp);
|
||||||
|
+ free_blacklist(blist_protocol_fcp_inv);
|
||||||
|
free_blacklist(blist_property_wwn);
|
||||||
|
+ free_blacklist(blist_property_wwn_inv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -141,6 +200,11 @@ static void test_devnode_blacklist(void **state)
|
||||||
|
expect_condlog(3, "sdb: device node name blacklisted\n");
|
||||||
|
assert_int_equal(filter_devnode(blist_devnode_sdb, NULL, "sdb"),
|
||||||
|
MATCH_DEVNODE_BLIST);
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_sdb_inv, NULL, "sdb"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ expect_condlog(3, "sdc: device node name blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_sdb_inv, NULL, "sdc"),
|
||||||
|
+ MATCH_DEVNODE_BLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_devnode_whitelist(void **state)
|
||||||
|
@@ -159,12 +223,39 @@ static void test_devnode_missing(void **state)
|
||||||
|
MATCH_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void test_devnode_default(void **state)
|
||||||
|
+{
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_default, NULL, "sdaa"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_default, NULL, "nvme0n1"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_default, NULL, "dasda"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ expect_condlog(3, "hda: device node name blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_devnode(blist_devnode_default, NULL, "hda"),
|
||||||
|
+ MATCH_DEVNODE_BLIST);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void test_device_blacklist(void **state)
|
||||||
|
{
|
||||||
|
expect_condlog(3, "sdb: (foo:bar) vendor/product blacklisted\n");
|
||||||
|
assert_int_equal(filter_device(blist_device_foo_bar, NULL, "foo",
|
||||||
|
"bar", "sdb"),
|
||||||
|
MATCH_DEVICE_BLIST);
|
||||||
|
+ assert_int_equal(filter_device(blist_device_foo_inv_bar, NULL, "foo",
|
||||||
|
+ "bar", "sdb"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ assert_int_equal(filter_device(blist_device_foo_bar_inv, NULL, "foo",
|
||||||
|
+ "bar", "sdb"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ expect_condlog(3, "sdb: (baz:bar) vendor/product blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_device(blist_device_foo_inv_bar, NULL, "baz",
|
||||||
|
+ "bar", "sdb"),
|
||||||
|
+ MATCH_DEVICE_BLIST);
|
||||||
|
+ expect_condlog(3, "sdb: (foo:baz) vendor/product blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_device(blist_device_foo_bar_inv, NULL, "foo",
|
||||||
|
+ "baz", "sdb"),
|
||||||
|
+ MATCH_DEVICE_BLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_device_whitelist(void **state)
|
||||||
|
@@ -191,6 +282,11 @@ static void test_wwid_blacklist(void **state)
|
||||||
|
expect_condlog(3, "sdb: wwid xyzzy blacklisted\n");
|
||||||
|
assert_int_equal(filter_wwid(blist_wwid_xyzzy, NULL, "xyzzy", "sdb"),
|
||||||
|
MATCH_WWID_BLIST);
|
||||||
|
+ assert_int_equal(filter_wwid(blist_wwid_xyzzy_inv, NULL, "xyzzy",
|
||||||
|
+ "sdb"), MATCH_NOTHING);
|
||||||
|
+ expect_condlog(3, "sdb: wwid plugh blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_wwid(blist_wwid_xyzzy_inv, NULL, "plugh",
|
||||||
|
+ "sdb"), MATCH_WWID_BLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_wwid_whitelist(void **state)
|
||||||
|
@@ -218,6 +314,12 @@ static void test_protocol_blacklist(void **state)
|
||||||
|
expect_condlog(3, "sdb: protocol scsi:fcp blacklisted\n");
|
||||||
|
assert_int_equal(filter_protocol(blist_protocol_fcp, NULL, &pp),
|
||||||
|
MATCH_PROTOCOL_BLIST);
|
||||||
|
+ assert_int_equal(filter_protocol(blist_protocol_fcp_inv, NULL, &pp),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
+ pp.sg_id.proto_id = SCSI_PROTOCOL_ATA;
|
||||||
|
+ expect_condlog(3, "sdb: protocol scsi:ata blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_protocol(blist_protocol_fcp_inv, NULL, &pp),
|
||||||
|
+ MATCH_PROTOCOL_BLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_protocol_whitelist(void **state)
|
||||||
|
@@ -245,10 +347,17 @@ static void test_protocol_missing(void **state)
|
||||||
|
static void test_property_blacklist(void **state)
|
||||||
|
{
|
||||||
|
static struct udev_device udev = { "sdb", { "ID_FOO", "ID_WWN", "ID_BAR", NULL } };
|
||||||
|
+ static struct udev_device udev_inv = { "sdb", { "ID_WWN", NULL } };
|
||||||
|
conf.blist_property = blist_property_wwn;
|
||||||
|
expect_condlog(3, "sdb: udev property ID_WWN blacklisted\n");
|
||||||
|
assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"),
|
||||||
|
MATCH_PROPERTY_BLIST);
|
||||||
|
+ conf.blist_property = blist_property_wwn_inv;
|
||||||
|
+ expect_condlog(3, "sdb: udev property ID_FOO blacklisted\n");
|
||||||
|
+ assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"),
|
||||||
|
+ MATCH_PROPERTY_BLIST);
|
||||||
|
+ assert_int_equal(filter_property(&conf, &udev_inv, 3, "ID_SERIAL"),
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the property check works different in that you check all the property
|
||||||
|
@@ -484,6 +593,7 @@ int test_blacklist(void)
|
||||||
|
cmocka_unit_test(test_devnode_blacklist),
|
||||||
|
cmocka_unit_test(test_devnode_whitelist),
|
||||||
|
cmocka_unit_test(test_devnode_missing),
|
||||||
|
+ cmocka_unit_test(test_devnode_default),
|
||||||
|
cmocka_unit_test(test_device_blacklist),
|
||||||
|
cmocka_unit_test(test_device_whitelist),
|
||||||
|
cmocka_unit_test(test_device_missing),
|
||||||
|
diff --git a/tests/test-lib.c b/tests/test-lib.c
|
||||||
|
index 00bae58e..b7c09cc2 100644
|
||||||
|
--- a/tests/test-lib.c
|
||||||
|
+++ b/tests/test-lib.c
|
||||||
|
@@ -15,7 +15,7 @@
|
||||||
|
#include "test-lib.h"
|
||||||
|
|
||||||
|
const int default_mask = (DI_SYSFS|DI_BLACKLIST|DI_WWID|DI_CHECKER|DI_PRIO);
|
||||||
|
-const char default_devnode[] = "sdTEST";
|
||||||
|
+const char default_devnode[] = "sdxTEST";
|
||||||
|
const char default_wwid[] = "TEST-WWID";
|
||||||
|
/* default_wwid should be a substring of default_wwid_1! */
|
||||||
|
const char default_wwid_1[] = "TEST-WWID-1";
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
111
0036-multipath-Fix-compiler-warnings-when-built-without-s.patch
Normal file
111
0036-multipath-Fix-compiler-warnings-when-built-without-s.patch
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Marius Bakke <marius@devup.no>
|
||||||
|
Date: Wed, 17 Jun 2020 01:11:26 +0200
|
||||||
|
Subject: [PATCH] multipath: Fix compiler warnings when built without systemd.
|
||||||
|
|
||||||
|
Add ifdef guards for code that is unused when systemd is not available.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 6 ++++--
|
||||||
|
multipathd/main.c | 10 +++++++++-
|
||||||
|
2 files changed, 13 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index b4d87689..658bec8b 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -696,9 +696,9 @@ process_config_dir(struct config *conf, char *dir)
|
||||||
|
pthread_cleanup_pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef USE_SYSTEMD
|
||||||
|
static void set_max_checkint_from_watchdog(struct config *conf)
|
||||||
|
{
|
||||||
|
-#ifdef USE_SYSTEMD
|
||||||
|
char *envp = getenv("WATCHDOG_USEC");
|
||||||
|
unsigned long checkint;
|
||||||
|
|
||||||
|
@@ -714,8 +714,8 @@ static void set_max_checkint_from_watchdog(struct config *conf)
|
||||||
|
condlog(3, "enabling watchdog, interval %ld", checkint);
|
||||||
|
conf->use_watchdog = true;
|
||||||
|
}
|
||||||
|
-#endif
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
struct config *
|
||||||
|
load_config (char * file)
|
||||||
|
@@ -789,7 +789,9 @@ load_config (char * file)
|
||||||
|
/*
|
||||||
|
* fill the voids left in the config file
|
||||||
|
*/
|
||||||
|
+#ifdef USE_SYSTEMD
|
||||||
|
set_max_checkint_from_watchdog(conf);
|
||||||
|
+#endif
|
||||||
|
if (conf->max_checkint == 0) {
|
||||||
|
if (conf->checkint == CHECKINT_UNDEF)
|
||||||
|
conf->checkint = DEFAULT_CHECKINT;
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 6b7db2c0..205ddb32 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -176,6 +176,7 @@ daemon_status(void)
|
||||||
|
/*
|
||||||
|
* I love you too, systemd ...
|
||||||
|
*/
|
||||||
|
+#ifdef USE_SYSTEMD
|
||||||
|
static const char *
|
||||||
|
sd_notify_status(enum daemon_status state)
|
||||||
|
{
|
||||||
|
@@ -195,7 +196,6 @@ sd_notify_status(enum daemon_status state)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
-#ifdef USE_SYSTEMD
|
||||||
|
static void do_sd_notify(enum daemon_status old_state,
|
||||||
|
enum daemon_status new_state)
|
||||||
|
{
|
||||||
|
@@ -247,7 +247,9 @@ enum daemon_status wait_for_state_change_if(enum daemon_status oldstate,
|
||||||
|
static void __post_config_state(enum daemon_status state)
|
||||||
|
{
|
||||||
|
if (state != running_state && running_state != DAEMON_SHUTDOWN) {
|
||||||
|
+#ifdef USE_SYSTEMD
|
||||||
|
enum daemon_status old_state = running_state;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
running_state = state;
|
||||||
|
pthread_cond_broadcast(&config_cond);
|
||||||
|
@@ -272,7 +274,9 @@ int set_config_state(enum daemon_status state)
|
||||||
|
pthread_cleanup_push(config_cleanup, NULL);
|
||||||
|
pthread_mutex_lock(&config_lock);
|
||||||
|
if (running_state != state) {
|
||||||
|
+#ifdef USE_SYSTEMD
|
||||||
|
enum daemon_status old_state = running_state;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
if (running_state == DAEMON_SHUTDOWN)
|
||||||
|
rc = EINVAL;
|
||||||
|
@@ -2280,7 +2284,9 @@ checkerloop (void *ap)
|
||||||
|
struct timespec last_time;
|
||||||
|
struct config *conf;
|
||||||
|
int foreign_tick = 0;
|
||||||
|
+#ifdef USE_SYSTEMD
|
||||||
|
bool use_watchdog;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
pthread_cleanup_push(rcu_unregister, NULL);
|
||||||
|
rcu_register_thread();
|
||||||
|
@@ -2294,7 +2300,9 @@ checkerloop (void *ap)
|
||||||
|
|
||||||
|
/* use_watchdog is set from process environment and never changes */
|
||||||
|
conf = get_multipath_config();
|
||||||
|
+#ifdef USE_SYSTEMD
|
||||||
|
use_watchdog = conf->use_watchdog;
|
||||||
|
+#endif
|
||||||
|
put_multipath_config(conf);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
43
0037-libmultipath-fix-sysfs-dev_loss_tmo-parsing.patch
Normal file
43
0037-libmultipath-fix-sysfs-dev_loss_tmo-parsing.patch
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:38:24 -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: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.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
0038-kpartx-read-devices-with-direct-IO.patch
Normal file
267
0038-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: Thu, 2 Jul 2020 19:38:25 -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
|
||||||
|
|
53
0039-kpartx-handle-alternate-bsd-disklabel-location.patch
Normal file
53
0039-kpartx-handle-alternate-bsd-disklabel-location.patch
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:38:26 -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.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
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,62 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:38:27 -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"
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
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
|
||||||
|
|
322
0041-libmultipath-make-dm_get_map-status-return-codes-sym.patch
Normal file
322
0041-libmultipath-make-dm_get_map-status-return-codes-sym.patch
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:07:00 -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 27d52398..24cc616a 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -534,36 +534,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;
|
||||||
|
@@ -637,35 +644,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);
|
||||||
|
@@ -920,7 +937,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;
|
||||||
|
@@ -1129,7 +1146,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);
|
||||||
|
@@ -1313,7 +1330,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 5ed7edc5..b2108638 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);
|
||||||
|
int dm_prereq(unsigned int *v);
|
||||||
|
void skip_libmp_dm_init(void);
|
||||||
|
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 205ddb32..ab141fed 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -418,7 +418,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;
|
||||||
|
}
|
||||||
|
@@ -557,9 +557,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))
|
||||||
|
@@ -1350,8 +1350,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--;
|
||||||
|
}
|
||||||
|
@@ -2091,7 +2091,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
|
||||||
|
|
116
0042-multipathd-fix-check_path-errors-with-removed-map.patch
Normal file
116
0042-multipathd-fix-check_path-errors-with-removed-map.patch
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:07:01 -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 ab141fed..daf19a4e 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -1615,22 +1615,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
|
||||||
|
@@ -2091,9 +2087,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 */
|
||||||
|
@@ -2183,12 +2186,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)
|
||||||
|
@@ -2204,15 +2203,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,46 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:07:02 -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.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
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 24cc616a..4c86b6d4 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -1007,13 +1007,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);
|
||||||
|
|
||||||
|
@@ -1026,6 +1026,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
|
||||||
|
|
161
0044-multipathd-add-del-maps-multipathd-command.patch
Normal file
161
0044-multipathd-add-del-maps-multipathd-command.patch
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:07:03 -0500
|
||||||
|
Subject: [PATCH] multipathd: add "del maps" multipathd command
|
||||||
|
|
||||||
|
This will flush all multipath devices.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
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 4c86b6d4..f597ff8b 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -1005,7 +1005,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;
|
||||||
|
@@ -1028,7 +1028,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 b2108638..6dd178c8 100644
|
||||||
|
--- a/libmultipath/devmapper.h
|
||||||
|
+++ b/libmultipath/devmapper.h
|
||||||
|
@@ -57,7 +57,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 c4740fab..d89f0a91 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -1096,7 +1096,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 daf19a4e..f014d2a1 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -635,7 +635,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;
|
||||||
|
@@ -1555,6 +1555,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
|
||||||
|
|
104
0045-multipath-make-flushing-maps-work-like-other-command.patch
Normal file
104
0045-multipath-make-flushing-maps-work-like-other-command.patch
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:07:04 -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.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
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 ceecff2d..55569360 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -38,6 +38,8 @@ enum mpath_cmds {
|
||||||
|
CMD_ADD_WWID,
|
||||||
|
CMD_USABLE_PATHS,
|
||||||
|
CMD_DUMP_CONFIG,
|
||||||
|
+ CMD_FLUSH_ONE,
|
||||||
|
+ CMD_FLUSH_ALL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum force_reload_types {
|
||||||
|
@@ -142,7 +144,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 d89f0a91..101fd656 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -909,10 +909,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))
|
||||||
|
@@ -1053,6 +1053,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:
|
||||||
|
@@ -1086,16 +1090,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
|
||||||
|
|
64
0046-multipath-delegate-flushing-maps-to-multipathd.patch
Normal file
64
0046-multipath-delegate-flushing-maps-to-multipathd.patch
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:07:05 -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.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
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 101fd656..6a24e483 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -820,6 +820,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 6fb8645a..5b29a5d9 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,63 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 2 Jul 2020 19:07:06 -0500
|
||||||
|
Subject: [PATCH] multipath: add option to skip multipathd delegation
|
||||||
|
|
||||||
|
Add the -D option to allow users to skip delegating commands to
|
||||||
|
multipathd.
|
||||||
|
|
||||||
|
Reviewed-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
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 55569360..92c61a0d 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -190,6 +190,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 6a24e483..4c43314e 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -817,6 +817,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");
|
||||||
|
}
|
||||||
|
@@ -890,7 +893,7 @@ main (int argc, char *argv[])
|
||||||
|
multipath_conf = conf;
|
||||||
|
conf->retrigger_tries = 0;
|
||||||
|
conf->force_sync = 1;
|
||||||
|
- while ((arg = getopt(argc, argv, ":adcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
+ while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
switch(arg) {
|
||||||
|
case 1: printf("optarg : %s\n",optarg);
|
||||||
|
break;
|
||||||
|
@@ -922,6 +925,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
|
||||||
|
|
44
0048-libmultipath-add-device-to-hwtable.c.patch
Normal file
44
0048-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,84 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: lixiaokeng <lixiaokeng@huawei.com>
|
||||||
|
Date: Mon, 13 Jul 2020 13:07:40 +0200
|
||||||
|
Subject: [PATCH] master - libmultipath: fix use after free when iscsi logs in
|
||||||
|
|
||||||
|
When two iscsi ips log in and out alternately and the following scripts run
|
||||||
|
at the same time,
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
interval=5
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
iscsiadm -m node -p 9.41.147.171 &> /dev/null
|
||||||
|
iscsiadm -m node -p 9.41.148.172 &> /dev/null
|
||||||
|
iscsiadm -m session &> /dev/null
|
||||||
|
rescan-scsi-bus.sh &> /dev/null
|
||||||
|
multipath -v2 &> /dev/null
|
||||||
|
multipath -ll &> /dev/null
|
||||||
|
sleep $interval
|
||||||
|
done
|
||||||
|
|
||||||
|
multipathd will have a segfault after about 30 mins.
|
||||||
|
|
||||||
|
The reason is that mpp->hwe is accessed after hwe is already freed. In
|
||||||
|
extract_hwe_from_path func, mpp->hwe is set to pp->hwe, so they points to the
|
||||||
|
same hwe. For some reasons, pp->mpp will be set to NULL in orphan_path func.
|
||||||
|
Then, pp and hwe will be freed with (pp->mpp == NULL) in free_path func
|
||||||
|
called by ev_remove_path func. However, mpp->hwe is not set to NULL while hwe
|
||||||
|
is already freed. So, when iscsi device logs in and new path is added to mpp,
|
||||||
|
mpp->hwe will be accessed in select_pgfailback func. Finally, use-after-free
|
||||||
|
problem occurs.
|
||||||
|
|
||||||
|
The procedure details given as follows,
|
||||||
|
1.wait_dmevents thread
|
||||||
|
wait_dmevents
|
||||||
|
->dmevent_loop
|
||||||
|
->update_multipath
|
||||||
|
->__setup_multipath
|
||||||
|
->update_multipath_strings
|
||||||
|
-> sync_paths
|
||||||
|
->orphan_path
|
||||||
|
2.uevqloop thread (iscsi log out, remove path)
|
||||||
|
uevqloop
|
||||||
|
->uevent_dispatch
|
||||||
|
->service_uevq
|
||||||
|
->uev_remove_path
|
||||||
|
->ev_remove_path //pp->mpp is NULL
|
||||||
|
->free_path(pp)
|
||||||
|
//pp->hew are freed but mpp->hwe is not set to NULL
|
||||||
|
3.ev_remove_path (iscsi log in, add path)
|
||||||
|
uevqloop
|
||||||
|
->uevent_dispatch
|
||||||
|
->service_uevq
|
||||||
|
->ev_add_path
|
||||||
|
->select_pgfailback //mpp->hwe is accessed
|
||||||
|
|
||||||
|
Here, we will set mpp->hwe to NULL before setting pp->map to NULL in orphan_path
|
||||||
|
func.
|
||||||
|
|
||||||
|
Signed-off-by: Tianxiong Lu <lutianxiong@huawei.com>
|
||||||
|
Signed-off-by: lixiaokeng <lixiaokeng@huawei.com>
|
||||||
|
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/structs_vec.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
||||||
|
index 8137ea21..430eaad7 100644
|
||||||
|
--- a/libmultipath/structs_vec.c
|
||||||
|
+++ b/libmultipath/structs_vec.c
|
||||||
|
@@ -93,6 +93,8 @@ int adopt_paths(vector pathvec, struct multipath *mpp)
|
||||||
|
void orphan_path(struct path *pp, const char *reason)
|
||||||
|
{
|
||||||
|
condlog(3, "%s: orphan path, %s", pp->dev, reason);
|
||||||
|
+ if (pp->mpp && pp->mpp->hwe == pp->hwe)
|
||||||
|
+ pp->mpp->hwe = NULL;
|
||||||
|
pp->mpp = NULL;
|
||||||
|
pp->dmstate = PSTATE_UNDEF;
|
||||||
|
pp->uid_attribute = NULL;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 13 Jul 2020 13:07:41 +0200
|
||||||
|
Subject: [PATCH] libmultipath: warn if freeing path that holds mpp->hwe
|
||||||
|
|
||||||
|
This just adds an error message to the previous patch.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/structs_vec.c | 5 ++++-
|
||||||
|
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
||||||
|
index 430eaad7..cde4dbe6 100644
|
||||||
|
--- a/libmultipath/structs_vec.c
|
||||||
|
+++ b/libmultipath/structs_vec.c
|
||||||
|
@@ -93,8 +93,11 @@ int adopt_paths(vector pathvec, struct multipath *mpp)
|
||||||
|
void orphan_path(struct path *pp, const char *reason)
|
||||||
|
{
|
||||||
|
condlog(3, "%s: orphan path, %s", pp->dev, reason);
|
||||||
|
- if (pp->mpp && pp->mpp->hwe == pp->hwe)
|
||||||
|
+ if (pp->mpp && pp->hwe && pp->mpp->hwe == pp->hwe) {
|
||||||
|
+ condlog(0, "BUG: orphaning path %s that holds hwe of %s",
|
||||||
|
+ pp->dev, pp->mpp->alias);
|
||||||
|
pp->mpp->hwe = NULL;
|
||||||
|
+ }
|
||||||
|
pp->mpp = NULL;
|
||||||
|
pp->dmstate = PSTATE_UNDEF;
|
||||||
|
pp->uid_attribute = NULL;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
33
0051-libmultipath-warn-about-NULL-value-of-mpp-hwe.patch
Normal file
33
0051-libmultipath-warn-about-NULL-value-of-mpp-hwe.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 13 Jul 2020 13:07:42 +0200
|
||||||
|
Subject: [PATCH] libmultipath: warn about NULL value of mpp->hwe
|
||||||
|
|
||||||
|
mpp->hwe is only accessed in propsel.c. It may become unset if
|
||||||
|
all paths of the mpp have been deleted. Access to mpp->hwe in this
|
||||||
|
case should be avoided.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/propsel.c | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
|
||||||
|
index d362beb4..68228272 100644
|
||||||
|
--- a/libmultipath/propsel.c
|
||||||
|
+++ b/libmultipath/propsel.c
|
||||||
|
@@ -65,7 +65,9 @@ do { \
|
||||||
|
__do_set_from_vec(struct hwentry, var, (src)->hwe, dest)
|
||||||
|
|
||||||
|
#define do_set_from_hwe(var, src, dest, msg) \
|
||||||
|
- if (__do_set_from_hwe(var, src, dest)) { \
|
||||||
|
+ if (!src->hwe) { \
|
||||||
|
+ condlog(0, "BUG: do_set_from_hwe called with hwe == NULL"); \
|
||||||
|
+ } else if (__do_set_from_hwe(var, src, dest)) { \
|
||||||
|
origin = msg; \
|
||||||
|
goto out; \
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
45
0052-libmultipath-fix-mpp-hwe-handling-in-sync_paths.patch
Normal file
45
0052-libmultipath-fix-mpp-hwe-handling-in-sync_paths.patch
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Mon, 13 Jul 2020 13:07:43 +0200
|
||||||
|
Subject: [PATCH] libmultipath: fix mpp->hwe handling in sync_paths()
|
||||||
|
|
||||||
|
This is anologous to
|
||||||
|
|
||||||
|
1f96269 ("multipathd: fix mpp->hwe handling on path removal")
|
||||||
|
f6839eb ("multipathd: fix mpp->hwe handling when paths are freed")
|
||||||
|
|
||||||
|
When paths are removed from a map, we need to make sure that
|
||||||
|
mpp->hwe doesn't become stale.
|
||||||
|
|
||||||
|
Reported-by: Lixiaokeng <lixiaokeng@huawei.com>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/structs_vec.c | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
||||||
|
index cde4dbe6..ede14297 100644
|
||||||
|
--- a/libmultipath/structs_vec.c
|
||||||
|
+++ b/libmultipath/structs_vec.c
|
||||||
|
@@ -260,6 +260,8 @@ void sync_paths(struct multipath *mpp, vector pathvec)
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
condlog(3, "%s dropped path %s", mpp->alias, pp->dev);
|
||||||
|
+ if (mpp->hwe == pp->hwe)
|
||||||
|
+ mpp->hwe = NULL;
|
||||||
|
vector_del_slot(mpp->paths, i--);
|
||||||
|
orphan_path(pp, "path removed externally");
|
||||||
|
}
|
||||||
|
@@ -267,6 +269,8 @@ void sync_paths(struct multipath *mpp, vector pathvec)
|
||||||
|
update_mpp_paths(mpp, pathvec);
|
||||||
|
vector_foreach_slot (mpp->paths, pp, i)
|
||||||
|
pp->mpp = mpp;
|
||||||
|
+ if (mpp->hwe == NULL)
|
||||||
|
+ extract_hwe_from_path(mpp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
--
|
||||||
|
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 e7256e3a..8ea3352d 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
0054-kpartx-fix-Wsign-compare-error.patch
Normal file
26
0054-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
|
||||||
|
|
129
0055-libmultipath-remove-code-duplication-in-path-countin.patch
Normal file
129
0055-libmultipath-remove-code-duplication-in-path-countin.patch
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 21 Jul 2020 01:12:05 -0500
|
||||||
|
Subject: [PATCH] libmultipath: remove code duplication in path counting
|
||||||
|
|
||||||
|
pathcountgr() is never used except by pathcount(), and neither is the
|
||||||
|
special case for PATH_WILD. Simplify this and make one function that is
|
||||||
|
used by both pathcount() and count_active_paths(). This will be used
|
||||||
|
again in a future patch.
|
||||||
|
|
||||||
|
Also use count_active_paths() in mpath_persist.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_persist.c | 4 +--
|
||||||
|
libmultipath/structs.c | 47 +++++++++++++--------------------
|
||||||
|
libmultipath/structs.h | 1 -
|
||||||
|
3 files changed, 21 insertions(+), 31 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||||
|
index 3da7a6cf..a132f4e9 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.c
|
||||||
|
+++ b/libmpathpersist/mpath_persist.c
|
||||||
|
@@ -436,7 +436,7 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
|
||||||
|
|
||||||
|
all_tg_pt = (mpp->all_tg_pt == ALL_TG_PT_ON ||
|
||||||
|
paramp->sa_flags & MPATH_F_ALL_TG_PT_MASK);
|
||||||
|
- active_pathcount = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
|
||||||
|
+ active_pathcount = count_active_paths(mpp);
|
||||||
|
|
||||||
|
if (active_pathcount == 0) {
|
||||||
|
condlog (0, "%s: no path available", mpp->wwid);
|
||||||
|
@@ -648,7 +648,7 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
|
||||||
|
if (!mpp)
|
||||||
|
return MPATH_PR_DMMP_ERROR;
|
||||||
|
|
||||||
|
- active_pathcount = pathcount (mpp, PATH_UP) + pathcount (mpp, PATH_GHOST);
|
||||||
|
+ active_pathcount = count_active_paths(mpp);
|
||||||
|
|
||||||
|
struct threadinfo thread[active_pathcount];
|
||||||
|
memset(thread, 0, sizeof(thread));
|
||||||
|
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
|
||||||
|
index 2dd378c4..3eac3d61 100644
|
||||||
|
--- a/libmultipath/structs.c
|
||||||
|
+++ b/libmultipath/structs.c
|
||||||
|
@@ -455,49 +455,40 @@ find_path_by_devt (const struct _vector *pathvec, const char * dev_t)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int pathcountgr(const struct pathgroup *pgp, int state)
|
||||||
|
+static int do_pathcount(const struct multipath *mpp, const int *states,
|
||||||
|
+ unsigned int nr_states)
|
||||||
|
{
|
||||||
|
+ struct pathgroup *pgp;
|
||||||
|
struct path *pp;
|
||||||
|
int count = 0;
|
||||||
|
- int i;
|
||||||
|
+ unsigned int i, j, k;
|
||||||
|
|
||||||
|
- vector_foreach_slot (pgp->paths, pp, i)
|
||||||
|
- if ((pp->state == state) || (state == PATH_WILD))
|
||||||
|
- count++;
|
||||||
|
+ if (!mpp->pg || !nr_states)
|
||||||
|
+ return count;
|
||||||
|
|
||||||
|
+ vector_foreach_slot (mpp->pg, pgp, i) {
|
||||||
|
+ vector_foreach_slot (pgp->paths, pp, j) {
|
||||||
|
+ for (k = 0; k < nr_states; k++) {
|
||||||
|
+ if (pp->state == states[k]) {
|
||||||
|
+ count++;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pathcount(const struct multipath *mpp, int state)
|
||||||
|
{
|
||||||
|
- struct pathgroup *pgp;
|
||||||
|
- int count = 0;
|
||||||
|
- int i;
|
||||||
|
-
|
||||||
|
- if (mpp->pg) {
|
||||||
|
- vector_foreach_slot (mpp->pg, pgp, i)
|
||||||
|
- count += pathcountgr(pgp, state);
|
||||||
|
- }
|
||||||
|
- return count;
|
||||||
|
+ return do_pathcount(mpp, &state, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int count_active_paths(const struct multipath *mpp)
|
||||||
|
{
|
||||||
|
- struct pathgroup *pgp;
|
||||||
|
- struct path *pp;
|
||||||
|
- int count = 0;
|
||||||
|
- int i, j;
|
||||||
|
-
|
||||||
|
- if (!mpp->pg)
|
||||||
|
- return 0;
|
||||||
|
+ int states[] = {PATH_UP, PATH_GHOST};
|
||||||
|
|
||||||
|
- vector_foreach_slot (mpp->pg, pgp, i) {
|
||||||
|
- vector_foreach_slot (pgp->paths, pp, j) {
|
||||||
|
- if (pp->state == PATH_UP || pp->state == PATH_GHOST)
|
||||||
|
- count++;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- return count;
|
||||||
|
+ return do_pathcount(mpp, states, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pathcmp(const struct pathgroup *pgp, const struct pathgroup *cpgp)
|
||||||
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||||
|
index d69bc2e9..0c03e711 100644
|
||||||
|
--- a/libmultipath/structs.h
|
||||||
|
+++ b/libmultipath/structs.h
|
||||||
|
@@ -446,7 +446,6 @@ struct path * find_path_by_devt (const struct _vector *pathvec, const char *devt
|
||||||
|
struct path * find_path_by_dev (const struct _vector *pathvec, const char *dev);
|
||||||
|
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 pathcmp (const struct pathgroup *, const struct pathgroup *);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,73 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 21 Jul 2020 01:19:30 -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 | 7 +++++++
|
||||||
|
libmultipath/structs.h | 1 +
|
||||||
|
3 files changed, 10 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index f597ff8b..126cd728 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -417,7 +417,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 3eac3d61..0d1f969d 100644
|
||||||
|
--- a/libmultipath/structs.c
|
||||||
|
+++ b/libmultipath/structs.c
|
||||||
|
@@ -491,6 +491,13 @@ int count_active_paths(const struct multipath *mpp)
|
||||||
|
return do_pathcount(mpp, states, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
+int count_active_pending_paths(const struct multipath *mpp)
|
||||||
|
+{
|
||||||
|
+ int states[] = {PATH_UP, PATH_GHOST, PATH_PENDING};
|
||||||
|
+
|
||||||
|
+ return do_pathcount(mpp, states, 3);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int pathcmp(const struct pathgroup *pgp, const struct pathgroup *cpgp)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
|
||||||
|
index 0c03e711..917e4083 100644
|
||||||
|
--- a/libmultipath/structs.h
|
||||||
|
+++ b/libmultipath/structs.h
|
||||||
|
@@ -448,6 +448,7 @@ struct path * first_path (const struct multipath *mpp);
|
||||||
|
|
||||||
|
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
|
||||||
|
|
33
0057-libmultipath-deal-with-flushing-no-maps.patch
Normal file
33
0057-libmultipath-deal-with-flushing-no-maps.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 21 Jul 2020 01:28:22 -0500
|
||||||
|
Subject: [PATCH] libmultipath: deal with flushing no 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.
|
||||||
|
|
||||||
|
Fixes: "libmultipath: make dm_flush_maps only return 0 on success"
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/devmapper.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
|
||||||
|
index 126cd728..b8199cb5 100644
|
||||||
|
--- a/libmultipath/devmapper.c
|
||||||
|
+++ b/libmultipath/devmapper.c
|
||||||
|
@@ -1024,10 +1024,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);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
39
0058-multipath-deal-with-delegation-failures-correctly.patch
Normal file
39
0058-multipath-deal-with-delegation-failures-correctly.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 21 Jul 2020 01:37:18 -0500
|
||||||
|
Subject: [PATCH] multipath: deal with delegation failures correctly
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Fixes: "multipath: delegate flushing maps to multipathd"
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/main.c | 9 ++++++---
|
||||||
|
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 4c43314e..3da692dc 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -861,9 +861,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
|
||||||
|
|
66
0059-RH-fixup-udev-rules-for-redhat.patch
Normal file
66
0059-RH-fixup-udev-rules-for-redhat.patch
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 13 Apr 2017 07:22:23 -0500
|
||||||
|
Subject: [PATCH] RH: fixup udev rules for redhat
|
||||||
|
|
||||||
|
The multipath rules need to run after scsi_id is run. This means moving
|
||||||
|
them after 60-persistent-storage.rules for redhat. Redhat also uses a
|
||||||
|
different naming scheme for partitions than SuSE.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile.inc | 2 +-
|
||||||
|
kpartx/kpartx.rules | 2 +-
|
||||||
|
multipath/Makefile | 4 ++--
|
||||||
|
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
|
index 8ea3352d..873fb62f 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -53,7 +53,7 @@ endif
|
||||||
|
prefix =
|
||||||
|
exec_prefix = $(prefix)
|
||||||
|
usr_prefix = $(prefix)
|
||||||
|
-bindir = $(exec_prefix)/sbin
|
||||||
|
+bindir = $(exec_prefix)/usr/sbin
|
||||||
|
libudevdir = $(prefix)/$(SYSTEMDPATH)/udev
|
||||||
|
udevrulesdir = $(libudevdir)/rules.d
|
||||||
|
multipathdir = $(TOPDIR)/libmultipath
|
||||||
|
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
|
||||||
|
index d7527d7d..0e0d70d5 100644
|
||||||
|
--- a/kpartx/kpartx.rules
|
||||||
|
+++ b/kpartx/kpartx.rules
|
||||||
|
@@ -36,6 +36,6 @@ LABEL="mpath_kpartx_end"
|
||||||
|
GOTO="kpartx_end"
|
||||||
|
|
||||||
|
LABEL="run_kpartx"
|
||||||
|
-RUN+="/sbin/kpartx -un -p -part /dev/$name"
|
||||||
|
+RUN+="/sbin/kpartx -un /dev/$name"
|
||||||
|
|
||||||
|
LABEL="kpartx_end"
|
||||||
|
diff --git a/multipath/Makefile b/multipath/Makefile
|
||||||
|
index 0828a8f7..b9bbb3cf 100644
|
||||||
|
--- a/multipath/Makefile
|
||||||
|
+++ b/multipath/Makefile
|
||||||
|
@@ -24,7 +24,7 @@ install:
|
||||||
|
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
|
||||||
|
- $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
|
||||||
|
+ $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
|
||||||
|
@@ -33,7 +33,7 @@ install:
|
||||||
|
uninstall:
|
||||||
|
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
|
||||||
|
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
|
||||||
|
- $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
|
||||||
|
+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
|
||||||
|
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
|
||||||
|
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
105
0060-RH-Remove-the-property-blacklist-exception-builtin.patch
Normal file
105
0060-RH-Remove-the-property-blacklist-exception-builtin.patch
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 2 Jul 2014 12:49:53 -0500
|
||||||
|
Subject: [PATCH] RH: Remove the property blacklist exception builtin
|
||||||
|
|
||||||
|
Multipath set the default property blacklist exceptions to
|
||||||
|
(ID_SCSI_VPD|ID_WWN). This has the effect of blacklisting some internal
|
||||||
|
devices. These devices may never have multiple paths, but it is nice
|
||||||
|
to be able to set multipath up on them all the same. This patch simply
|
||||||
|
removes the default, and makes it so that if no property
|
||||||
|
blacklist_exception is given, then devices aren't failed for not matching
|
||||||
|
it.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/blacklist.c | 9 ++-------
|
||||||
|
multipath/multipath.conf.5 | 11 ++++++-----
|
||||||
|
tests/blacklist.c | 6 ++----
|
||||||
|
3 files changed, 10 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
|
||||||
|
index db58ccca..0c58aa32 100644
|
||||||
|
--- a/libmultipath/blacklist.c
|
||||||
|
+++ b/libmultipath/blacklist.c
|
||||||
|
@@ -187,12 +187,6 @@ setup_default_blist (struct config * conf)
|
||||||
|
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
- str = STRDUP("(SCSI_IDENT_|ID_WWN)");
|
||||||
|
- if (!str)
|
||||||
|
- return 1;
|
||||||
|
- if (store_ble(conf->elist_property, str, ORIGIN_DEFAULT))
|
||||||
|
- return 1;
|
||||||
|
-
|
||||||
|
vector_foreach_slot (conf->hwtable, hwe, i) {
|
||||||
|
if (hwe->bl_product) {
|
||||||
|
if (find_blacklist_device(conf->blist_device,
|
||||||
|
@@ -394,7 +388,8 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl,
|
||||||
|
*uid_attribute != '\0';
|
||||||
|
bool uid_attr_seen = false;
|
||||||
|
|
||||||
|
- r = MATCH_PROPERTY_BLIST_MISSING;
|
||||||
|
+ if (VECTOR_SIZE(conf->elist_property))
|
||||||
|
+ r = MATCH_PROPERTY_BLIST_MISSING;
|
||||||
|
udev_list_entry_foreach(list_entry,
|
||||||
|
udev_device_get_properties_list_entry(udev)) {
|
||||||
|
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 5adaced6..42a192f6 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -1296,9 +1296,14 @@ keywords. Both are regular expressions. For a full description of these keywords
|
||||||
|
Regular expression for an udev property. All
|
||||||
|
devices that have matching udev properties will be excluded/included.
|
||||||
|
The handling of the \fIproperty\fR keyword is special,
|
||||||
|
-because devices \fBmust\fR have at least one whitelisted udev property;
|
||||||
|
+because if a property blacklist_exception is set, devices \fBmust\fR have at
|
||||||
|
+least one whitelisted udev property;
|
||||||
|
otherwise they're treated as blacklisted, and the message
|
||||||
|
"\fIblacklisted, udev property missing\fR" is displayed in the logs.
|
||||||
|
+For example, setting the property blacklist_exception to
|
||||||
|
+\fB(SCSI_IDENT_|ID_WWN)\fR, will cause well-behaved SCSI devices and devices
|
||||||
|
+that provide a WWN (World Wide Number) to be included, and all others to be
|
||||||
|
+excluded. This works to exclude most non-multipathable devices.
|
||||||
|
.
|
||||||
|
.RS
|
||||||
|
.PP
|
||||||
|
@@ -1309,10 +1314,6 @@ Blacklisting by missing properties is only applied to devices which do have the
|
||||||
|
property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR)
|
||||||
|
set. Previously, it was applied to every device, possibly causing devices to be
|
||||||
|
blacklisted because of temporary I/O error conditions.
|
||||||
|
-.PP
|
||||||
|
-The default \fIblacklist exception\fR is: \fB(SCSI_IDENT_|ID_WWN)\fR, causing
|
||||||
|
-well-behaved SCSI devices and devices that provide a WWN (World Wide Number)
|
||||||
|
-to be included, and all others to be excluded.
|
||||||
|
.RE
|
||||||
|
.TP
|
||||||
|
.B protocol
|
||||||
|
diff --git a/tests/blacklist.c b/tests/blacklist.c
|
||||||
|
index d5c40898..d20e97af 100644
|
||||||
|
--- a/tests/blacklist.c
|
||||||
|
+++ b/tests/blacklist.c
|
||||||
|
@@ -380,7 +380,7 @@ static void test_property_missing(void **state)
|
||||||
|
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_PROPERTY_BLIST_MISSING);
|
||||||
|
+ MATCH_NOTHING);
|
||||||
|
assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"),
|
||||||
|
MATCH_NOTHING);
|
||||||
|
assert_int_equal(filter_property(&conf, &udev, 3, ""),
|
||||||
|
@@ -472,9 +472,7 @@ static void test_filter_path_missing1(void **state)
|
||||||
|
conf.blist_device = blist_device_foo_bar;
|
||||||
|
conf.blist_protocol = blist_protocol_fcp;
|
||||||
|
conf.blist_wwid = blist_wwid_xyzzy;
|
||||||
|
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
|
||||||
|
- assert_int_equal(filter_path(&conf, &miss1_pp),
|
||||||
|
- MATCH_PROPERTY_BLIST_MISSING);
|
||||||
|
+ assert_int_equal(filter_path(&conf, &miss1_pp), MATCH_NOTHING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This one matches the property whitelist, to test the other missing
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
106
0061-RH-don-t-start-without-a-config-file.patch
Normal file
106
0061-RH-don-t-start-without-a-config-file.patch
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 15 Oct 2014 10:39:30 -0500
|
||||||
|
Subject: [PATCH] RH: don't start without a config file
|
||||||
|
|
||||||
|
If /etc/multipath.conf doesn't exist, don't start multipathd and blacklist
|
||||||
|
all devices when running multipath. A completely blank configuration file
|
||||||
|
is almost never what users want. Also, people may have the multipath
|
||||||
|
packages installed but don't want to use them. This patch provides a
|
||||||
|
simple way to disable multipath. Simply removing or renaming
|
||||||
|
/etc/multipath.conf will keep multipath from doing anything.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 15 +++++++++++++++
|
||||||
|
libmultipath/config.h | 1 +
|
||||||
|
multipath/multipath.rules | 1 +
|
||||||
|
multipathd/multipathd.8 | 2 ++
|
||||||
|
multipathd/multipathd.service | 1 +
|
||||||
|
5 files changed, 20 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index 658bec8b..1c02e230 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -26,6 +26,7 @@
|
||||||
|
#include "devmapper.h"
|
||||||
|
#include "mpath_cmd.h"
|
||||||
|
#include "propsel.h"
|
||||||
|
+#include "version.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2)
|
||||||
|
@@ -778,6 +779,20 @@ load_config (char * file)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
|
||||||
|
+ } else {
|
||||||
|
+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
|
||||||
|
+ if (conf->blist_devnode == NULL) {
|
||||||
|
+ conf->blist_devnode = vector_alloc();
|
||||||
|
+ if (!conf->blist_devnode) {
|
||||||
|
+ condlog(0, "cannot allocate blacklist\n");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ if (store_ble(conf->blist_devnode, strdup(".*"),
|
||||||
|
+ ORIGIN_NO_CONFIG)) {
|
||||||
|
+ condlog(0, "cannot store default no-config blacklist\n");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->processed_main_config = 1;
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index 92c61a0d..160867cd 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -9,6 +9,7 @@
|
||||||
|
|
||||||
|
#define ORIGIN_DEFAULT 0
|
||||||
|
#define ORIGIN_CONFIG 1
|
||||||
|
+#define ORIGIN_NO_CONFIG 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In kernel, fast_io_fail == 0 means immediate failure on rport delete.
|
||||||
|
diff --git a/multipath/multipath.rules b/multipath/multipath.rules
|
||||||
|
index 9df11a95..0486bf70 100644
|
||||||
|
--- a/multipath/multipath.rules
|
||||||
|
+++ b/multipath/multipath.rules
|
||||||
|
@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath"
|
||||||
|
ENV{nompath}=="?*", GOTO="end_mpath"
|
||||||
|
IMPORT{cmdline}="multipath"
|
||||||
|
ENV{multipath}=="off", GOTO="end_mpath"
|
||||||
|
+TEST!="/etc/multipath.conf", GOTO="end_mpath"
|
||||||
|
|
||||||
|
ENV{DEVTYPE}!="partition", GOTO="test_dev"
|
||||||
|
IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH"
|
||||||
|
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
|
||||||
|
index 048a838d..8bd47a80 100644
|
||||||
|
--- a/multipathd/multipathd.8
|
||||||
|
+++ b/multipathd/multipathd.8
|
||||||
|
@@ -39,6 +39,8 @@ map regains its maximum performance and redundancy.
|
||||||
|
This daemon executes the external \fBmultipath\fR tool when events occur.
|
||||||
|
In turn, the multipath tool signals the multipathd daemon when it is done with
|
||||||
|
devmap reconfiguration, so that it can refresh its failed path list.
|
||||||
|
+
|
||||||
|
+In this Linux distribution, multipathd does not run unless a /etc/multipath.conf file exists.
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.\" ----------------------------------------------------------------------------
|
||||||
|
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
|
||||||
|
index ba24983e..17434cef 100644
|
||||||
|
--- a/multipathd/multipathd.service
|
||||||
|
+++ b/multipathd/multipathd.service
|
||||||
|
@@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service
|
||||||
|
Before=iscsi.service iscsid.service lvm2-activation-early.service
|
||||||
|
Before=local-fs-pre.target blk-availability.service
|
||||||
|
After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service
|
||||||
|
+ConditionPathExists=/etc/multipath.conf
|
||||||
|
DefaultDependencies=no
|
||||||
|
Conflicts=shutdown.target
|
||||||
|
ConditionKernelCommandLine=!nompath
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
60
0062-RH-use-rpm-optflags-if-present.patch
Normal file
60
0062-RH-use-rpm-optflags-if-present.patch
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 19 Apr 2017 06:10:01 -0500
|
||||||
|
Subject: [PATCH] RH: use rpm optflags if present
|
||||||
|
|
||||||
|
Use the passed in optflags when compiling as an RPM, and keep the
|
||||||
|
default flags as close as possible to the current fedora flags, while
|
||||||
|
still being generic.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile.inc | 24 ++++++++++++++++++------
|
||||||
|
1 file changed, 18 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
|
index 873fb62f..479523bc 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -89,15 +89,27 @@ TEST_CC_OPTION = $(shell \
|
||||||
|
echo "$(2)"; \
|
||||||
|
fi)
|
||||||
|
|
||||||
|
-STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
|
||||||
|
ERROR_DISCARDED_QUALIFIERS := $(call TEST_CC_OPTION,-Werror=discarded-qualifiers,)
|
||||||
|
WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered -Wno-error=clobbered,)
|
||||||
|
|
||||||
|
-OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
|
||||||
|
-WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int \
|
||||||
|
+ifndef RPM_OPT_FLAGS
|
||||||
|
+ STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
|
||||||
|
+ OPTFLAGS := -O2 -g -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions \
|
||||||
|
+ $(STACKPROT) -grecord-gcc-switches \
|
||||||
|
+ -fasynchronous-unwind-tables --param=ssp-buffer-size=4
|
||||||
|
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-hardened-cc1 && echo 1),1)
|
||||||
|
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1
|
||||||
|
+ endif
|
||||||
|
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-annobin-cc1 && echo 1),1)
|
||||||
|
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1
|
||||||
|
+ endif
|
||||||
|
+else
|
||||||
|
+ OPTFLAGS := $(RPM_OPT_FLAGS) --param=ssp-buffer-size=4
|
||||||
|
+endif
|
||||||
|
+WARNFLAGS := -Werror -Wextra -Wformat=2 -Werror=implicit-int \
|
||||||
|
-Werror=implicit-function-declaration -Werror=format-security \
|
||||||
|
- $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS)
|
||||||
|
-CPPFLAGS := -Wp,-D_FORTIFY_SOURCE=2
|
||||||
|
+ $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
|
||||||
|
+ -Wstrict-prototypes
|
||||||
|
CFLAGS := $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
|
||||||
|
-DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
|
||||||
|
-MMD -MP
|
||||||
|
@@ -135,4 +147,4 @@ check_file = $(shell \
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
@echo building $@ because of $?
|
||||||
|
- $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||||
|
+ $(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
784
0063-RH-add-mpathconf.patch
Normal file
784
0063-RH-add-mpathconf.patch
Normal file
@ -0,0 +1,784 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 16 Oct 2014 15:49:01 -0500
|
||||||
|
Subject: [PATCH] RH: add mpathconf
|
||||||
|
|
||||||
|
mpathconf is a program (largely based on lvmcomf) to help users
|
||||||
|
configure /etc/multipath.conf and enable or disable multipathing. It
|
||||||
|
has a couple of built-in options that can be set directly from the
|
||||||
|
command line. But, mostly it is used to get a multipath.conf file
|
||||||
|
with the OS defaults, and to enable and disable multipathing via
|
||||||
|
a single command.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 2 +
|
||||||
|
multipath/Makefile | 5 +
|
||||||
|
multipath/mpathconf | 565 ++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
multipath/mpathconf.8 | 135 ++++++++++
|
||||||
|
4 files changed, 707 insertions(+)
|
||||||
|
create mode 100644 multipath/mpathconf
|
||||||
|
create mode 100644 multipath/mpathconf.8
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index 1c02e230..a253a936 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -781,6 +781,8 @@ load_config (char * file)
|
||||||
|
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
|
||||||
|
} else {
|
||||||
|
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
|
||||||
|
+ condlog(0, "You can run \"/sbin/mpathconf --enable\" to create");
|
||||||
|
+ condlog(0, "/etc/multipath.conf. See man mpathconf(8) for more details");
|
||||||
|
if (conf->blist_devnode == NULL) {
|
||||||
|
conf->blist_devnode = vector_alloc();
|
||||||
|
if (!conf->blist_devnode) {
|
||||||
|
diff --git a/multipath/Makefile b/multipath/Makefile
|
||||||
|
index b9bbb3cf..e720c7f6 100644
|
||||||
|
--- a/multipath/Makefile
|
||||||
|
+++ b/multipath/Makefile
|
||||||
|
@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
|
||||||
|
$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS)
|
||||||
|
$(GZIP) $(EXEC).8 > $(EXEC).8.gz
|
||||||
|
$(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
|
||||||
|
+ $(GZIP) mpathconf.8 > mpathconf.8.gz
|
||||||
|
|
||||||
|
install:
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
|
||||||
|
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
|
||||||
|
+ $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
|
||||||
|
@@ -29,13 +31,16 @@ install:
|
||||||
|
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
|
||||||
|
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
|
||||||
|
$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
|
||||||
|
+ $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(man8dir)
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
|
||||||
|
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
|
||||||
|
$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
|
||||||
|
+ $(RM) $(DESTDIR)$(bindir)/mpathconf
|
||||||
|
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
|
||||||
|
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
|
||||||
|
+ $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz
|
||||||
|
|
||||||
|
clean: dep_clean
|
||||||
|
$(RM) core *.o $(EXEC) *.gz
|
||||||
|
diff --git a/multipath/mpathconf b/multipath/mpathconf
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..f0d09cbb
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/multipath/mpathconf
|
||||||
|
@@ -0,0 +1,565 @@
|
||||||
|
+#!/bin/bash
|
||||||
|
+#
|
||||||
|
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
|
||||||
|
+#
|
||||||
|
+# This file is part of the device-mapper-multipath package.
|
||||||
|
+#
|
||||||
|
+# This copyrighted material is made available to anyone wishing to use,
|
||||||
|
+# modify, copy, or redistribute it subject to the terms and conditions
|
||||||
|
+# of the GNU General Public License v.2.
|
||||||
|
+#
|
||||||
|
+# You should have received a copy of the GNU General Public License
|
||||||
|
+# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Simple editting of /etc/multipath.conf
|
||||||
|
+# This program was largely ripped off from lvmconf
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+unset ENABLE FIND FRIENDLY PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST
|
||||||
|
+
|
||||||
|
+DEFAULT_CONFIG="# device-mapper-multipath configuration file
|
||||||
|
+
|
||||||
|
+# For a complete list of the default configuration values, run either:
|
||||||
|
+# # multipath -t
|
||||||
|
+# or
|
||||||
|
+# # multipathd show config
|
||||||
|
+
|
||||||
|
+# For a list of configuration options with descriptions, see the
|
||||||
|
+# multipath.conf man page.
|
||||||
|
+
|
||||||
|
+defaults {
|
||||||
|
+ user_friendly_names yes
|
||||||
|
+ find_multipaths yes
|
||||||
|
+}"
|
||||||
|
+
|
||||||
|
+CONFIGFILE="/etc/multipath.conf"
|
||||||
|
+OUTPUTFILE="/etc/multipath.conf"
|
||||||
|
+MULTIPATHDIR="/etc/multipath"
|
||||||
|
+TMPFILE="/etc/multipath/.multipath.conf.tmp"
|
||||||
|
+WWIDS=0
|
||||||
|
+
|
||||||
|
+function usage
|
||||||
|
+{
|
||||||
|
+ echo "usage: $0 <command>"
|
||||||
|
+ echo ""
|
||||||
|
+ echo "Commands:"
|
||||||
|
+ echo "Enable: --enable "
|
||||||
|
+ 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 default property blacklist (Default n): --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>"
|
||||||
|
+ echo "start/stop/reload multipathd (Default n): --with_multipathd <y|n>"
|
||||||
|
+ echo "select output file (Default /etc/multipath.conf): --outfile <FILE>"
|
||||||
|
+ echo ""
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function add_wwid
|
||||||
|
+{
|
||||||
|
+ INDEX=0
|
||||||
|
+ while [ "$INDEX" -lt "$WWIDS" ] ; do
|
||||||
|
+ if [ "$1" = "${WWID_LIST[$INDEX]}" ] ; then
|
||||||
|
+ return
|
||||||
|
+ fi
|
||||||
|
+ ((INDEX++))
|
||||||
|
+ done
|
||||||
|
+ WWID_LIST[$WWIDS]="$1"
|
||||||
|
+ ((WWIDS++))
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function get_dm_deps
|
||||||
|
+{
|
||||||
|
+ shift 3
|
||||||
|
+ while [ -n "$1" -a -n "$2" ]; do
|
||||||
|
+ MAJOR=$(echo $1 | tr -d '(,')
|
||||||
|
+ MINOR=$(echo $2 | tr -d ')')
|
||||||
|
+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null`
|
||||||
|
+ if [ -n "$UUID" ] ; then
|
||||||
|
+ set_dm_wwid $UUID
|
||||||
|
+ fi
|
||||||
|
+ shift 2
|
||||||
|
+ done
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function set_dm_wwid
|
||||||
|
+{
|
||||||
|
+ if [[ "$1" =~ ^part[[:digit:]]+-mpath- ]] ; then
|
||||||
|
+ add_wwid "${1##part*-mpath-}"
|
||||||
|
+ elif [[ "$1" =~ ^mpath- ]] ; then
|
||||||
|
+ add_wwid "${1##mpath-}"
|
||||||
|
+ else
|
||||||
|
+ get_dm_deps `dmsetup deps -u $1`
|
||||||
|
+ fi
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function set_wwid
|
||||||
|
+{
|
||||||
|
+ UUID=""
|
||||||
|
+ if [[ "$1" =~ ^[[:digit:]]+:[[:digit:]]+$ ]] ; then
|
||||||
|
+ MAJOR=${1%%:*}
|
||||||
|
+ MINOR=${1##*:}
|
||||||
|
+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null`
|
||||||
|
+ else
|
||||||
|
+ UUID=`dmsetup info -c --noheadings -o uuid $1 2> /dev/null`
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$UUID" ] ; then
|
||||||
|
+ set_dm_wwid $UUID
|
||||||
|
+ else
|
||||||
|
+ add_wwid "$1"
|
||||||
|
+ fi
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function parse_args
|
||||||
|
+{
|
||||||
|
+ while [ -n "$1" ]; do
|
||||||
|
+ case $1 in
|
||||||
|
+ --enable)
|
||||||
|
+ ENABLE=1
|
||||||
|
+ shift
|
||||||
|
+ ;;
|
||||||
|
+ --disable)
|
||||||
|
+ ENABLE=0
|
||||||
|
+ shift
|
||||||
|
+ ;;
|
||||||
|
+ --allow)
|
||||||
|
+ ENABLE=2
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ set_wwid $2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --user_friendly_names)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ FRIENDLY=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --find_multipaths)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ FIND=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --property_blacklist)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ PROPERTY=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --enable_foreign)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ FOREIGN=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --with_module)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ MODULE=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --with_multipathd)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ MULTIPATHD=$2
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ --outfile)
|
||||||
|
+ if [ -n "$2" ]; then
|
||||||
|
+ OUTPUTFILE=$2
|
||||||
|
+ HAVE_OUTFILE=1
|
||||||
|
+ shift 2
|
||||||
|
+ else
|
||||||
|
+ usage
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ ;;
|
||||||
|
+ *)
|
||||||
|
+ usage
|
||||||
|
+ exit
|
||||||
|
+ esac
|
||||||
|
+ done
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function validate_args
|
||||||
|
+{
|
||||||
|
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" -o -n "$FOREIGN" ]; then
|
||||||
|
+ echo "ignoring extra parameters on disable"
|
||||||
|
+ FRIENDLY=""
|
||||||
|
+ FIND=""
|
||||||
|
+ PROPERTY=""
|
||||||
|
+ MODULE=""
|
||||||
|
+ FOREIGN=""
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then
|
||||||
|
+ echo "--user_friendly_names must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then
|
||||||
|
+ echo "--find_multipaths must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$PROPERTY" ] && [ "$PROPERTY" != "y" -a "$PROPERTY" != "n" ]; then
|
||||||
|
+ echo "--property_blacklist must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$FOREIGN" ] && [ "$FOREIGN" != "y" -a "$FOREIGN" != "n" ]; then
|
||||||
|
+ echo "--enable_foreign must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" -a -z "$FOREIGN" ]; then
|
||||||
|
+ SHOW_STATUS=1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
|
||||||
|
+ echo "--with_module must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$MULTIPATHD" ] && [ "$MULTIPATHD" != "y" -a "$MULTIPATHD" != "n" ]; then
|
||||||
|
+ echo "--with_multipathd must be either 'y' or 'n'"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+ if [ "$ENABLE" = 2 -a -z "$HAVE_OUTFILE" ]; then
|
||||||
|
+ echo "Because --allow makes changes that cannot be automatically reversed,"
|
||||||
|
+ echo "you must set --outfile when you set --allow"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+function add_blacklist_exceptions
|
||||||
|
+{
|
||||||
|
+ INDEX=0
|
||||||
|
+ while [ "$INDEX" -lt "$WWIDS" ] ; do
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
|
||||||
|
+ wwid '"\"${WWID_LIST[$INDEX]}\""'
|
||||||
|
+' $TMPFILE
|
||||||
|
+ ((INDEX++))
|
||||||
|
+ done
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+umask 0077
|
||||||
|
+
|
||||||
|
+parse_args "$@"
|
||||||
|
+
|
||||||
|
+validate_args
|
||||||
|
+
|
||||||
|
+if [ ! -d "$MULTIPATHDIR" ]; then
|
||||||
|
+ echo "/etc/multipath/ does not exist. failing"
|
||||||
|
+ exit 1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+rm $TMPFILE 2> /dev/null
|
||||||
|
+echo "$DEFAULT_CONFIG" > $TMPFILE
|
||||||
|
+if [ -f "$CONFIGFILE" ]; then
|
||||||
|
+ cp $CONFIGFILE $TMPFILE
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if grep -q "^blacklist[[:space:]]*{" $TMPFILE ; then
|
||||||
|
+ HAVE_BLACKLIST=1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if grep -q "^blacklist_exceptions[[:space:]]*{" $TMPFILE ; then
|
||||||
|
+ HAVE_EXCEPTIONS=1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if grep -q "^defaults[[:space:]]*{" $TMPFILE ; then
|
||||||
|
+ HAVE_DEFAULTS=1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -z "$MODULE" -o "$MODULE" = "y" ]; then
|
||||||
|
+ if lsmod | grep -q "dm_multipath" ; then
|
||||||
|
+ HAVE_MODULE=1
|
||||||
|
+ else
|
||||||
|
+ HAVE_MODULE=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$MULTIPATHD" = "y" ]; then
|
||||||
|
+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then
|
||||||
|
+ HAVE_MULTIPATHD=1
|
||||||
|
+ else
|
||||||
|
+ HAVE_MULTIPATHD=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$HAVE_BLACKLIST" = "1" ]; then
|
||||||
|
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then
|
||||||
|
+ HAVE_DISABLE=1
|
||||||
|
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then
|
||||||
|
+ HAVE_DISABLE=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$HAVE_BLACKLIST" = "1" ]; then
|
||||||
|
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then
|
||||||
|
+ HAVE_WWID_DISABLE=1
|
||||||
|
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then
|
||||||
|
+ HAVE_WWID_DISABLE=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$HAVE_DEFAULTS" = "1" ]; then
|
||||||
|
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then
|
||||||
|
+ HAVE_FIND=1
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then
|
||||||
|
+ HAVE_FIND=0
|
||||||
|
+ fi
|
||||||
|
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then
|
||||||
|
+ HAVE_FRIENDLY=1
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then
|
||||||
|
+ HAVE_FRIENDLY=0
|
||||||
|
+ fi
|
||||||
|
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*enable_foreign" ; then
|
||||||
|
+ HAVE_FOREIGN=0
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]]*\"\^\$\"" ; then
|
||||||
|
+ HAVE_FOREIGN=1
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]]*\"NONE\"" ; then
|
||||||
|
+ HAVE_FOREIGN=1
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]] \"\.\?\*\"" ; then
|
||||||
|
+ HAVE_FOREIGN=2
|
||||||
|
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
|
||||||
|
+ HAVE_FOREIGN=3
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$HAVE_EXCEPTIONS" = "1" ]; then
|
||||||
|
+ if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
|
||||||
|
+ HAVE_PROPERTY=1
|
||||||
|
+ elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
|
||||||
|
+ HAVE_PROPERTY=0
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -n "$SHOW_STATUS" ]; then
|
||||||
|
+ if [ -z "$HAVE_DISABLE" -o "$HAVE_DISABLE" = 0 ]; then
|
||||||
|
+ echo "multipath is enabled"
|
||||||
|
+ else
|
||||||
|
+ echo "multipath is disabled"
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then
|
||||||
|
+ echo "find_multipaths is disabled"
|
||||||
|
+ else
|
||||||
|
+ echo "find_multipaths is enabled"
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then
|
||||||
|
+ echo "user_friendly_names is disabled"
|
||||||
|
+ else
|
||||||
|
+ echo "user_friendly_names is enabled"
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_PROPERTY" -o "$HAVE_PROPERTY" = 0 ]; then
|
||||||
|
+ echo "default property blacklist is disabled"
|
||||||
|
+ else
|
||||||
|
+ echo "default property blacklist is enabled"
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_FOREIGN" -o "$HAVE_FOREIGN" = 0 ]; then
|
||||||
|
+ echo "enable_foreign is not set (no foreign multipath devices will be shown)"
|
||||||
|
+ elif [ "$HAVE_FOREIGN" = 1 ]; then
|
||||||
|
+ echo "enable_foreign is set (no foreign multipath devices will be shown)"
|
||||||
|
+ elif [ "$HAVE_FOREIGN" = 2 ]; then
|
||||||
|
+ echo "enable_foreign is set (all foreign multipath devices will be shown)"
|
||||||
|
+ else
|
||||||
|
+ echo "enable_foreign is set (foreign multipath devices may not be shown)"
|
||||||
|
+ fi
|
||||||
|
+ if [ -n "$HAVE_MODULE" ]; then
|
||||||
|
+ if [ "$HAVE_MODULE" = 1 ]; then
|
||||||
|
+ echo "dm_multipath module is loaded"
|
||||||
|
+ else
|
||||||
|
+ echo "dm_multipath module is not loaded"
|
||||||
|
+ fi
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_MULTIPATHD" ]; then
|
||||||
|
+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then
|
||||||
|
+ HAVE_MULTIPATHD=1
|
||||||
|
+ else
|
||||||
|
+ HAVE_MULTIPATHD=0
|
||||||
|
+ fi
|
||||||
|
+ fi
|
||||||
|
+ if [ "$HAVE_MULTIPATHD" = 1 ]; then
|
||||||
|
+ echo "multipathd is running"
|
||||||
|
+ else
|
||||||
|
+ echo "multipathd is not running"
|
||||||
|
+ fi
|
||||||
|
+ exit 0
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -z "$HAVE_BLACKLIST" ]; then
|
||||||
|
+ cat >> $TMPFILE <<- _EOF_
|
||||||
|
+
|
||||||
|
+blacklist {
|
||||||
|
+}
|
||||||
|
+_EOF_
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -z "$HAVE_DEFAULTS" ]; then
|
||||||
|
+ cat >> $TMPFILE <<- _EOF_
|
||||||
|
+
|
||||||
|
+defaults {
|
||||||
|
+}
|
||||||
|
+_EOF_
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$ENABLE" = 2 ]; then
|
||||||
|
+ if [ "$HAVE_DISABLE" = 1 ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
|
||||||
|
+ fi
|
||||||
|
+ if [ -z "$HAVE_WWID_DISABLE" ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/ a\
|
||||||
|
+ wwid ".*"
|
||||||
|
+' $TMPFILE
|
||||||
|
+ elif [ "$HAVE_WWID_DISABLE" = 0 ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE
|
||||||
|
+ fi
|
||||||
|
+ if [ "$HAVE_EXCEPTIONS" = 1 ]; then
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE
|
||||||
|
+ else
|
||||||
|
+ cat >> $TMPFILE <<- _EOF_
|
||||||
|
+
|
||||||
|
+blacklist_exceptions {
|
||||||
|
+}
|
||||||
|
+_EOF_
|
||||||
|
+ fi
|
||||||
|
+ add_blacklist_exceptions
|
||||||
|
+elif [ "$ENABLE" = 1 ]; then
|
||||||
|
+ if [ "$HAVE_DISABLE" = 1 ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
|
||||||
|
+ fi
|
||||||
|
+elif [ "$ENABLE" = 0 ]; then
|
||||||
|
+ if [ -z "$HAVE_DISABLE" ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/ a\
|
||||||
|
+ devnode ".*"
|
||||||
|
+' $TMPFILE
|
||||||
|
+ elif [ "$HAVE_DISABLE" = 0 ]; then
|
||||||
|
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$FIND" = "n" ]; then
|
||||||
|
+ if [ "$HAVE_FIND" = 1 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+elif [ "$FIND" = "y" ]; then
|
||||||
|
+ if [ -z "$HAVE_FIND" ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/ a\
|
||||||
|
+ find_multipaths yes
|
||||||
|
+' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ "$HAVE_FIND" = 0 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$FRIENDLY" = "n" ]; then
|
||||||
|
+ if [ "$HAVE_FRIENDLY" = 1 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+elif [ "$FRIENDLY" = "y" ]; then
|
||||||
|
+ if [ -z "$HAVE_FRIENDLY" ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/ a\
|
||||||
|
+ user_friendly_names yes
|
||||||
|
+' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ "$HAVE_FRIENDLY" = 0 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$PROPERTY" = "n" ]; then
|
||||||
|
+ if [ "$HAVE_PROPERTY" = 1 ]; then
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+elif [ "$PROPERTY" = "y" ]; then
|
||||||
|
+ if [ -z "$HAVE_PROPERTY" -a -z "$HAVE_EXCEPTIONS" ]; then
|
||||||
|
+ cat >> $TMPFILE << _EOF_
|
||||||
|
+
|
||||||
|
+blacklist_exceptions {
|
||||||
|
+ property "(SCSI_IDENT_|ID_WWN)"
|
||||||
|
+}
|
||||||
|
+_EOF_
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ -z "$HAVE_PROPERTY" ]; then
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
|
||||||
|
+ property "(SCSI_IDENT_|ID_WWN)"
|
||||||
|
+' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ "$HAVE_PROPERTY" = 0 ]; then
|
||||||
|
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ "$FOREIGN" = "y" ]; then
|
||||||
|
+ if [ -z "$HAVE_FOREIGN" ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/ a\
|
||||||
|
+ enable_foreign ".*"
|
||||||
|
+' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ elif [ "$HAVE_FOREIGN" = 0 -o "$HAVE_FOREIGN" = 1 -o "$HAVE_FOREIGN" = 3 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*#\?[[:space:]]*enable_foreign.*$/ enable_foreign ".*"/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+elif [ "$FOREIGN" = "n" ]; then
|
||||||
|
+ if [ "$HAVE_FOREIGN" = 2 -o "$HAVE_FOREIGN" = 3 ]; then
|
||||||
|
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*enable_foreign/# enable_foreign/' $TMPFILE
|
||||||
|
+ CHANGED_CONFIG=1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+if [ -f "$OUTPUTFILE" ]; then
|
||||||
|
+ cp $OUTPUTFILE $OUTPUTFILE.old
|
||||||
|
+ if [ $? != 0 ]; then
|
||||||
|
+ echo "failed to backup old config file, $OUTPUTFILE not updated"
|
||||||
|
+ exit 1
|
||||||
|
+ fi
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+cp $TMPFILE $OUTPUTFILE
|
||||||
|
+if [ $? != 0 ]; then
|
||||||
|
+ echo "failed to copy new config file into place, check $OUTPUTFILE is still OK"
|
||||||
|
+ exit 1
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
+rm -f $TMPFILE
|
||||||
|
+
|
||||||
|
+if [ "$ENABLE" = 1 ]; then
|
||||||
|
+ if [ "$HAVE_MODULE" = 0 ]; then
|
||||||
|
+ modprobe dm_multipath
|
||||||
|
+ fi
|
||||||
|
+ if [ "$HAVE_MULTIPATHD" = 0 ]; then
|
||||||
|
+ systemctl start multipathd.service
|
||||||
|
+ fi
|
||||||
|
+elif [ "$ENABLE" = 0 ]; then
|
||||||
|
+ if [ "$HAVE_MULTIPATHD" = 1 ]; then
|
||||||
|
+ systemctl stop multipathd.service
|
||||||
|
+ fi
|
||||||
|
+elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then
|
||||||
|
+ systemctl reload multipathd.service
|
||||||
|
+fi
|
||||||
|
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..b82961d6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/multipath/mpathconf.8
|
||||||
|
@@ -0,0 +1,135 @@
|
||||||
|
+.TH MPATHCONF 8 "June 2010" "" "Linux Administrator's Manual"
|
||||||
|
+.SH NAME
|
||||||
|
+mpathconf - A tool for configuring device-mapper-multipath
|
||||||
|
+.SH SYNOPSIS
|
||||||
|
+.B mpathconf
|
||||||
|
+.RB [\| commands \|]
|
||||||
|
+.RB [\| options \|]
|
||||||
|
+.SH DESCRIPTION
|
||||||
|
+.B mpathconf
|
||||||
|
+is a utility that creates or modifies
|
||||||
|
+.B /etc/multipath.conf.
|
||||||
|
+It can enable or disable multipathing and configure some common options.
|
||||||
|
+.B mpathconf
|
||||||
|
+can also load the
|
||||||
|
+.B dm_multipath
|
||||||
|
+module, start and stop the
|
||||||
|
+.B multipathd
|
||||||
|
+daemon, and configure the
|
||||||
|
+.B multipathd
|
||||||
|
+service to start automatically or not. If
|
||||||
|
+.B mpathconf
|
||||||
|
+is called with no commands, it will display the current configuration, but
|
||||||
|
+will not create of modify
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+
|
||||||
|
+The default options for mpathconf are
|
||||||
|
+.B --with_module
|
||||||
|
+The
|
||||||
|
+.B --with_multipathd
|
||||||
|
+option is not set by default. Enabling multipathing will load the
|
||||||
|
+.B dm_multipath
|
||||||
|
+module but it will not immediately start it. This is so
|
||||||
|
+that users can manually edit their config file if necessary, before starting
|
||||||
|
+.B multipathd.
|
||||||
|
+
|
||||||
|
+If
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+already exists, mpathconf will edit it. If it does not exist, mpathconf will
|
||||||
|
+create a default file with
|
||||||
|
+.B user_friendly_names
|
||||||
|
+and
|
||||||
|
+.B find_multipaths
|
||||||
|
+set. To disable these, use the
|
||||||
|
+.B --user_friendly_names n
|
||||||
|
+and
|
||||||
|
+.B --find_multipaths n
|
||||||
|
+options
|
||||||
|
+.SH COMMANDS
|
||||||
|
+.TP
|
||||||
|
+.B --enable
|
||||||
|
+Removes any line that blacklists all device nodes from the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+blacklist section. Also, creates
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+if it doesn't exist.
|
||||||
|
+.TP
|
||||||
|
+.B --disable
|
||||||
|
+Adds a line that blacklists all device nodes to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+blacklist section. If no blacklist section exists, it will create one.
|
||||||
|
+.TP
|
||||||
|
+.B --allow \fB<device>\fP
|
||||||
|
+Modifies the \fB/etc/multipath/conf\fP blacklist to blacklist all
|
||||||
|
+wwids and the blacklist_exceptions to whitelist \fB<device>\fP. \fB<device>\fP
|
||||||
|
+can be in the form of MAJOR:MINOR, a wwid, or the name of a device-mapper
|
||||||
|
+device, either a multipath device, or any device on stacked on top of one or
|
||||||
|
+more multipath devices. This command can be used multiple times to allow
|
||||||
|
+multiple devices. \fBNOTE:\fP This action will create a configuration file that
|
||||||
|
+mpathconf will not be able to revert back to its previous state. Because
|
||||||
|
+of this, \fB--outfile\fP is required when using \fB--allow\fP.
|
||||||
|
+.TP
|
||||||
|
+.B --user_friendly_names \fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this adds the line
|
||||||
|
+.B user_friendly_names yes
|
||||||
|
+to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+defaults section. If set to \fBn\fP, this removes the line, if present. This
|
||||||
|
+command can be used along with any other command.
|
||||||
|
+.TP
|
||||||
|
+.B --find_multipaths\fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this adds the line
|
||||||
|
+.B find_multipaths yes
|
||||||
|
+to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+defaults section. If set to \fBn\fP, this removes the line, if present. This
|
||||||
|
+command can be used along with any other command.
|
||||||
|
+.TP
|
||||||
|
+.B --property_blacklist \fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this adds the line
|
||||||
|
+.B property "(SCSI_IDENT_|ID_WWN)"
|
||||||
|
+to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+blacklist_exceptions section. If set to \fBn\fP, this removes the line, if
|
||||||
|
+present. This command can be used along with any other command.
|
||||||
|
+.TP
|
||||||
|
+.B --enable_foreign\fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBn\fP, this adds the line
|
||||||
|
+.B enable_foreign "^$"
|
||||||
|
+to the
|
||||||
|
+.B /etc/multipath.conf
|
||||||
|
+defaults section. if set to \fBy\fP, this removes the line, if present. This
|
||||||
|
+command can be used along with any other command.
|
||||||
|
+.TP
|
||||||
|
+.B --outfile \fB<filename>\fP
|
||||||
|
+Write the resulting multipath configuration to \fB<filename>\fP instead of
|
||||||
|
+\fB/etc/multipath.conf\fP.
|
||||||
|
+.SH OPTIONS
|
||||||
|
+.TP
|
||||||
|
+.B --with_module\fP { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this runs
|
||||||
|
+.B modprobe dm_multipath
|
||||||
|
+to install the multipath modules. This option only works with the
|
||||||
|
+.B --enable
|
||||||
|
+command. This option is set to \fBy\fP by default.
|
||||||
|
+.TP
|
||||||
|
+.B --with_multipathd { \fBy\fP | \fBn\fP }
|
||||||
|
+If set to \fBy\fP, this runs
|
||||||
|
+.B service multipathd start
|
||||||
|
+to start the multipathd daemon on \fB--enable\fP,
|
||||||
|
+.B service multipathd stop
|
||||||
|
+to stop the multipathd daemon on \fB--disable\fP, and
|
||||||
|
+.B service multipathd reload
|
||||||
|
+to reconfigure multipathd on \fB--user_frindly_names\fP and
|
||||||
|
+\fB--find_multipaths\fP.
|
||||||
|
+This option is set to \fBn\fP by default.
|
||||||
|
+.SH FILES
|
||||||
|
+.BR /etc/multipath.conf
|
||||||
|
+.SH "SEE ALSO"
|
||||||
|
+.BR multipath.conf (5),
|
||||||
|
+.BR modprobe (8),
|
||||||
|
+.BR multipath (8),
|
||||||
|
+.BR multipathd (8),
|
||||||
|
+.BR service (8),
|
||||||
|
+.SH AUTHOR
|
||||||
|
+Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
169
0064-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Normal file
169
0064-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 17 Oct 2014 11:20:34 -0500
|
||||||
|
Subject: [PATCH] RH: add wwids from kernel cmdline mpath.wwids with -A
|
||||||
|
|
||||||
|
This patch adds another option to multipath, "-A", which reads
|
||||||
|
/proc/cmdline for mpath.wwid=<WWID> options, and adds any wwids it finds
|
||||||
|
to /etc/multipath/wwids. While this isn't usually important during
|
||||||
|
normal operation, since these wwids should already be added, it can be
|
||||||
|
helpful during installation, to make sure that multipath can claim
|
||||||
|
devices as its own, before LVM or something else makes use of them. The
|
||||||
|
patch also execs "/sbin/multipath -A" before running multipathd in
|
||||||
|
multipathd.service
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/wwids.c | 44 +++++++++++++++++++++++++++++++++++
|
||||||
|
libmultipath/wwids.h | 1 +
|
||||||
|
multipath/main.c | 10 ++++++--
|
||||||
|
multipath/multipath.8 | 7 +++++-
|
||||||
|
multipathd/multipathd.service | 1 +
|
||||||
|
5 files changed, 60 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
|
||||||
|
index 61d9c39e..c7a16636 100644
|
||||||
|
--- a/libmultipath/wwids.c
|
||||||
|
+++ b/libmultipath/wwids.c
|
||||||
|
@@ -451,3 +451,47 @@ int unmark_failed_wwid(const char *wwid)
|
||||||
|
print_failed_wwid_result("unmark_failed", wwid, r);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+int remember_cmdline_wwid(void)
|
||||||
|
+{
|
||||||
|
+ FILE *f = NULL;
|
||||||
|
+ char buf[LINE_MAX], *next, *ptr;
|
||||||
|
+ int ret = 0;
|
||||||
|
+
|
||||||
|
+ f = fopen("/proc/cmdline", "re");
|
||||||
|
+ if (!f) {
|
||||||
|
+ condlog(0, "can't open /proc/cmdline : %s", strerror(errno));
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!fgets(buf, sizeof(buf), f)) {
|
||||||
|
+ if (ferror(f))
|
||||||
|
+ condlog(0, "read of /proc/cmdline failed : %s",
|
||||||
|
+ strerror(errno));
|
||||||
|
+ else
|
||||||
|
+ condlog(0, "couldn't read /proc/cmdline");
|
||||||
|
+ fclose(f);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ fclose(f);
|
||||||
|
+ next = buf;
|
||||||
|
+ while((ptr = strstr(next, "mpath.wwid="))) {
|
||||||
|
+ ptr += 11;
|
||||||
|
+ next = strpbrk(ptr, " \t\n");
|
||||||
|
+ if (next) {
|
||||||
|
+ *next = '\0';
|
||||||
|
+ next++;
|
||||||
|
+ }
|
||||||
|
+ if (strlen(ptr)) {
|
||||||
|
+ if (remember_wwid(ptr) != 0)
|
||||||
|
+ ret = -1;
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ condlog(0, "empty mpath.wwid kernel command line option");
|
||||||
|
+ ret = -1;
|
||||||
|
+ }
|
||||||
|
+ if (!next)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
diff --git a/libmultipath/wwids.h b/libmultipath/wwids.h
|
||||||
|
index 0c6ee54d..e32a0b0e 100644
|
||||||
|
--- a/libmultipath/wwids.h
|
||||||
|
+++ b/libmultipath/wwids.h
|
||||||
|
@@ -17,6 +17,7 @@ int remember_wwid(char *wwid);
|
||||||
|
int check_wwids_file(char *wwid, int write_wwid);
|
||||||
|
int remove_wwid(char *wwid);
|
||||||
|
int replace_wwids(vector mp);
|
||||||
|
+int remember_cmdline_wwid(void);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WWID_IS_NOT_FAILED = 0,
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 3da692dc..ce48a932 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -135,7 +135,7 @@ usage (char * progname)
|
||||||
|
fprintf (stderr, " %s [-v level] [-R retries] -F\n", progname);
|
||||||
|
fprintf (stderr, " %s [-v level] [-l|-ll] [device]\n", progname);
|
||||||
|
fprintf (stderr, " %s [-v level] [-a|-w] device\n", progname);
|
||||||
|
- fprintf (stderr, " %s [-v level] -W\n", progname);
|
||||||
|
+ fprintf (stderr, " %s [-v level] [-A|-W]\n", progname);
|
||||||
|
fprintf (stderr, " %s [-v level] [-i] [-c|-C] device\n", progname);
|
||||||
|
fprintf (stderr, " %s [-v level] [-i] [-u|-U]\n", progname);
|
||||||
|
fprintf (stderr, " %s [-h|-t|-T]\n", progname);
|
||||||
|
@@ -149,6 +149,8 @@ usage (char * progname)
|
||||||
|
" -f flush a multipath device map\n"
|
||||||
|
" -F flush all multipath device maps\n"
|
||||||
|
" -a add a device wwid to the wwids file\n"
|
||||||
|
+ " -A add devices from kernel command line mpath.wwids\n"
|
||||||
|
+ " parameters to wwids file\n"
|
||||||
|
" -c check if a device should be a path in a multipath device\n"
|
||||||
|
" -C check if a multipath device has usable paths\n"
|
||||||
|
" -q allow queue_if_no_path when multipathd is not running\n"
|
||||||
|
@@ -896,7 +898,7 @@ main (int argc, char *argv[])
|
||||||
|
multipath_conf = conf;
|
||||||
|
conf->retrigger_tries = 0;
|
||||||
|
conf->force_sync = 1;
|
||||||
|
- while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
+ while ((arg = getopt(argc, argv, ":aAdDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
switch(arg) {
|
||||||
|
case 1: printf("optarg : %s\n",optarg);
|
||||||
|
break;
|
||||||
|
@@ -973,6 +975,10 @@ main (int argc, char *argv[])
|
||||||
|
case 'T':
|
||||||
|
cmd = CMD_DUMP_CONFIG;
|
||||||
|
break;
|
||||||
|
+ case 'A':
|
||||||
|
+ if (remember_cmdline_wwid() != 0)
|
||||||
|
+ exit(RTVL_FAIL);
|
||||||
|
+ exit(RTVL_OK);
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0]);
|
||||||
|
exit(RTVL_OK);
|
||||||
|
diff --git a/multipath/multipath.8 b/multipath/multipath.8
|
||||||
|
index 5b29a5d9..0478f4e7 100644
|
||||||
|
--- a/multipath/multipath.8
|
||||||
|
+++ b/multipath/multipath.8
|
||||||
|
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.
|
||||||
|
.B multipath
|
||||||
|
.RB [\| \-v\ \c
|
||||||
|
.IR level \|]
|
||||||
|
-.B -W
|
||||||
|
+.RB [\| \-A | \-W \|]
|
||||||
|
.
|
||||||
|
.LP
|
||||||
|
.B multipath
|
||||||
|
@@ -145,6 +145,11 @@ device mapper, path checkers ...).
|
||||||
|
Add the WWID for the specified device to the WWIDs file.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
+.B \-A
|
||||||
|
+Add the WWIDs from any kernel command line \fImpath.wwid\fR parameters to the
|
||||||
|
+WWIDs file.
|
||||||
|
+.
|
||||||
|
+.TP
|
||||||
|
.B \-w
|
||||||
|
Remove the WWID for the specified device from the WWIDs file.
|
||||||
|
.
|
||||||
|
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
|
||||||
|
index 17434cef..0fbcc46b 100644
|
||||||
|
--- a/multipathd/multipathd.service
|
||||||
|
+++ b/multipathd/multipathd.service
|
||||||
|
@@ -15,6 +15,7 @@ Type=notify
|
||||||
|
NotifyAccess=main
|
||||||
|
LimitCORE=infinity
|
||||||
|
ExecStartPre=-/sbin/modprobe -a scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm-multipath
|
||||||
|
+ExecStartPre=-/sbin/multipath -A
|
||||||
|
ExecStart=/sbin/multipathd -d -s
|
||||||
|
ExecReload=/sbin/multipathd reconfigure
|
||||||
|
TasksMax=infinity
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
121
0065-RH-warn-on-invalid-regex-instead-of-failing.patch
Normal file
121
0065-RH-warn-on-invalid-regex-instead-of-failing.patch
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Mon, 6 Nov 2017 21:39:28 -0600
|
||||||
|
Subject: [PATCH] RH: warn on invalid regex instead of failing
|
||||||
|
|
||||||
|
multipath.conf used to allow "*" as a match everything regular expression,
|
||||||
|
instead of requiring ".*". Instead of erroring when the old style
|
||||||
|
regular expressions are used, it should print a warning and convert
|
||||||
|
them.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dict.c | 27 +++++++++++++++++++++------
|
||||||
|
libmultipath/parser.c | 13 +++++++++++++
|
||||||
|
libmultipath/parser.h | 1 +
|
||||||
|
3 files changed, 35 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 0e9ea387..184d4b22 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -103,6 +103,21 @@ set_str(vector strvec, void *ptr)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+set_regex(vector strvec, void *ptr)
|
||||||
|
+{
|
||||||
|
+ char **str_ptr = (char **)ptr;
|
||||||
|
+
|
||||||
|
+ if (*str_ptr)
|
||||||
|
+ FREE(*str_ptr);
|
||||||
|
+ *str_ptr = set_regex_value(strvec);
|
||||||
|
+
|
||||||
|
+ if (!*str_ptr)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
set_yes_no(vector strvec, void *ptr)
|
||||||
|
{
|
||||||
|
@@ -1504,7 +1519,7 @@ ble_ ## option ## _handler (struct config *conf, vector strvec) \
|
||||||
|
if (!conf->option) \
|
||||||
|
return 1; \
|
||||||
|
\
|
||||||
|
- buff = set_value(strvec); \
|
||||||
|
+ buff = set_regex_value(strvec); \
|
||||||
|
if (!buff) \
|
||||||
|
return 1; \
|
||||||
|
\
|
||||||
|
@@ -1520,7 +1535,7 @@ ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
|
||||||
|
if (!conf->option) \
|
||||||
|
return 1; \
|
||||||
|
\
|
||||||
|
- buff = set_value(strvec); \
|
||||||
|
+ buff = set_regex_value(strvec); \
|
||||||
|
if (!buff) \
|
||||||
|
return 1; \
|
||||||
|
\
|
||||||
|
@@ -1623,16 +1638,16 @@ device_handler(struct config *conf, vector strvec)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-declare_hw_handler(vendor, set_str)
|
||||||
|
+declare_hw_handler(vendor, set_regex)
|
||||||
|
declare_hw_snprint(vendor, print_str)
|
||||||
|
|
||||||
|
-declare_hw_handler(product, set_str)
|
||||||
|
+declare_hw_handler(product, set_regex)
|
||||||
|
declare_hw_snprint(product, print_str)
|
||||||
|
|
||||||
|
-declare_hw_handler(revision, set_str)
|
||||||
|
+declare_hw_handler(revision, set_regex)
|
||||||
|
declare_hw_snprint(revision, print_str)
|
||||||
|
|
||||||
|
-declare_hw_handler(bl_product, set_str)
|
||||||
|
+declare_hw_handler(bl_product, set_regex)
|
||||||
|
declare_hw_snprint(bl_product, print_str)
|
||||||
|
|
||||||
|
declare_hw_handler(hwhandler, set_str)
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index 11a6168c..a7285a35 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -384,6 +384,19 @@ oom:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void *
|
||||||
|
+set_regex_value(vector strvec)
|
||||||
|
+{
|
||||||
|
+ char *buff = set_value(strvec);
|
||||||
|
+
|
||||||
|
+ if (buff && strcmp("*", buff) == 0) {
|
||||||
|
+ condlog(0, "Invalid regular expression \"*\" in multipath.conf. Using \".*\"");
|
||||||
|
+ FREE(buff);
|
||||||
|
+ return strdup(".*");
|
||||||
|
+ }
|
||||||
|
+ return buff;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* non-recursive configuration stream handler */
|
||||||
|
static int kw_level = 0;
|
||||||
|
|
||||||
|
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
|
||||||
|
index 62906e98..b7917052 100644
|
||||||
|
--- a/libmultipath/parser.h
|
||||||
|
+++ b/libmultipath/parser.h
|
||||||
|
@@ -77,6 +77,7 @@ extern void dump_keywords(vector keydump, int level);
|
||||||
|
extern void free_keywords(vector keywords);
|
||||||
|
extern vector alloc_strvec(char *string);
|
||||||
|
extern void *set_value(vector strvec);
|
||||||
|
+extern void *set_regex_value(vector strvec);
|
||||||
|
extern int process_file(struct config *conf, char *conf_file);
|
||||||
|
extern struct keyword * find_keyword(vector keywords, vector v, char * name);
|
||||||
|
int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
29
0066-RH-reset-default-find_mutipaths-value-to-off.patch
Normal file
29
0066-RH-reset-default-find_mutipaths-value-to-off.patch
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 7 Jun 2018 17:43:52 -0500
|
||||||
|
Subject: [PATCH] RH: reset default find_mutipaths value to off
|
||||||
|
|
||||||
|
Upstream has changed to default find_multipaths to "strict". For now
|
||||||
|
Redhat will retain the previous default of "off".
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/defaults.h | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
|
||||||
|
index 01a501bd..984d8dd8 100644
|
||||||
|
--- a/libmultipath/defaults.h
|
||||||
|
+++ b/libmultipath/defaults.h
|
||||||
|
@@ -22,7 +22,7 @@
|
||||||
|
#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
|
||||||
|
#define DEFAULT_VERBOSITY 2
|
||||||
|
#define DEFAULT_REASSIGN_MAPS 0
|
||||||
|
-#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_STRICT
|
||||||
|
+#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_OFF
|
||||||
|
#define DEFAULT_FAST_IO_FAIL 5
|
||||||
|
#define DEFAULT_DEV_LOSS_TMO 600
|
||||||
|
#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
26
0067-RH-Fix-nvme-compilation-warning.patch
Normal file
26
0067-RH-Fix-nvme-compilation-warning.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 25 Jan 2019 14:54:56 -0600
|
||||||
|
Subject: [PATCH] RH: Fix nvme compilation warning
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/nvme/argconfig.h | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/nvme/argconfig.h b/libmultipath/nvme/argconfig.h
|
||||||
|
index adb192b6..bfd10ef8 100644
|
||||||
|
--- a/libmultipath/nvme/argconfig.h
|
||||||
|
+++ b/libmultipath/nvme/argconfig.h
|
||||||
|
@@ -76,7 +76,7 @@ struct argconfig_commandline_options {
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-typedef void argconfig_help_func();
|
||||||
|
+typedef void argconfig_help_func(void);
|
||||||
|
void argconfig_append_usage(const char *str);
|
||||||
|
void argconfig_print_help(const char *program_desc,
|
||||||
|
const struct argconfig_commandline_options *options);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
87
0068-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Normal file
87
0068-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Thu, 11 Apr 2019 13:25:42 -0500
|
||||||
|
Subject: [PATCH] RH: attempt to get ANA info via sysfs first
|
||||||
|
|
||||||
|
When the ANA prioritizer is run, first see if the "ana_state" sysfs file
|
||||||
|
exists, and if it does, try to read the state from there. If that fails,
|
||||||
|
fallback to using an ioctl.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/prioritizers/ana.c | 31 +++++++++++++++++++++++++++++--
|
||||||
|
1 file changed, 29 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c
|
||||||
|
index b5c7873d..e139360c 100644
|
||||||
|
--- a/libmultipath/prioritizers/ana.c
|
||||||
|
+++ b/libmultipath/prioritizers/ana.c
|
||||||
|
@@ -24,6 +24,7 @@
|
||||||
|
#include "prio.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "structs.h"
|
||||||
|
+#include "sysfs.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ANA_ERR_GETCTRL_FAILED = 1,
|
||||||
|
@@ -36,6 +37,7 @@ enum {
|
||||||
|
ANA_ERR_GETNS_FAILED,
|
||||||
|
ANA_ERR_NO_MEMORY,
|
||||||
|
ANA_ERR_NO_INFORMATION,
|
||||||
|
+ ANA_ERR_INVALID_STATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *ana_errmsg[] = {
|
||||||
|
@@ -49,6 +51,7 @@ static const char *ana_errmsg[] = {
|
||||||
|
[ANA_ERR_GETNS_FAILED] = "couldn't get namespace info",
|
||||||
|
[ANA_ERR_NO_MEMORY] = "out of memory",
|
||||||
|
[ANA_ERR_NO_INFORMATION] = "invalid fd",
|
||||||
|
+ [ANA_ERR_INVALID_STATE] = "invalid state",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *anas_string[] = {
|
||||||
|
@@ -107,6 +110,27 @@ static int get_ana_state(__u32 nsid, __u32 anagrpid, void *ana_log,
|
||||||
|
return -ANA_ERR_GETANAS_NOTFOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int get_ana_info_sysfs(struct path *pp)
|
||||||
|
+{
|
||||||
|
+ char state[32];
|
||||||
|
+
|
||||||
|
+ if (!pp->udev || sysfs_attr_get_value(pp->udev, "ana_state", state,
|
||||||
|
+ sizeof(state)) <= 0)
|
||||||
|
+ return -ANA_ERR_NO_INFORMATION;
|
||||||
|
+
|
||||||
|
+ if (strcmp(state, "optimized") == 0)
|
||||||
|
+ return NVME_ANA_OPTIMIZED;
|
||||||
|
+ if (strcmp(state, "non-optimized") == 0)
|
||||||
|
+ return NVME_ANA_NONOPTIMIZED;
|
||||||
|
+ if (strcmp(state, "inaccessible") == 0)
|
||||||
|
+ return NVME_ANA_INACCESSIBLE;
|
||||||
|
+ if (strcmp(state, "persistent-loss") == 0)
|
||||||
|
+ return NVME_ANA_PERSISTENT_LOSS;
|
||||||
|
+ if (strcmp(state, "change") == 0)
|
||||||
|
+ return NVME_ANA_CHANGE;
|
||||||
|
+ return -ANA_ERR_INVALID_STATE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int get_ana_info(struct path * pp)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
@@ -210,8 +234,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args,
|
||||||
|
|
||||||
|
if (pp->fd < 0)
|
||||||
|
rc = -ANA_ERR_NO_INFORMATION;
|
||||||
|
- else
|
||||||
|
- rc = get_ana_info(pp);
|
||||||
|
+ else {
|
||||||
|
+ rc = get_ana_info_sysfs(pp);
|
||||||
|
+ if (rc < 0)
|
||||||
|
+ rc = get_ana_info(pp);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
switch (rc) {
|
||||||
|
case NVME_ANA_OPTIMIZED:
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
31
0069-RH-work-around-gcc-10-format-truncation-issue.patch
Normal file
31
0069-RH-work-around-gcc-10-format-truncation-issue.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Fri, 29 May 2020 17:21:21 -0500
|
||||||
|
Subject: [PATCH] RH: work around gcc 10 format-truncation issue
|
||||||
|
|
||||||
|
gcc 10 was returning false positives on some architectures, when trying
|
||||||
|
to determine if a snprintf() function could silently truncate its
|
||||||
|
output. Instead of changing the code to pretend that this is possible,
|
||||||
|
make these warnings, instead of errors.
|
||||||
|
|
||||||
|
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 479523bc..e2f5d0dc 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -109,7 +109,7 @@ endif
|
||||||
|
WARNFLAGS := -Werror -Wextra -Wformat=2 -Werror=implicit-int \
|
||||||
|
-Werror=implicit-function-declaration -Werror=format-security \
|
||||||
|
$(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
|
||||||
|
- -Wstrict-prototypes
|
||||||
|
+ -Wstrict-prototypes -Wno-error=format-truncation
|
||||||
|
CFLAGS := $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
|
||||||
|
-DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
|
||||||
|
-MMD -MP
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
369
0070-multipath-add-libmpathvalid-library.patch
Normal file
369
0070-multipath-add-libmpathvalid-library.patch
Normal file
@ -0,0 +1,369 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 13 May 2020 17:04:24 -0500
|
||||||
|
Subject: [PATCH] multipath: add libmpathvalid library
|
||||||
|
|
||||||
|
This library allows other programs to check if a path should be claimed
|
||||||
|
by multipath. It exports an init and exit function, that need to be
|
||||||
|
called before any other functions can be called, a pointer to a struct
|
||||||
|
config, that stores the configuration which is dealt with in the
|
||||||
|
init and exit functions, and two more functions.
|
||||||
|
|
||||||
|
mpath_get_mode() get the configured find_multipaths mode.
|
||||||
|
mpath_is_path() returns whether the device is claimed by multipath, and
|
||||||
|
optionally returns the wwid. This code works slightly different than
|
||||||
|
the multipath -c/u code for SMART mode. Instead of checking all the
|
||||||
|
existing paths to see if another has the same wwid, it expects the
|
||||||
|
caller to pass in an array of the already known path wwids, and checks
|
||||||
|
if the current path matches any of those.
|
||||||
|
|
||||||
|
The library also doesn't set up the device-mapper log fuctions. It
|
||||||
|
leaves this up to the caller.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile | 3 +-
|
||||||
|
Makefile.inc | 1 +
|
||||||
|
libmpathvalid/Makefile | 38 +++++++
|
||||||
|
libmpathvalid/libmpathvalid.version | 10 ++
|
||||||
|
libmpathvalid/mpath_valid.c | 168 ++++++++++++++++++++++++++++
|
||||||
|
libmpathvalid/mpath_valid.h | 57 ++++++++++
|
||||||
|
6 files changed, 276 insertions(+), 1 deletion(-)
|
||||||
|
create mode 100644 libmpathvalid/Makefile
|
||||||
|
create mode 100644 libmpathvalid/libmpathvalid.version
|
||||||
|
create mode 100644 libmpathvalid/mpath_valid.c
|
||||||
|
create mode 100644 libmpathvalid/mpath_valid.h
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 8bcaba66..f157a549 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -9,6 +9,7 @@ BUILDDIRS := \
|
||||||
|
libmultipath/checkers \
|
||||||
|
libmultipath/foreign \
|
||||||
|
libmpathpersist \
|
||||||
|
+ libmpathvalid \
|
||||||
|
multipath \
|
||||||
|
multipathd \
|
||||||
|
mpathpersist \
|
||||||
|
@@ -29,7 +30,7 @@ $(BUILDDIRS):
|
||||||
|
$(MAKE) -C $@
|
||||||
|
|
||||||
|
libmultipath libdmmp: libmpathcmd
|
||||||
|
-libmpathpersist multipath multipathd: libmultipath
|
||||||
|
+libmpathpersist libmpathvalid multipath multipathd: libmultipath
|
||||||
|
mpathpersist multipathd: libmpathpersist
|
||||||
|
|
||||||
|
libmultipath/checkers.install \
|
||||||
|
diff --git a/Makefile.inc b/Makefile.inc
|
||||||
|
index e2f5d0dc..936e5833 100644
|
||||||
|
--- a/Makefile.inc
|
||||||
|
+++ b/Makefile.inc
|
||||||
|
@@ -66,6 +66,7 @@ libdir = $(prefix)/$(LIB)/multipath
|
||||||
|
unitdir = $(prefix)/$(SYSTEMDPATH)/systemd/system
|
||||||
|
mpathpersistdir = $(TOPDIR)/libmpathpersist
|
||||||
|
mpathcmddir = $(TOPDIR)/libmpathcmd
|
||||||
|
+mpathvaliddir = $(TOPDIR)/libmpathvalid
|
||||||
|
thirdpartydir = $(TOPDIR)/third-party
|
||||||
|
libdmmpdir = $(TOPDIR)/libdmmp
|
||||||
|
nvmedir = $(TOPDIR)/libmultipath/nvme
|
||||||
|
diff --git a/libmpathvalid/Makefile b/libmpathvalid/Makefile
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..70b97eca
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libmpathvalid/Makefile
|
||||||
|
@@ -0,0 +1,38 @@
|
||||||
|
+include ../Makefile.inc
|
||||||
|
+
|
||||||
|
+SONAME = 0
|
||||||
|
+DEVLIB = libmpathvalid.so
|
||||||
|
+LIBS = $(DEVLIB).$(SONAME)
|
||||||
|
+
|
||||||
|
+CFLAGS += $(LIB_CFLAGS) -I$(multipathdir) -I$(mpathcmddir)
|
||||||
|
+
|
||||||
|
+LIBDEPS += -lpthread -ldevmapper -ldl -L$(multipathdir) \
|
||||||
|
+ -lmultipath -L$(mpathcmddir) -lmpathcmd -ludev
|
||||||
|
+
|
||||||
|
+OBJS = mpath_valid.o
|
||||||
|
+
|
||||||
|
+all: $(LIBS)
|
||||||
|
+
|
||||||
|
+$(LIBS): $(OBJS)
|
||||||
|
+ $(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ -o $@ $(OBJS) $(LIBDEPS) -Wl,--version-script=libmpathvalid.version
|
||||||
|
+ $(LN) $(LIBS) $(DEVLIB)
|
||||||
|
+
|
||||||
|
+install: $(LIBS)
|
||||||
|
+ $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(syslibdir)
|
||||||
|
+ $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS)
|
||||||
|
+ $(LN) $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB)
|
||||||
|
+ $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(includedir)
|
||||||
|
+ $(INSTALL_PROGRAM) -m 644 mpath_valid.h $(DESTDIR)$(includedir)
|
||||||
|
+
|
||||||
|
+uninstall:
|
||||||
|
+ $(RM) $(DESTDIR)$(syslibdir)/$(LIBS)
|
||||||
|
+ $(RM) $(DESTDIR)$(syslibdir)/$(DEVLIB)
|
||||||
|
+ $(RM) $(DESTDIR)$(includedir)/mpath_valid.h
|
||||||
|
+
|
||||||
|
+clean: dep_clean
|
||||||
|
+ $(RM) core *.a *.o *.so *.so.* *.gz
|
||||||
|
+
|
||||||
|
+include $(wildcard $(OBJS:.o=.d))
|
||||||
|
+
|
||||||
|
+dep_clean:
|
||||||
|
+ $(RM) $(OBJS:.o=.d)
|
||||||
|
diff --git a/libmpathvalid/libmpathvalid.version b/libmpathvalid/libmpathvalid.version
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..4d8a8ba4
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libmpathvalid/libmpathvalid.version
|
||||||
|
@@ -0,0 +1,10 @@
|
||||||
|
+MPATH_1.0 {
|
||||||
|
+ global:
|
||||||
|
+ mpathvalid_conf;
|
||||||
|
+ mpathvalid_init;
|
||||||
|
+ mpathvalid_exit;
|
||||||
|
+ mpathvalid_is_path;
|
||||||
|
+ mpathvalid_get_mode;
|
||||||
|
+ local:
|
||||||
|
+ *;
|
||||||
|
+};
|
||||||
|
diff --git a/libmpathvalid/mpath_valid.c b/libmpathvalid/mpath_valid.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..6153e8b7
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libmpathvalid/mpath_valid.c
|
||||||
|
@@ -0,0 +1,168 @@
|
||||||
|
+#include <stdlib.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdint.h>
|
||||||
|
+#include <libdevmapper.h>
|
||||||
|
+#include <libudev.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+
|
||||||
|
+#include "devmapper.h"
|
||||||
|
+#include "structs.h"
|
||||||
|
+#include "util.h"
|
||||||
|
+#include "config.h"
|
||||||
|
+#include "discovery.h"
|
||||||
|
+#include "wwids.h"
|
||||||
|
+#include "sysfs.h"
|
||||||
|
+#include "mpath_cmd.h"
|
||||||
|
+#include "valid.h"
|
||||||
|
+#include "mpath_valid.h"
|
||||||
|
+
|
||||||
|
+static struct config default_config = { .verbosity = -1 };
|
||||||
|
+struct config *mpathvalid_conf = &default_config;
|
||||||
|
+
|
||||||
|
+static unsigned int get_conf_mode(struct config *conf)
|
||||||
|
+{
|
||||||
|
+ if (conf->find_multipaths == FIND_MULTIPATHS_SMART)
|
||||||
|
+ return MPATH_SMART;
|
||||||
|
+ if (conf->find_multipaths == FIND_MULTIPATHS_GREEDY)
|
||||||
|
+ return MPATH_GREEDY;
|
||||||
|
+ return MPATH_STRICT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void set_conf_mode(struct config *conf, unsigned int mode)
|
||||||
|
+{
|
||||||
|
+ if (mode == MPATH_SMART)
|
||||||
|
+ conf->find_multipaths = FIND_MULTIPATHS_SMART;
|
||||||
|
+ else if (mode == MPATH_GREEDY)
|
||||||
|
+ conf->find_multipaths = FIND_MULTIPATHS_GREEDY;
|
||||||
|
+ else
|
||||||
|
+ conf->find_multipaths = FIND_MULTIPATHS_STRICT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+unsigned int mpathvalid_get_mode(void)
|
||||||
|
+{
|
||||||
|
+ int mode;
|
||||||
|
+ struct config *conf;
|
||||||
|
+
|
||||||
|
+ conf = get_multipath_config();
|
||||||
|
+ if (!conf)
|
||||||
|
+ return -1;
|
||||||
|
+ mode = get_conf_mode(conf);
|
||||||
|
+ put_multipath_config(conf);
|
||||||
|
+ return mode;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int convert_result(int result) {
|
||||||
|
+ switch (result) {
|
||||||
|
+ case PATH_IS_ERROR:
|
||||||
|
+ return MPATH_IS_ERROR;
|
||||||
|
+ case PATH_IS_NOT_VALID:
|
||||||
|
+ return MPATH_IS_NOT_VALID;
|
||||||
|
+ case PATH_IS_VALID:
|
||||||
|
+ return MPATH_IS_VALID;
|
||||||
|
+ case PATH_IS_VALID_NO_CHECK:
|
||||||
|
+ return MPATH_IS_VALID_NO_CHECK;
|
||||||
|
+ case PATH_IS_MAYBE_VALID:
|
||||||
|
+ return MPATH_IS_MAYBE_VALID;
|
||||||
|
+ }
|
||||||
|
+ return MPATH_IS_ERROR;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+mpathvalid_init(int verbosity)
|
||||||
|
+{
|
||||||
|
+ unsigned int version[3];
|
||||||
|
+ struct config *conf;
|
||||||
|
+
|
||||||
|
+ default_config.verbosity = verbosity;
|
||||||
|
+ skip_libmp_dm_init();
|
||||||
|
+ conf = load_config(DEFAULT_CONFIGFILE);
|
||||||
|
+ if (!conf)
|
||||||
|
+ return -1;
|
||||||
|
+ conf->verbosity = verbosity;
|
||||||
|
+ if (dm_prereq(version))
|
||||||
|
+ goto fail;
|
||||||
|
+ memcpy(conf->version, version, sizeof(version));
|
||||||
|
+
|
||||||
|
+ mpathvalid_conf = conf;
|
||||||
|
+ return 0;
|
||||||
|
+fail:
|
||||||
|
+ free_config(conf);
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+mpathvalid_exit(void)
|
||||||
|
+{
|
||||||
|
+ struct config *conf = mpathvalid_conf;
|
||||||
|
+
|
||||||
|
+ default_config.verbosity = -1;
|
||||||
|
+ if (mpathvalid_conf == &default_config)
|
||||||
|
+ return 0;
|
||||||
|
+ mpathvalid_conf = &default_config;
|
||||||
|
+ free_config(conf);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * name: name of path to check
|
||||||
|
+ * mode: mode to use for determination. MPATH_DEFAULT uses configured mode
|
||||||
|
+ * info: on success, contains the path wwid
|
||||||
|
+ * paths: array of the returned mpath_info from other claimed paths
|
||||||
|
+ * nr_paths: the size of the paths array
|
||||||
|
+ */
|
||||||
|
+int
|
||||||
|
+mpathvalid_is_path(const char *name, unsigned int mode, char **wwid,
|
||||||
|
+ const char **path_wwids, unsigned int nr_paths)
|
||||||
|
+{
|
||||||
|
+ struct config *conf;
|
||||||
|
+ int r = MPATH_IS_ERROR;
|
||||||
|
+ unsigned int i;
|
||||||
|
+ struct path *pp;
|
||||||
|
+
|
||||||
|
+ if (!name || mode >= MPATH_MAX_MODE)
|
||||||
|
+ return r;
|
||||||
|
+
|
||||||
|
+ if (nr_paths > 0 && !path_wwids)
|
||||||
|
+ return r;
|
||||||
|
+
|
||||||
|
+ pp = alloc_path();
|
||||||
|
+ if (!pp)
|
||||||
|
+ return r;
|
||||||
|
+
|
||||||
|
+ if (wwid) {
|
||||||
|
+ *wwid = (char *)malloc(WWID_SIZE);
|
||||||
|
+ if (!*wwid)
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ conf = get_multipath_config();
|
||||||
|
+ if (!conf || conf == &default_config)
|
||||||
|
+ goto out_wwid;
|
||||||
|
+ if (mode != MPATH_DEFAULT)
|
||||||
|
+ set_conf_mode(conf, mode);
|
||||||
|
+ r = convert_result(is_path_valid(name, conf, pp, true));
|
||||||
|
+ put_multipath_config(conf);
|
||||||
|
+
|
||||||
|
+ if (r == MPATH_IS_MAYBE_VALID) {
|
||||||
|
+ for (i = 0; i < nr_paths; i++) {
|
||||||
|
+ if (strncmp(path_wwids[i], pp->wwid, WWID_SIZE) == 0) {
|
||||||
|
+ r = MPATH_IS_VALID;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out_wwid:
|
||||||
|
+ if (wwid) {
|
||||||
|
+ if (r == MPATH_IS_VALID || r == MPATH_IS_VALID_NO_CHECK ||
|
||||||
|
+ r == MPATH_IS_MAYBE_VALID)
|
||||||
|
+ strlcpy(*wwid, pp->wwid, WWID_SIZE);
|
||||||
|
+ else {
|
||||||
|
+ free(*wwid);
|
||||||
|
+ *wwid = NULL;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+out:
|
||||||
|
+ free_path(pp);
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
diff --git a/libmpathvalid/mpath_valid.h b/libmpathvalid/mpath_valid.h
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..7fd8aa47
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/libmpathvalid/mpath_valid.h
|
||||||
|
@@ -0,0 +1,57 @@
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2015 Red Hat, Inc.
|
||||||
|
+ *
|
||||||
|
+ * This file is part of the device-mapper multipath userspace tools.
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or
|
||||||
|
+ * modify it under the terms of the GNU Lesser General Public License
|
||||||
|
+ * as published by the Free Software Foundation; either version 2
|
||||||
|
+ * of the License, or (at your option) any later version.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU Lesser General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU Lesser General Public License
|
||||||
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef LIB_MPATH_VALID_H
|
||||||
|
+#define LIB_MPATH_VALID_H
|
||||||
|
+
|
||||||
|
+#ifdef __cpluscplus
|
||||||
|
+extern "C" {
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+enum mpath_valid_mode {
|
||||||
|
+ MPATH_DEFAULT,
|
||||||
|
+ MPATH_STRICT,
|
||||||
|
+ MPATH_SMART,
|
||||||
|
+ MPATH_GREEDY,
|
||||||
|
+ MPATH_MAX_MODE, /* used only for bounds checking */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* MPATH_IS_VALID_NO_CHECK is used to skip checks to see if the device
|
||||||
|
+ * has already been unclaimed by multipath in the past */
|
||||||
|
+enum mpath_valid_result {
|
||||||
|
+ MPATH_IS_ERROR = -1,
|
||||||
|
+ MPATH_IS_NOT_VALID,
|
||||||
|
+ MPATH_IS_VALID,
|
||||||
|
+ MPATH_IS_VALID_NO_CHECK,
|
||||||
|
+ MPATH_IS_MAYBE_VALID,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct config;
|
||||||
|
+extern struct config *mpathvalid_conf;
|
||||||
|
+int mpathvalid_init(int verbosity);
|
||||||
|
+int mpathvalid_exit(void);
|
||||||
|
+unsigned int mpathvalid_get_mode(void);
|
||||||
|
+int mpathvalid_is_path(const char *name, unsigned int mode, char **wwid,
|
||||||
|
+ const char **path_wwids, unsigned int nr_paths);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#ifdef __cplusplus
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+#endif /* LIB_PATH_VALID_H */
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
89
0071-libmultipath-add-uid-failback-for-dasd-devices.patch
Normal file
89
0071-libmultipath-add-uid-failback-for-dasd-devices.patch
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 19 May 2020 15:55:15 -0500
|
||||||
|
Subject: [PATCH] libmultipath: add uid failback for dasd devices
|
||||||
|
|
||||||
|
Add failback code to get the uid for dasd devices from sysfs. Copied
|
||||||
|
from dasdinfo
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/defaults.h | 1 +
|
||||||
|
libmultipath/discovery.c | 37 ++++++++++++++++++++++++++++++++++++-
|
||||||
|
2 files changed, 37 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
|
||||||
|
index 984d8dd8..6a678a83 100644
|
||||||
|
--- a/libmultipath/defaults.h
|
||||||
|
+++ b/libmultipath/defaults.h
|
||||||
|
@@ -8,6 +8,7 @@
|
||||||
|
*/
|
||||||
|
#define DEFAULT_UID_ATTRIBUTE "ID_SERIAL"
|
||||||
|
#define DEFAULT_NVME_UID_ATTRIBUTE "ID_WWN"
|
||||||
|
+#define DEFAULT_DASD_UID_ATTRIBUTE "ID_UID"
|
||||||
|
#define DEFAULT_UDEVDIR "/dev"
|
||||||
|
#define DEFAULT_MULTIPATHDIR "/" LIB_STRING "/multipath"
|
||||||
|
#define DEFAULT_SELECTOR "service-time 0"
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index aa5942c3..002d3d18 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -1920,12 +1920,44 @@ get_vpd_uid(struct path * pp)
|
||||||
|
return get_vpd_sysfs(parent, 0x83, pp->wwid, WWID_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* based on code from s390-tools/dasdinfo/dasdinfo.c */
|
||||||
|
+static ssize_t dasd_get_uid(struct path *pp)
|
||||||
|
+{
|
||||||
|
+ struct udev_device *parent;
|
||||||
|
+ char value[80];
|
||||||
|
+ char *p;
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ parent = udev_device_get_parent_with_subsystem_devtype(pp->udev, "ccw",
|
||||||
|
+ NULL);
|
||||||
|
+ if (!parent)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (sysfs_attr_get_value(parent, "uid", value, 80) < 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ p = value - 1;
|
||||||
|
+ /* look for the 4th '.' and cut there */
|
||||||
|
+ for (i = 0; i < 4; i++) {
|
||||||
|
+ p = index(p + 1, '.');
|
||||||
|
+ if (!p)
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (p)
|
||||||
|
+ *p = '\0';
|
||||||
|
+
|
||||||
|
+ return strlcpy(pp->wwid, value, WWID_SIZE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static ssize_t uid_fallback(struct path *pp, int path_state,
|
||||||
|
const char **origin)
|
||||||
|
{
|
||||||
|
ssize_t len = -1;
|
||||||
|
|
||||||
|
- if (pp->bus == SYSFS_BUS_SCSI) {
|
||||||
|
+ if (pp->bus == SYSFS_BUS_CCW) {
|
||||||
|
+ len = dasd_get_uid(pp);
|
||||||
|
+ *origin = "sysfs";
|
||||||
|
+ } else if (pp->bus == SYSFS_BUS_SCSI) {
|
||||||
|
len = get_vpd_uid(pp);
|
||||||
|
*origin = "sysfs";
|
||||||
|
if (len < 0 && path_state == PATH_UP) {
|
||||||
|
@@ -1970,6 +2002,9 @@ static bool has_uid_fallback(struct path *pp)
|
||||||
|
!strcmp(pp->uid_attribute, ""))) ||
|
||||||
|
(pp->bus == SYSFS_BUS_NVME &&
|
||||||
|
(!strcmp(pp->uid_attribute, DEFAULT_NVME_UID_ATTRIBUTE) ||
|
||||||
|
+ !strcmp(pp->uid_attribute, ""))) ||
|
||||||
|
+ (pp->bus == SYSFS_BUS_CCW &&
|
||||||
|
+ (!strcmp(pp->uid_attribute, DEFAULT_DASD_UID_ATTRIBUTE) ||
|
||||||
|
!strcmp(pp->uid_attribute, ""))));
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
192
0072-libmultipath-add-ignore_udev_uid-option.patch
Normal file
192
0072-libmultipath-add-ignore_udev_uid-option.patch
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Wed, 20 May 2020 16:46:55 -0500
|
||||||
|
Subject: [PATCH] libmultipath: add ignore_udev_uid option
|
||||||
|
|
||||||
|
Setting this option to yes will force multipath to get the uid by using
|
||||||
|
the fallback sysfs methods, instead of getting it from udev. This will
|
||||||
|
cause devices that can't get their uid from the standard locations to
|
||||||
|
not get a uid. It will also disable uevent merging.
|
||||||
|
|
||||||
|
It will not stop uevents from being resent for device that failed to
|
||||||
|
get a WWID, although I'm on the fence about the benefit of this.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.h | 1 +
|
||||||
|
libmultipath/dict.c | 4 ++++
|
||||||
|
libmultipath/discovery.c | 17 +++++++++++------
|
||||||
|
libmultipath/discovery.h | 8 +++++++-
|
||||||
|
libmultipath/uevent.c | 2 +-
|
||||||
|
multipath/multipath.conf.5 | 13 +++++++++++++
|
||||||
|
multipathd/main.c | 7 ++++++-
|
||||||
|
7 files changed, 43 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index 160867cd..c7a73fba 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -192,6 +192,7 @@ struct config {
|
||||||
|
int find_multipaths_timeout;
|
||||||
|
int marginal_pathgroups;
|
||||||
|
int skip_delegate;
|
||||||
|
+ int ignore_udev_uid;
|
||||||
|
unsigned int version[3];
|
||||||
|
unsigned int sequence_nr;
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 184d4b22..9a0729bf 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -1406,6 +1406,9 @@ declare_hw_snprint(all_tg_pt, print_yes_no_undef)
|
||||||
|
declare_def_handler(marginal_pathgroups, set_yes_no)
|
||||||
|
declare_def_snprint(marginal_pathgroups, print_yes_no)
|
||||||
|
|
||||||
|
+declare_def_handler(ignore_udev_uid, set_yes_no)
|
||||||
|
+declare_def_snprint(ignore_udev_uid, print_yes_no)
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
def_uxsock_timeout_handler(struct config *conf, vector strvec)
|
||||||
|
{
|
||||||
|
@@ -1816,6 +1819,7 @@ init_keywords(vector keywords)
|
||||||
|
install_keyword("enable_foreign", &def_enable_foreign_handler,
|
||||||
|
&snprint_def_enable_foreign);
|
||||||
|
install_keyword("marginal_pathgroups", &def_marginal_pathgroups_handler, &snprint_def_marginal_pathgroups);
|
||||||
|
+ install_keyword("ignore_udev_uid", &def_ignore_udev_uid_handler, &snprint_def_ignore_udev_uid);
|
||||||
|
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
|
||||||
|
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
|
||||||
|
__deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index 002d3d18..f0e92227 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -2010,7 +2010,7 @@ static bool has_uid_fallback(struct path *pp)
|
||||||
|
|
||||||
|
int
|
||||||
|
get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
- int allow_fallback)
|
||||||
|
+ int fallback)
|
||||||
|
{
|
||||||
|
char *c;
|
||||||
|
const char *origin = "unknown";
|
||||||
|
@@ -2043,7 +2043,9 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
} else
|
||||||
|
len = strlen(pp->wwid);
|
||||||
|
origin = "callout";
|
||||||
|
- } else {
|
||||||
|
+ } else if (fallback == UID_FALLBACK_FORCE)
|
||||||
|
+ len = uid_fallback(pp, path_state, &origin);
|
||||||
|
+ else {
|
||||||
|
bool udev_available = udev && pp->uid_attribute
|
||||||
|
&& *pp->uid_attribute;
|
||||||
|
|
||||||
|
@@ -2056,8 +2058,9 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
else
|
||||||
|
origin = "udev";
|
||||||
|
}
|
||||||
|
- if ((!udev_available || (len <= 0 && allow_fallback))
|
||||||
|
- && has_uid_fallback(pp)) {
|
||||||
|
+ if ((!udev_available ||
|
||||||
|
+ (len <= 0 && fallback == UID_FALLBACK_ALLOW)) &&
|
||||||
|
+ has_uid_fallback(pp)) {
|
||||||
|
used_fallback = 1;
|
||||||
|
len = uid_fallback(pp, path_state, &origin);
|
||||||
|
}
|
||||||
|
@@ -2197,8 +2200,10 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & DI_WWID) && !strlen(pp->wwid)) {
|
||||||
|
- get_uid(pp, path_state, pp->udev,
|
||||||
|
- (pp->retriggers >= conf->retrigger_tries));
|
||||||
|
+ int fallback = conf->ignore_udev_uid? UID_FALLBACK_FORCE :
|
||||||
|
+ (pp->retriggers >= conf->retrigger_tries)?
|
||||||
|
+ UID_FALLBACK_ALLOW : UID_FALLBACK_NONE;
|
||||||
|
+ get_uid(pp, path_state, pp->udev, fallback);
|
||||||
|
if (!strlen(pp->wwid)) {
|
||||||
|
if (pp->bus == SYSFS_BUS_UNDEF)
|
||||||
|
return PATHINFO_SKIPPED;
|
||||||
|
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
|
||||||
|
index 6444887d..ca8542d6 100644
|
||||||
|
--- a/libmultipath/discovery.h
|
||||||
|
+++ b/libmultipath/discovery.h
|
||||||
|
@@ -54,8 +54,14 @@ ssize_t sysfs_get_inquiry(struct udev_device *udev,
|
||||||
|
unsigned char *buff, size_t len);
|
||||||
|
int sysfs_get_asymmetric_access_state(struct path *pp,
|
||||||
|
char *buff, int buflen);
|
||||||
|
+
|
||||||
|
+enum {
|
||||||
|
+ UID_FALLBACK_NONE,
|
||||||
|
+ UID_FALLBACK_ALLOW,
|
||||||
|
+ UID_FALLBACK_FORCE,
|
||||||
|
+};
|
||||||
|
int get_uid(struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
- int allow_fallback);
|
||||||
|
+ int fallback);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* discovery bitmask
|
||||||
|
diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c
|
||||||
|
index e0d13b11..d67129d1 100644
|
||||||
|
--- a/libmultipath/uevent.c
|
||||||
|
+++ b/libmultipath/uevent.c
|
||||||
|
@@ -179,7 +179,7 @@ uevent_need_merge(void)
|
||||||
|
bool need_merge = false;
|
||||||
|
|
||||||
|
conf = get_multipath_config();
|
||||||
|
- if (VECTOR_SIZE(&conf->uid_attrs) > 0)
|
||||||
|
+ if (!conf->ignore_udev_uid && VECTOR_SIZE(&conf->uid_attrs) > 0)
|
||||||
|
need_merge = true;
|
||||||
|
put_multipath_config(conf);
|
||||||
|
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 42a192f6..175ca095 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -286,6 +286,19 @@ The default is: \fB<unset>\fR
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
+.B ignore_udev_uid
|
||||||
|
+Setting this option to yes will force multipath to ignore the the uid_attrs
|
||||||
|
+and uid_attribute settings, and generate the WWID by the \fIsysfs\fR
|
||||||
|
+method. This will cause devices that cannot get their WWID from the standard
|
||||||
|
+locations for their device type to not get a WWID; see \fBWWID generation\fR
|
||||||
|
+below.
|
||||||
|
+.RS
|
||||||
|
+.TP
|
||||||
|
+The default is: \fBno\fR
|
||||||
|
+.RE
|
||||||
|
+.
|
||||||
|
+.
|
||||||
|
+.TP
|
||||||
|
.B prio
|
||||||
|
The name of the path priority routine. The specified routine
|
||||||
|
should return a numeric value specifying the relative priority
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index f014d2a1..48b62937 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -1226,6 +1226,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
|
||||||
|
if (pp) {
|
||||||
|
struct multipath *mpp = pp->mpp;
|
||||||
|
char wwid[WWID_SIZE];
|
||||||
|
+ int fallback;
|
||||||
|
|
||||||
|
if (pp->initialized == INIT_REQUESTED_UDEV) {
|
||||||
|
needs_reinit = 1;
|
||||||
|
@@ -1237,7 +1238,11 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
strcpy(wwid, pp->wwid);
|
||||||
|
- rc = get_uid(pp, pp->state, uev->udev, 0);
|
||||||
|
+ conf = get_multipath_config();
|
||||||
|
+ fallback = conf->ignore_udev_uid? UID_FALLBACK_FORCE:
|
||||||
|
+ UID_FALLBACK_NONE;
|
||||||
|
+ put_multipath_config(conf);
|
||||||
|
+ rc = get_uid(pp, pp->state, uev->udev, fallback);
|
||||||
|
|
||||||
|
if (rc != 0)
|
||||||
|
strcpy(pp->wwid, wwid);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
111
0073-libmultipath-util-constify-function-arguments.patch
Normal file
111
0073-libmultipath-util-constify-function-arguments.patch
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Wed, 8 Jul 2020 09:23:20 +0200
|
||||||
|
Subject: [PATCH] libmultipath: util: constify function arguments
|
||||||
|
|
||||||
|
Use "const" for function arguments where possible.
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/dmparser.c | 2 +-
|
||||||
|
libmultipath/util.c | 12 ++++++------
|
||||||
|
libmultipath/util.h | 10 +++++-----
|
||||||
|
3 files changed, 12 insertions(+), 12 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c
|
||||||
|
index b856a07f..27581cde 100644
|
||||||
|
--- a/libmultipath/dmparser.c
|
||||||
|
+++ b/libmultipath/dmparser.c
|
||||||
|
@@ -18,7 +18,7 @@
|
||||||
|
#define WORD_SIZE 64
|
||||||
|
|
||||||
|
static int
|
||||||
|
-merge_words(char **dst, char *word)
|
||||||
|
+merge_words(char **dst, const char *word)
|
||||||
|
{
|
||||||
|
char * p = *dst;
|
||||||
|
int len, dstlen;
|
||||||
|
diff --git a/libmultipath/util.c b/libmultipath/util.c
|
||||||
|
index 51c38c87..67e7a42f 100644
|
||||||
|
--- a/libmultipath/util.c
|
||||||
|
+++ b/libmultipath/util.c
|
||||||
|
@@ -52,7 +52,7 @@ basenamecpy (const char *src, char *dst, size_t size)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-filepresent (char * run) {
|
||||||
|
+filepresent (const char *run) {
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
if(!stat(run, &buf))
|
||||||
|
@@ -60,7 +60,7 @@ filepresent (char * run) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-char *get_next_string(char **temp, char *split_char)
|
||||||
|
+char *get_next_string(char **temp, const char *split_char)
|
||||||
|
{
|
||||||
|
char *token = NULL;
|
||||||
|
token = strsep(temp, split_char);
|
||||||
|
@@ -70,9 +70,9 @@ char *get_next_string(char **temp, char *split_char)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-get_word (char * sentence, char ** word)
|
||||||
|
+get_word (const char *sentence, char **word)
|
||||||
|
{
|
||||||
|
- char * p;
|
||||||
|
+ const char *p;
|
||||||
|
int len;
|
||||||
|
int skip = 0;
|
||||||
|
|
||||||
|
@@ -381,7 +381,7 @@ int get_linux_version_code(void)
|
||||||
|
return _linux_version_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int parse_prkey(char *ptr, uint64_t *prkey)
|
||||||
|
+int parse_prkey(const char *ptr, uint64_t *prkey)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
return 1;
|
||||||
|
@@ -398,7 +398,7 @@ int parse_prkey(char *ptr, uint64_t *prkey)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int parse_prkey_flags(char *ptr, uint64_t *prkey, uint8_t *flags)
|
||||||
|
+int parse_prkey_flags(const char *ptr, uint64_t *prkey, uint8_t *flags)
|
||||||
|
{
|
||||||
|
char *flagstr;
|
||||||
|
|
||||||
|
diff --git a/libmultipath/util.h b/libmultipath/util.h
|
||||||
|
index 56bd78c7..c19c5ac3 100644
|
||||||
|
--- a/libmultipath/util.h
|
||||||
|
+++ b/libmultipath/util.h
|
||||||
|
@@ -9,9 +9,9 @@
|
||||||
|
|
||||||
|
size_t strchop(char *);
|
||||||
|
int basenamecpy (const char *src, char *dst, size_t size);
|
||||||
|
-int filepresent (char * run);
|
||||||
|
-char *get_next_string(char **temp, char *split_char);
|
||||||
|
-int get_word (char * sentence, char ** word);
|
||||||
|
+int filepresent (const char *run);
|
||||||
|
+char *get_next_string(char **temp, const char *split_char);
|
||||||
|
+int get_word (const char * sentence, char ** word);
|
||||||
|
size_t strlcpy(char *dst, const char *src, size_t size);
|
||||||
|
size_t strlcat(char *dst, const char *src, size_t size);
|
||||||
|
int devt2devname (char *, int, char *);
|
||||||
|
@@ -20,8 +20,8 @@ char *convert_dev(char *dev, int is_path_device);
|
||||||
|
void setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached);
|
||||||
|
int systemd_service_enabled(const char *dev);
|
||||||
|
int get_linux_version_code(void);
|
||||||
|
-int parse_prkey(char *ptr, uint64_t *prkey);
|
||||||
|
-int parse_prkey_flags(char *ptr, uint64_t *prkey, uint8_t *flags);
|
||||||
|
+int parse_prkey(const char *ptr, uint64_t *prkey);
|
||||||
|
+int parse_prkey_flags(const char *ptr, uint64_t *prkey, uint8_t *flags);
|
||||||
|
int safe_write(int fd, const void *buf, size_t count);
|
||||||
|
void set_max_fds(rlim_t max_fds);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,99 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:07 +0200
|
||||||
|
Subject: [PATCH] libmultipath: constify file argument in config parser
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 3 +--
|
||||||
|
libmultipath/config.h | 2 +-
|
||||||
|
libmultipath/parser.c | 9 +++++----
|
||||||
|
libmultipath/parser.h | 2 +-
|
||||||
|
4 files changed, 8 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index a253a936..1818f8b9 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -718,8 +718,7 @@ static void set_max_checkint_from_watchdog(struct config *conf)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-struct config *
|
||||||
|
-load_config (char * file)
|
||||||
|
+struct config *load_config(const char *file)
|
||||||
|
{
|
||||||
|
struct config *conf = alloc_config();
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index c7a73fba..78375f2f 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -253,7 +253,7 @@ void free_mptable (vector mptable);
|
||||||
|
|
||||||
|
int store_hwe (vector hwtable, struct hwentry *);
|
||||||
|
|
||||||
|
-struct config *load_config (char * file);
|
||||||
|
+struct config *load_config (const char *file);
|
||||||
|
struct config * alloc_config (void);
|
||||||
|
void free_config (struct config * conf);
|
||||||
|
extern struct config *get_multipath_config(void);
|
||||||
|
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
|
||||||
|
index a7285a35..d150e7b2 100644
|
||||||
|
--- a/libmultipath/parser.c
|
||||||
|
+++ b/libmultipath/parser.c
|
||||||
|
@@ -400,7 +400,7 @@ set_regex_value(vector strvec)
|
||||||
|
/* non-recursive configuration stream handler */
|
||||||
|
static int kw_level = 0;
|
||||||
|
|
||||||
|
-int warn_on_duplicates(vector uniques, char *str, char *file)
|
||||||
|
+int warn_on_duplicates(vector uniques, char *str, const char *file)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
int i;
|
||||||
|
@@ -444,7 +444,7 @@ is_sublevel_keyword(char *str)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-validate_config_strvec(vector strvec, char *file)
|
||||||
|
+validate_config_strvec(vector strvec, const char *file)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
int i;
|
||||||
|
@@ -507,7 +507,8 @@ validate_config_strvec(vector strvec, char *file)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-process_stream(struct config *conf, FILE *stream, vector keywords, char *file)
|
||||||
|
+process_stream(struct config *conf, FILE *stream, vector keywords,
|
||||||
|
+ const char *file)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int r = 0, t;
|
||||||
|
@@ -592,7 +593,7 @@ out:
|
||||||
|
|
||||||
|
/* Data initialization */
|
||||||
|
int
|
||||||
|
-process_file(struct config *conf, char *file)
|
||||||
|
+process_file(struct config *conf, const char *file)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
FILE *stream;
|
||||||
|
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
|
||||||
|
index b7917052..b385fb9e 100644
|
||||||
|
--- a/libmultipath/parser.h
|
||||||
|
+++ b/libmultipath/parser.h
|
||||||
|
@@ -78,7 +78,7 @@ extern void free_keywords(vector keywords);
|
||||||
|
extern vector alloc_strvec(char *string);
|
||||||
|
extern void *set_value(vector strvec);
|
||||||
|
extern void *set_regex_value(vector strvec);
|
||||||
|
-extern int process_file(struct config *conf, char *conf_file);
|
||||||
|
+extern int process_file(struct config *conf, const char *conf_file);
|
||||||
|
extern struct keyword * find_keyword(vector keywords, vector v, char * name);
|
||||||
|
int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
|
||||||
|
const void *data);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
182
0075-libmultipath-provide-defaults-for-get-put-_multipath.patch
Normal file
182
0075-libmultipath-provide-defaults-for-get-put-_multipath.patch
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:08 +0200
|
||||||
|
Subject: [PATCH] libmultipath: provide defaults for {get,put}_multipath_config
|
||||||
|
|
||||||
|
Add an implementation of get_multipath_config() and put_multipath_config()
|
||||||
|
to libmultipath. The linker's symbol lookup rules will make sure that
|
||||||
|
applications can override these functions if they need to. Defining
|
||||||
|
these functions in libmultipath avoids the need to provide stubs
|
||||||
|
for these functions in every appliation linking to libmultipath.
|
||||||
|
|
||||||
|
libmultipath's internal functions simply refer to a static "struct config".
|
||||||
|
It must be initialized with init_config() rather than load_config(),
|
||||||
|
which always allocates a new struct for backward compatibility, and must
|
||||||
|
be teared down using uninit_config().
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 72 +++++++++++++++++++++++++++++++++++++------
|
||||||
|
libmultipath/config.h | 21 +++++++++++--
|
||||||
|
2 files changed, 80 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index 1818f8b9..422e923d 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -28,6 +28,23 @@
|
||||||
|
#include "propsel.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
+static struct config __internal_config;
|
||||||
|
+struct config *libmp_get_multipath_config(void)
|
||||||
|
+{
|
||||||
|
+ return &__internal_config;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct config *get_multipath_config(void)
|
||||||
|
+ __attribute__((weak, alias("libmp_get_multipath_config")));
|
||||||
|
+
|
||||||
|
+void libmp_put_multipath_config(void *conf __attribute__((unused)))
|
||||||
|
+{
|
||||||
|
+ /* empty */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void put_multipath_config(void *conf)
|
||||||
|
+ __attribute__((weak, alias("libmp_put_multipath_config")));
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
hwe_strmatch (const struct hwentry *hwe1, const struct hwentry *hwe2)
|
||||||
|
{
|
||||||
|
@@ -575,17 +592,15 @@ restart:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
-struct config *
|
||||||
|
-alloc_config (void)
|
||||||
|
+static struct config *alloc_config (void)
|
||||||
|
{
|
||||||
|
return (struct config *)MALLOC(sizeof(struct config));
|
||||||
|
}
|
||||||
|
|
||||||
|
-void
|
||||||
|
-free_config (struct config * conf)
|
||||||
|
+static void _uninit_config(struct config *conf)
|
||||||
|
{
|
||||||
|
if (!conf)
|
||||||
|
- return;
|
||||||
|
+ conf = &__internal_config;
|
||||||
|
|
||||||
|
if (conf->multipath_dir)
|
||||||
|
FREE(conf->multipath_dir);
|
||||||
|
@@ -649,7 +664,27 @@ free_config (struct config * conf)
|
||||||
|
free_hwtable(conf->hwtable);
|
||||||
|
free_hwe(conf->overrides);
|
||||||
|
free_keywords(conf->keywords);
|
||||||
|
- FREE(conf);
|
||||||
|
+
|
||||||
|
+ memset(conf, 0, sizeof(*conf));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void uninit_config(void)
|
||||||
|
+{
|
||||||
|
+ _uninit_config(&__internal_config);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void free_config(struct config *conf)
|
||||||
|
+{
|
||||||
|
+ if (!conf)
|
||||||
|
+ return;
|
||||||
|
+ else if (conf == &__internal_config) {
|
||||||
|
+ condlog(0, "ERROR: %s called for internal config. Use uninit_config() instead",
|
||||||
|
+ __func__);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ _uninit_config(conf);
|
||||||
|
+ free(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if multipath fails to process the config directory, it should continue,
|
||||||
|
@@ -718,12 +753,29 @@ static void set_max_checkint_from_watchdog(struct config *conf)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+static int _init_config (const char *file, struct config *conf);
|
||||||
|
+
|
||||||
|
+int init_config(const char *file)
|
||||||
|
+{
|
||||||
|
+ return _init_config(file, &__internal_config);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct config *load_config(const char *file)
|
||||||
|
{
|
||||||
|
struct config *conf = alloc_config();
|
||||||
|
|
||||||
|
+ if (conf && !_init_config(file, conf))
|
||||||
|
+ return conf;
|
||||||
|
+
|
||||||
|
+ free(conf);
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int _init_config (const char *file, struct config *conf)
|
||||||
|
+{
|
||||||
|
+
|
||||||
|
if (!conf)
|
||||||
|
- return NULL;
|
||||||
|
+ conf = &__internal_config;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* internal defaults
|
||||||
|
@@ -911,10 +963,10 @@ struct config *load_config(const char *file)
|
||||||
|
!conf->wwids_file || !conf->prkeys_file)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
- return conf;
|
||||||
|
+ return 0;
|
||||||
|
out:
|
||||||
|
- free_config(conf);
|
||||||
|
- return NULL;
|
||||||
|
+ _uninit_config(conf);
|
||||||
|
+ return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_uid_attribute_by_attrs(struct config *conf,
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index 78375f2f..83d179ac 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -254,10 +254,25 @@ void free_mptable (vector mptable);
|
||||||
|
int store_hwe (vector hwtable, struct hwentry *);
|
||||||
|
|
||||||
|
struct config *load_config (const char *file);
|
||||||
|
-struct config * alloc_config (void);
|
||||||
|
void free_config (struct config * conf);
|
||||||
|
-extern struct config *get_multipath_config(void);
|
||||||
|
-extern void put_multipath_config(void *);
|
||||||
|
+int init_config(const char *file);
|
||||||
|
+void uninit_config(void);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * libmultipath provides default implementations of
|
||||||
|
+ * get_multipath_config() and put_multipath_config().
|
||||||
|
+ * Applications using these should use init_config(file, NULL)
|
||||||
|
+ * to load the configuration, rather than load_config(file).
|
||||||
|
+ * Likewise, uninit_config() should be used for teardown, but
|
||||||
|
+ * using free_config() for that is supported, too.
|
||||||
|
+ * Applications can define their own {get,put}_multipath_config()
|
||||||
|
+ * functions, which override the library-internal ones, but
|
||||||
|
+ * could still call libmp_{get,put}_multipath_config().
|
||||||
|
+ */
|
||||||
|
+struct config *libmp_get_multipath_config(void);
|
||||||
|
+struct config *get_multipath_config(void);
|
||||||
|
+void libmp_put_multipath_config(void *);
|
||||||
|
+void put_multipath_config(void *);
|
||||||
|
|
||||||
|
int parse_uid_attrs(char *uid_attrs, struct config *conf);
|
||||||
|
char *get_uid_attribute_by_attrs(struct config *conf,
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
142
0076-libmpathpersist-allow-using-libmultipath-get-put-_mu.patch
Normal file
142
0076-libmpathpersist-allow-using-libmultipath-get-put-_mu.patch
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:09 +0200
|
||||||
|
Subject: [PATCH] libmpathpersist: allow using libmultipath
|
||||||
|
{get,put}_multipath_config
|
||||||
|
|
||||||
|
Provide an alternative init function libmpathpersist_init() which
|
||||||
|
avoids allocating a new struct config, simply using libmultipath's
|
||||||
|
internal implementation.
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_persist.c | 42 ++++++++++++++++++++++++++++-----
|
||||||
|
libmpathpersist/mpath_persist.h | 28 ++++++++++++++++++++++
|
||||||
|
2 files changed, 64 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||||
|
index a132f4e9..9dfc98cd 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.c
|
||||||
|
+++ b/libmpathpersist/mpath_persist.c
|
||||||
|
@@ -37,6 +37,27 @@
|
||||||
|
|
||||||
|
extern struct udev *udev;
|
||||||
|
|
||||||
|
+static void adapt_config(struct config *conf)
|
||||||
|
+{
|
||||||
|
+ conf->force_sync = 1;
|
||||||
|
+ set_max_fds(conf->max_fds);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int libmpathpersist_init(void)
|
||||||
|
+{
|
||||||
|
+ struct config *conf;
|
||||||
|
+ int rc = 0;
|
||||||
|
+
|
||||||
|
+ if (init_config(DEFAULT_CONFIGFILE)) {
|
||||||
|
+ condlog(0, "Failed to initialize multipath config.");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ conf = libmp_get_multipath_config();
|
||||||
|
+ adapt_config(conf);
|
||||||
|
+ libmp_put_multipath_config(conf);
|
||||||
|
+ return rc;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct config *
|
||||||
|
mpath_lib_init (void)
|
||||||
|
{
|
||||||
|
@@ -47,21 +68,30 @@ mpath_lib_init (void)
|
||||||
|
condlog(0, "Failed to initialize multipath config.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
- conf->force_sync = 1;
|
||||||
|
- set_max_fds(conf->max_fds);
|
||||||
|
-
|
||||||
|
+ adapt_config(conf);
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-mpath_lib_exit (struct config *conf)
|
||||||
|
+static void libmpathpersist_cleanup(void)
|
||||||
|
{
|
||||||
|
dm_lib_release();
|
||||||
|
dm_lib_exit();
|
||||||
|
cleanup_prio();
|
||||||
|
cleanup_checkers();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+mpath_lib_exit (struct config *conf)
|
||||||
|
+{
|
||||||
|
+ libmpathpersist_cleanup();
|
||||||
|
free_config(conf);
|
||||||
|
- conf = NULL;
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int libmpathpersist_exit(void)
|
||||||
|
+{
|
||||||
|
+ libmpathpersist_cleanup();
|
||||||
|
+ uninit_config();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
|
||||||
|
index 7cf4faf9..91606efc 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.h
|
||||||
|
+++ b/libmpathpersist/mpath_persist.h
|
||||||
|
@@ -175,6 +175,22 @@ struct prout_param_descriptor { /* PROUT parameter descriptor */
|
||||||
|
* DESCRIPTION :
|
||||||
|
* Initialize device mapper multipath configuration. This function must be invoked first
|
||||||
|
* before performing reservation management functions.
|
||||||
|
+ * Either this function or mpath_lib_init() may be used.
|
||||||
|
+ * Use this function to work with libmultipath's internal "struct config".
|
||||||
|
+ * Call libmpathpersist_exit() for cleanup.
|
||||||
|
+ * RESTRICTIONS:
|
||||||
|
+ *
|
||||||
|
+ * RETURNS: 0->Success, 1->Failed.
|
||||||
|
+ */
|
||||||
|
+extern int libmpathpersist_init (void);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * DESCRIPTION :
|
||||||
|
+ * Initialize device mapper multipath configuration. This function must be invoked first
|
||||||
|
+ * before performing reservation management functions.
|
||||||
|
+ * Either this function or libmpathpersist_init() may be used.
|
||||||
|
+ * Use this function to work with an application-specific "struct config".
|
||||||
|
+ * Call mpath_lib_exit() for cleanup.
|
||||||
|
* RESTRICTIONS:
|
||||||
|
*
|
||||||
|
* RETURNS: struct config ->Success, NULL->Failed.
|
||||||
|
@@ -186,12 +202,24 @@ extern struct config * mpath_lib_init (void);
|
||||||
|
* DESCRIPTION :
|
||||||
|
* Release device mapper multipath configuration. This function must be invoked after
|
||||||
|
* performing reservation management functions.
|
||||||
|
+ * Use this after initialization with mpath_lib_init().
|
||||||
|
* RESTRICTIONS:
|
||||||
|
*
|
||||||
|
* RETURNS: 0->Success, 1->Failed.
|
||||||
|
*/
|
||||||
|
extern int mpath_lib_exit (struct config *conf);
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * DESCRIPTION :
|
||||||
|
+ * Release device mapper multipath configuration. This function must be invoked after
|
||||||
|
+ * performing reservation management functions.
|
||||||
|
+ * Use this after initialization with libmpathpersist_init().
|
||||||
|
+ * RESTRICTIONS:
|
||||||
|
+ *
|
||||||
|
+ * RETURNS: 0->Success, 1->Failed.
|
||||||
|
+ */
|
||||||
|
+extern int libmpathpersist_exit (void);
|
||||||
|
+
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DESCRIPTION :
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,68 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:10 +0200
|
||||||
|
Subject: [PATCH] multipath: use {get_put}_multipath_config from libmultipath
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/main.c | 20 ++++----------------
|
||||||
|
1 file changed, 4 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index ce48a932..879d7ac9 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -67,7 +67,6 @@
|
||||||
|
|
||||||
|
int logsink;
|
||||||
|
struct udev *udev;
|
||||||
|
-struct config *multipath_conf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return values of configure(), check_path_valid(), and main().
|
||||||
|
@@ -78,16 +77,6 @@ enum {
|
||||||
|
RTVL_RETRY, /* returned by configure(), not by main() */
|
||||||
|
};
|
||||||
|
|
||||||
|
-struct config *get_multipath_config(void)
|
||||||
|
-{
|
||||||
|
- return multipath_conf;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void put_multipath_config(__attribute__((unused)) void *arg)
|
||||||
|
-{
|
||||||
|
- /* Noop for now */
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int
|
||||||
|
dump_config (struct config *conf, vector hwes, vector mpvec)
|
||||||
|
{
|
||||||
|
@@ -892,10 +881,9 @@ main (int argc, char *argv[])
|
||||||
|
|
||||||
|
udev = udev_new();
|
||||||
|
logsink = 0;
|
||||||
|
- conf = load_config(DEFAULT_CONFIGFILE);
|
||||||
|
- if (!conf)
|
||||||
|
+ if (init_config(DEFAULT_CONFIGFILE))
|
||||||
|
exit(RTVL_FAIL);
|
||||||
|
- multipath_conf = conf;
|
||||||
|
+ conf = get_multipath_config();
|
||||||
|
conf->retrigger_tries = 0;
|
||||||
|
conf->force_sync = 1;
|
||||||
|
while ((arg = getopt(argc, argv, ":aAdDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
|
||||||
|
@@ -1148,8 +1136,8 @@ out_free_config:
|
||||||
|
* the logging function (dm_write_log()), which is called there,
|
||||||
|
* references the config.
|
||||||
|
*/
|
||||||
|
- free_config(conf);
|
||||||
|
- conf = NULL;
|
||||||
|
+ put_multipath_config(conf);
|
||||||
|
+ uninit_config();
|
||||||
|
udev_unref(udev);
|
||||||
|
if (dev)
|
||||||
|
FREE(dev);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,56 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:11 +0200
|
||||||
|
Subject: [PATCH] mpathpersist: use {get,put}_multipath_config() from
|
||||||
|
libmultipath
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
mpathpersist/main.c | 16 ++--------------
|
||||||
|
1 file changed, 2 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mpathpersist/main.c b/mpathpersist/main.c
|
||||||
|
index 28bfe410..0f0db4b8 100644
|
||||||
|
--- a/mpathpersist/main.c
|
||||||
|
+++ b/mpathpersist/main.c
|
||||||
|
@@ -43,17 +43,6 @@ void mpath_print_transport_id(struct prin_fulldescr *fdesc);
|
||||||
|
int construct_transportid(const char * inp, struct transportid transid[], int num_transportids);
|
||||||
|
|
||||||
|
int logsink;
|
||||||
|
-struct config *multipath_conf;
|
||||||
|
-
|
||||||
|
-struct config *get_multipath_config(void)
|
||||||
|
-{
|
||||||
|
- return multipath_conf;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-void put_multipath_config(__attribute__((unused)) void * arg)
|
||||||
|
-{
|
||||||
|
- /* Noop for now */
|
||||||
|
-}
|
||||||
|
|
||||||
|
void rcu_register_thread_memb(void) {}
|
||||||
|
|
||||||
|
@@ -620,15 +609,14 @@ int main(int argc, char *argv[])
|
||||||
|
}
|
||||||
|
|
||||||
|
udev = udev_new();
|
||||||
|
- multipath_conf = mpath_lib_init();
|
||||||
|
- if(!multipath_conf) {
|
||||||
|
+ if (libmpathpersist_init()) {
|
||||||
|
udev_unref(udev);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = handle_args(argc, argv, 0);
|
||||||
|
|
||||||
|
- mpath_lib_exit(multipath_conf);
|
||||||
|
+ libmpathpersist_exit();
|
||||||
|
udev_unref(udev);
|
||||||
|
|
||||||
|
return (ret >= 0) ? ret : MPATH_PR_OTHER;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
156
0079-libmultipath-add-udev-and-logsink-symbols.patch
Normal file
156
0079-libmultipath-add-udev-and-logsink-symbols.patch
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:12 +0200
|
||||||
|
Subject: [PATCH] libmultipath: add udev and logsink symbols
|
||||||
|
|
||||||
|
With these symbols added, applications using libmultipath don't
|
||||||
|
need to define global variables "udev" and "logsink" any more.
|
||||||
|
This comes at the cost of having to call an init function.
|
||||||
|
Currently, libmultipath_init() does nothing but initialize
|
||||||
|
"udev".
|
||||||
|
|
||||||
|
The linker's symbol lookup order still allows applications to use
|
||||||
|
their own "logsink" and "udev" variables, which will take precendence
|
||||||
|
over libmultipath's internal ones. In this case, calling
|
||||||
|
libmultipath_init() can be skipped, but like before,
|
||||||
|
udev should be initialized (using udev_new()) before making any
|
||||||
|
libmultipath calls.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.c | 46 +++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
libmultipath/config.h | 46 ++++++++++++++++++++++++++++++++++++++++++-
|
||||||
|
libmultipath/debug.c | 2 ++
|
||||||
|
3 files changed, 93 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.c b/libmultipath/config.c
|
||||||
|
index 422e923d..b3809433 100644
|
||||||
|
--- a/libmultipath/config.c
|
||||||
|
+++ b/libmultipath/config.c
|
||||||
|
@@ -28,6 +28,52 @@
|
||||||
|
#include "propsel.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * We don't support re-initialization after
|
||||||
|
+ * libmultipath_exit().
|
||||||
|
+ */
|
||||||
|
+static bool libmultipath_exit_called;
|
||||||
|
+static pthread_once_t _init_once = PTHREAD_ONCE_INIT;
|
||||||
|
+static pthread_once_t _exit_once = PTHREAD_ONCE_INIT;
|
||||||
|
+struct udev *udev;
|
||||||
|
+
|
||||||
|
+static void _udev_init(void)
|
||||||
|
+{
|
||||||
|
+ if (udev)
|
||||||
|
+ udev_ref(udev);
|
||||||
|
+ else
|
||||||
|
+ udev = udev_new();
|
||||||
|
+ if (!udev)
|
||||||
|
+ condlog(0, "%s: failed to initialize udev", __func__);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void _libmultipath_init(void)
|
||||||
|
+{
|
||||||
|
+ _udev_init();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool _is_libmultipath_initialized(void)
|
||||||
|
+{
|
||||||
|
+ return !libmultipath_exit_called && !!udev;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int libmultipath_init(void)
|
||||||
|
+{
|
||||||
|
+ pthread_once(&_init_once, _libmultipath_init);
|
||||||
|
+ return !_is_libmultipath_initialized();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void _libmultipath_exit(void)
|
||||||
|
+{
|
||||||
|
+ libmultipath_exit_called = true;
|
||||||
|
+ udev_unref(udev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void libmultipath_exit(void)
|
||||||
|
+{
|
||||||
|
+ pthread_once(&_exit_once, _libmultipath_exit);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static struct config __internal_config;
|
||||||
|
struct config *libmp_get_multipath_config(void)
|
||||||
|
{
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index 83d179ac..089b2ac2 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -235,7 +235,51 @@ struct config {
|
||||||
|
char *enable_foreign;
|
||||||
|
};
|
||||||
|
|
||||||
|
-extern struct udev * udev;
|
||||||
|
+/**
|
||||||
|
+ * extern variable: udev
|
||||||
|
+ *
|
||||||
|
+ * A &struct udev instance used by libmultipath. libmultipath expects
|
||||||
|
+ * a valid, initialized &struct udev in this variable.
|
||||||
|
+ * An application can define this variable itself, in which case
|
||||||
|
+ * the applications's instance will take precedence.
|
||||||
|
+ * The application can initialize and destroy this variable by
|
||||||
|
+ * calling libmultipath_init() and libmultipath_exit(), respectively,
|
||||||
|
+ * whether or not it defines the variable itself.
|
||||||
|
+ * An application can initialize udev with udev_new() before calling
|
||||||
|
+ * libmultipath_init(), e.g. if it has to make libudev calls before
|
||||||
|
+ * libmultipath calls. If an application wants to keep using the
|
||||||
|
+ * udev variable after calling libmultipath_exit(), it should have taken
|
||||||
|
+ * an additional reference on it beforehand. This is the case e.g.
|
||||||
|
+ * after initiazing udev with udev_new().
|
||||||
|
+ */
|
||||||
|
+extern struct udev *udev;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * libmultipath_init() - library initialization
|
||||||
|
+ *
|
||||||
|
+ * This function initializes libmultipath data structures.
|
||||||
|
+ * It is light-weight; some other initializations, like device-mapper
|
||||||
|
+ * initialization, are done lazily when the respective functionality
|
||||||
|
+ * is required.
|
||||||
|
+ *
|
||||||
|
+ * Clean up by libmultipath_exit() when the program terminates.
|
||||||
|
+ * It is an error to call libmultipath_init() after libmultipath_exit().
|
||||||
|
+ * Return: 0 on success, 1 on failure.
|
||||||
|
+ */
|
||||||
|
+int libmultipath_init(void);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * libmultipath_exit() - library un-initialization
|
||||||
|
+ *
|
||||||
|
+ * This function un-initializes libmultipath data structures.
|
||||||
|
+ * It is recommended to call this function at program exit.
|
||||||
|
+ *
|
||||||
|
+ * Calls to libmultipath_init() after libmultipath_exit() will fail
|
||||||
|
+ * (in other words, libmultipath can't be re-initialized).
|
||||||
|
+ * Any other libmultipath calls after libmultipath_exit() may cause
|
||||||
|
+ * undefined behavior.
|
||||||
|
+ */
|
||||||
|
+void libmultipath_exit(void);
|
||||||
|
|
||||||
|
int find_hwe (const struct _vector *hwtable,
|
||||||
|
const char * vendor, const char * product, const char *revision,
|
||||||
|
diff --git a/libmultipath/debug.c b/libmultipath/debug.c
|
||||||
|
index 4128cb90..b3a1de9e 100644
|
||||||
|
--- a/libmultipath/debug.c
|
||||||
|
+++ b/libmultipath/debug.c
|
||||||
|
@@ -15,6 +15,8 @@
|
||||||
|
#include "defaults.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
+int logsink;
|
||||||
|
+
|
||||||
|
void dlog (int sink, int prio, const char * fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
49
0080-multipath-remove-logsink-and-udev.patch
Normal file
49
0080-multipath-remove-logsink-and-udev.patch
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:13 +0200
|
||||||
|
Subject: [PATCH] multipath: remove logsink and udev
|
||||||
|
|
||||||
|
We can use libmultipath's symbols now.
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipath/main.c | 7 ++-----
|
||||||
|
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipath/main.c b/multipath/main.c
|
||||||
|
index 879d7ac9..322b30e0 100644
|
||||||
|
--- a/multipath/main.c
|
||||||
|
+++ b/multipath/main.c
|
||||||
|
@@ -65,9 +65,6 @@
|
||||||
|
#include "file.h"
|
||||||
|
#include "valid.h"
|
||||||
|
|
||||||
|
-int logsink;
|
||||||
|
-struct udev *udev;
|
||||||
|
-
|
||||||
|
/*
|
||||||
|
* Return values of configure(), check_path_valid(), and main().
|
||||||
|
*/
|
||||||
|
@@ -879,7 +876,7 @@ main (int argc, char *argv[])
|
||||||
|
int retries = -1;
|
||||||
|
bool enable_foreign = false;
|
||||||
|
|
||||||
|
- udev = udev_new();
|
||||||
|
+ libmultipath_init();
|
||||||
|
logsink = 0;
|
||||||
|
if (init_config(DEFAULT_CONFIGFILE))
|
||||||
|
exit(RTVL_FAIL);
|
||||||
|
@@ -1138,7 +1135,7 @@ out_free_config:
|
||||||
|
*/
|
||||||
|
put_multipath_config(conf);
|
||||||
|
uninit_config();
|
||||||
|
- udev_unref(udev);
|
||||||
|
+ libmultipath_exit();
|
||||||
|
if (dev)
|
||||||
|
FREE(dev);
|
||||||
|
#ifdef _DEBUG_
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
98
0081-libmpathpersist-call-libmultipath_-init-exit.patch
Normal file
98
0081-libmpathpersist-call-libmultipath_-init-exit.patch
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:14 +0200
|
||||||
|
Subject: [PATCH] libmpathpersist: call libmultipath_{init,exit}()
|
||||||
|
|
||||||
|
Have libmpathpersist_{init,exit} do the udev initialization, too.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathpersist/mpath_persist.c | 13 +++++++++----
|
||||||
|
libmpathpersist/mpath_persist.h | 9 ++++++---
|
||||||
|
2 files changed, 15 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
|
||||||
|
index 9dfc98cd..d1538195 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.c
|
||||||
|
+++ b/libmpathpersist/mpath_persist.c
|
||||||
|
@@ -48,6 +48,10 @@ int libmpathpersist_init(void)
|
||||||
|
struct config *conf;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
+ if (libmultipath_init()) {
|
||||||
|
+ condlog(0, "Failed to initialize libmultipath.");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
if (init_config(DEFAULT_CONFIGFILE)) {
|
||||||
|
condlog(0, "Failed to initialize multipath config.");
|
||||||
|
return 1;
|
||||||
|
@@ -74,24 +78,25 @@ mpath_lib_init (void)
|
||||||
|
|
||||||
|
static void libmpathpersist_cleanup(void)
|
||||||
|
{
|
||||||
|
- dm_lib_release();
|
||||||
|
- dm_lib_exit();
|
||||||
|
cleanup_prio();
|
||||||
|
cleanup_checkers();
|
||||||
|
+ libmultipath_exit();
|
||||||
|
+ dm_lib_release();
|
||||||
|
+ dm_lib_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mpath_lib_exit (struct config *conf)
|
||||||
|
{
|
||||||
|
- libmpathpersist_cleanup();
|
||||||
|
free_config(conf);
|
||||||
|
+ libmpathpersist_cleanup();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libmpathpersist_exit(void)
|
||||||
|
{
|
||||||
|
- libmpathpersist_cleanup();
|
||||||
|
uninit_config();
|
||||||
|
+ libmpathpersist_cleanup();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
|
||||||
|
index 91606efc..5435eae4 100644
|
||||||
|
--- a/libmpathpersist/mpath_persist.h
|
||||||
|
+++ b/libmpathpersist/mpath_persist.h
|
||||||
|
@@ -176,7 +176,8 @@ struct prout_param_descriptor { /* PROUT parameter descriptor */
|
||||||
|
* Initialize device mapper multipath configuration. This function must be invoked first
|
||||||
|
* before performing reservation management functions.
|
||||||
|
* Either this function or mpath_lib_init() may be used.
|
||||||
|
- * Use this function to work with libmultipath's internal "struct config".
|
||||||
|
+ * Use this function to work with libmultipath's internal "struct config"
|
||||||
|
+ * and "struct udev". The latter will be initialized automatically.
|
||||||
|
* Call libmpathpersist_exit() for cleanup.
|
||||||
|
* RESTRICTIONS:
|
||||||
|
*
|
||||||
|
@@ -189,7 +190,8 @@ extern int libmpathpersist_init (void);
|
||||||
|
* Initialize device mapper multipath configuration. This function must be invoked first
|
||||||
|
* before performing reservation management functions.
|
||||||
|
* Either this function or libmpathpersist_init() may be used.
|
||||||
|
- * Use this function to work with an application-specific "struct config".
|
||||||
|
+ * Use this function to work with an application-specific "struct config"
|
||||||
|
+ * and "struct udev". The latter must be initialized by the application.
|
||||||
|
* Call mpath_lib_exit() for cleanup.
|
||||||
|
* RESTRICTIONS:
|
||||||
|
*
|
||||||
|
@@ -211,9 +213,10 @@ extern int mpath_lib_exit (struct config *conf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DESCRIPTION :
|
||||||
|
- * Release device mapper multipath configuration. This function must be invoked after
|
||||||
|
+ * Release device mapper multipath configuration a. This function must be invoked after
|
||||||
|
* performing reservation management functions.
|
||||||
|
* Use this after initialization with libmpathpersist_init().
|
||||||
|
+ * Calling libmpathpersist_init() after libmpathpersist_exit() will fail.
|
||||||
|
* RESTRICTIONS:
|
||||||
|
*
|
||||||
|
* RETURNS: 0->Success, 1->Failed.
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
52
0082-mpathpersist-remove-logsink-and-udev.patch
Normal file
52
0082-mpathpersist-remove-logsink-and-udev.patch
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:15 +0200
|
||||||
|
Subject: [PATCH] mpathpersist: remove logsink and udev
|
||||||
|
|
||||||
|
We can use libmultipath's internal symbols now. The libmultipath
|
||||||
|
initialization is taken care of by libmpathpersist_init().
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
mpathpersist/main.c | 6 ------
|
||||||
|
1 file changed, 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mpathpersist/main.c b/mpathpersist/main.c
|
||||||
|
index 0f0db4b8..a25b08f0 100644
|
||||||
|
--- a/mpathpersist/main.c
|
||||||
|
+++ b/mpathpersist/main.c
|
||||||
|
@@ -42,13 +42,10 @@ void * mpath_alloc_prin_response(int prin_sa);
|
||||||
|
void mpath_print_transport_id(struct prin_fulldescr *fdesc);
|
||||||
|
int construct_transportid(const char * inp, struct transportid transid[], int num_transportids);
|
||||||
|
|
||||||
|
-int logsink;
|
||||||
|
-
|
||||||
|
void rcu_register_thread_memb(void) {}
|
||||||
|
|
||||||
|
void rcu_unregister_thread_memb(void) {}
|
||||||
|
|
||||||
|
-struct udev *udev;
|
||||||
|
|
||||||
|
static int verbose, loglevel, noisy;
|
||||||
|
|
||||||
|
@@ -608,16 +605,13 @@ int main(int argc, char *argv[])
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- udev = udev_new();
|
||||||
|
if (libmpathpersist_init()) {
|
||||||
|
- udev_unref(udev);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = handle_args(argc, argv, 0);
|
||||||
|
|
||||||
|
libmpathpersist_exit();
|
||||||
|
- udev_unref(udev);
|
||||||
|
|
||||||
|
return (ret >= 0) ? ret : MPATH_PR_OTHER;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
57
0083-multipathd-remove-logsink-and-udev.patch
Normal file
57
0083-multipathd-remove-logsink-and-udev.patch
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Thu, 24 Sep 2020 15:37:16 +0200
|
||||||
|
Subject: [PATCH] multipathd: remove logsink and udev
|
||||||
|
|
||||||
|
We can use the symbols from libmultipath now.
|
||||||
|
|
||||||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
multipathd/main.c | 9 +++------
|
||||||
|
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 48b62937..6a4b8b83 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -113,7 +113,6 @@ struct mpath_event_param
|
||||||
|
struct multipath *mpp;
|
||||||
|
};
|
||||||
|
|
||||||
|
-int logsink;
|
||||||
|
int uxsock_timeout;
|
||||||
|
int verbosity;
|
||||||
|
int bindings_read_only;
|
||||||
|
@@ -144,8 +143,6 @@ static inline enum daemon_status get_running_state(void)
|
||||||
|
*/
|
||||||
|
struct vectors * gvecs;
|
||||||
|
|
||||||
|
-struct udev * udev;
|
||||||
|
-
|
||||||
|
struct config *multipath_conf;
|
||||||
|
|
||||||
|
/* Local variables */
|
||||||
|
@@ -3009,8 +3006,6 @@ child (__attribute__((unused)) void *param)
|
||||||
|
conf = rcu_dereference(multipath_conf);
|
||||||
|
rcu_assign_pointer(multipath_conf, NULL);
|
||||||
|
call_rcu(&conf->rcu, rcu_free_config);
|
||||||
|
- udev_unref(udev);
|
||||||
|
- udev = NULL;
|
||||||
|
pthread_attr_destroy(&waiter_attr);
|
||||||
|
pthread_attr_destroy(&io_err_stat_attr);
|
||||||
|
#ifdef _DEBUG_
|
||||||
|
@@ -3114,7 +3109,9 @@ main (int argc, char *argv[])
|
||||||
|
|
||||||
|
pthread_cond_init_mono(&config_cond);
|
||||||
|
|
||||||
|
- udev = udev_new();
|
||||||
|
+ libmultipath_init();
|
||||||
|
+ if (atexit(libmultipath_exit))
|
||||||
|
+ condlog(3, "failed to register exit handler for libmultipath");
|
||||||
|
libmp_udev_set_sync_support(0);
|
||||||
|
|
||||||
|
while ((arg = getopt(argc, argv, ":dsv:k::Bniw")) != EOF ) {
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
180
0084-libmpathvalid-use-default-_multipath_config-udev-and.patch
Normal file
180
0084-libmpathvalid-use-default-_multipath_config-udev-and.patch
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Sat, 26 Sep 2020 23:25:46 -0500
|
||||||
|
Subject: [PATCH] libmpathvalid: use default *_multipath_config, udev, and
|
||||||
|
logsink
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmpathvalid/libmpathvalid.version | 2 +-
|
||||||
|
libmpathvalid/mpath_valid.c | 73 ++++++++++++++++++++---------
|
||||||
|
libmpathvalid/mpath_valid.h | 12 +++--
|
||||||
|
3 files changed, 61 insertions(+), 26 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmpathvalid/libmpathvalid.version b/libmpathvalid/libmpathvalid.version
|
||||||
|
index 4d8a8ba4..3bd0d3c5 100644
|
||||||
|
--- a/libmpathvalid/libmpathvalid.version
|
||||||
|
+++ b/libmpathvalid/libmpathvalid.version
|
||||||
|
@@ -1,7 +1,7 @@
|
||||||
|
MPATH_1.0 {
|
||||||
|
global:
|
||||||
|
- mpathvalid_conf;
|
||||||
|
mpathvalid_init;
|
||||||
|
+ mpathvalid_reload_config;
|
||||||
|
mpathvalid_exit;
|
||||||
|
mpathvalid_is_path;
|
||||||
|
mpathvalid_get_mode;
|
||||||
|
diff --git a/libmpathvalid/mpath_valid.c b/libmpathvalid/mpath_valid.c
|
||||||
|
index 6153e8b7..d839dbac 100644
|
||||||
|
--- a/libmpathvalid/mpath_valid.c
|
||||||
|
+++ b/libmpathvalid/mpath_valid.c
|
||||||
|
@@ -15,9 +15,7 @@
|
||||||
|
#include "mpath_cmd.h"
|
||||||
|
#include "valid.h"
|
||||||
|
#include "mpath_valid.h"
|
||||||
|
-
|
||||||
|
-static struct config default_config = { .verbosity = -1 };
|
||||||
|
-struct config *mpathvalid_conf = &default_config;
|
||||||
|
+#include "debug.h"
|
||||||
|
|
||||||
|
static unsigned int get_conf_mode(struct config *conf)
|
||||||
|
{
|
||||||
|
@@ -68,38 +66,70 @@ static int convert_result(int result) {
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-mpathvalid_init(int verbosity)
|
||||||
|
+mpathvalid_init(int verbosity, int log_style)
|
||||||
|
{
|
||||||
|
unsigned int version[3];
|
||||||
|
struct config *conf;
|
||||||
|
|
||||||
|
- default_config.verbosity = verbosity;
|
||||||
|
- skip_libmp_dm_init();
|
||||||
|
- conf = load_config(DEFAULT_CONFIGFILE);
|
||||||
|
- if (!conf)
|
||||||
|
+ logsink = log_style;
|
||||||
|
+ if (libmultipath_init())
|
||||||
|
return -1;
|
||||||
|
+ conf = get_multipath_config();
|
||||||
|
conf->verbosity = verbosity;
|
||||||
|
- if (dm_prereq(version))
|
||||||
|
+ put_multipath_config(conf);
|
||||||
|
+
|
||||||
|
+ skip_libmp_dm_init();
|
||||||
|
+ if (init_config(DEFAULT_CONFIGFILE))
|
||||||
|
goto fail;
|
||||||
|
- memcpy(conf->version, version, sizeof(version));
|
||||||
|
+ if (dm_prereq(version))
|
||||||
|
+ goto fail_config;
|
||||||
|
|
||||||
|
- mpathvalid_conf = conf;
|
||||||
|
+ conf = get_multipath_config();
|
||||||
|
+ conf->verbosity = verbosity;
|
||||||
|
+ memcpy(conf->version, version, sizeof(version));
|
||||||
|
+ put_multipath_config(conf);
|
||||||
|
return 0;
|
||||||
|
+
|
||||||
|
+fail_config:
|
||||||
|
+ uninit_config();
|
||||||
|
fail:
|
||||||
|
- free_config(conf);
|
||||||
|
+ libmultipath_exit();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-mpathvalid_exit(void)
|
||||||
|
+mpathvalid_reload_config(void)
|
||||||
|
{
|
||||||
|
- struct config *conf = mpathvalid_conf;
|
||||||
|
+ int verbosity;
|
||||||
|
+ unsigned int version[3];
|
||||||
|
+ struct config *conf;
|
||||||
|
+
|
||||||
|
+ conf = get_multipath_config();
|
||||||
|
+ memcpy(version, conf->version, sizeof(version));
|
||||||
|
+ verbosity = conf->verbosity;
|
||||||
|
+ put_multipath_config(conf);
|
||||||
|
|
||||||
|
- default_config.verbosity = -1;
|
||||||
|
- if (mpathvalid_conf == &default_config)
|
||||||
|
- return 0;
|
||||||
|
- mpathvalid_conf = &default_config;
|
||||||
|
- free_config(conf);
|
||||||
|
+ uninit_config();
|
||||||
|
+
|
||||||
|
+ conf = get_multipath_config();
|
||||||
|
+ conf->verbosity = verbosity;
|
||||||
|
+ put_multipath_config(conf);
|
||||||
|
+
|
||||||
|
+ if (init_config(DEFAULT_CONFIGFILE))
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ conf = get_multipath_config();
|
||||||
|
+ conf->verbosity = verbosity;
|
||||||
|
+ memcpy(conf->version, version, sizeof(version));
|
||||||
|
+ put_multipath_config(conf);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+mpathvalid_exit(void)
|
||||||
|
+{
|
||||||
|
+ uninit_config();
|
||||||
|
+ libmultipath_exit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -121,9 +151,10 @@ mpathvalid_is_path(const char *name, unsigned int mode, char **wwid,
|
||||||
|
|
||||||
|
if (!name || mode >= MPATH_MAX_MODE)
|
||||||
|
return r;
|
||||||
|
-
|
||||||
|
if (nr_paths > 0 && !path_wwids)
|
||||||
|
return r;
|
||||||
|
+ if (!udev)
|
||||||
|
+ return r;
|
||||||
|
|
||||||
|
pp = alloc_path();
|
||||||
|
if (!pp)
|
||||||
|
@@ -136,7 +167,7 @@ mpathvalid_is_path(const char *name, unsigned int mode, char **wwid,
|
||||||
|
}
|
||||||
|
|
||||||
|
conf = get_multipath_config();
|
||||||
|
- if (!conf || conf == &default_config)
|
||||||
|
+ if (!conf)
|
||||||
|
goto out_wwid;
|
||||||
|
if (mode != MPATH_DEFAULT)
|
||||||
|
set_conf_mode(conf, mode);
|
||||||
|
diff --git a/libmpathvalid/mpath_valid.h b/libmpathvalid/mpath_valid.h
|
||||||
|
index 7fd8aa47..c83b8da5 100644
|
||||||
|
--- a/libmpathvalid/mpath_valid.h
|
||||||
|
+++ b/libmpathvalid/mpath_valid.h
|
||||||
|
@@ -42,15 +42,19 @@ enum mpath_valid_result {
|
||||||
|
MPATH_IS_MAYBE_VALID,
|
||||||
|
};
|
||||||
|
|
||||||
|
-struct config;
|
||||||
|
-extern struct config *mpathvalid_conf;
|
||||||
|
-int mpathvalid_init(int verbosity);
|
||||||
|
+enum mpath_valid_log_style {
|
||||||
|
+ MPATH_LOG_STDIO = -1,
|
||||||
|
+ MPATH_LOG_STDIO_TIMESTAMP,
|
||||||
|
+ MPATH_LOG_SYSLOG,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int mpathvalid_init(int verbosity, int log_style);
|
||||||
|
+int mpathvalid_reload_config(void);
|
||||||
|
int mpathvalid_exit(void);
|
||||||
|
unsigned int mpathvalid_get_mode(void);
|
||||||
|
int mpathvalid_is_path(const char *name, unsigned int mode, char **wwid,
|
||||||
|
const char **path_wwids, unsigned int nr_paths);
|
||||||
|
|
||||||
|
-
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
186
0085-Revert-libmultipath-add-ignore_udev_uid-option.patch
Normal file
186
0085-Revert-libmultipath-add-ignore_udev_uid-option.patch
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Sat, 26 Sep 2020 23:26:32 -0500
|
||||||
|
Subject: [PATCH] Revert "libmultipath: add ignore_udev_uid option"
|
||||||
|
|
||||||
|
This reverts commit f1350bc5c4aa445804f3f4fc8968fb46d581336e.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/config.h | 1 -
|
||||||
|
libmultipath/dict.c | 4 ----
|
||||||
|
libmultipath/discovery.c | 17 ++++++-----------
|
||||||
|
libmultipath/discovery.h | 8 +-------
|
||||||
|
libmultipath/uevent.c | 2 +-
|
||||||
|
multipath/multipath.conf.5 | 13 -------------
|
||||||
|
multipathd/main.c | 7 +------
|
||||||
|
7 files changed, 9 insertions(+), 43 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/config.h b/libmultipath/config.h
|
||||||
|
index 089b2ac2..576f15d1 100644
|
||||||
|
--- a/libmultipath/config.h
|
||||||
|
+++ b/libmultipath/config.h
|
||||||
|
@@ -192,7 +192,6 @@ struct config {
|
||||||
|
int find_multipaths_timeout;
|
||||||
|
int marginal_pathgroups;
|
||||||
|
int skip_delegate;
|
||||||
|
- int ignore_udev_uid;
|
||||||
|
unsigned int version[3];
|
||||||
|
unsigned int sequence_nr;
|
||||||
|
|
||||||
|
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
|
||||||
|
index 9a0729bf..184d4b22 100644
|
||||||
|
--- a/libmultipath/dict.c
|
||||||
|
+++ b/libmultipath/dict.c
|
||||||
|
@@ -1406,9 +1406,6 @@ declare_hw_snprint(all_tg_pt, print_yes_no_undef)
|
||||||
|
declare_def_handler(marginal_pathgroups, set_yes_no)
|
||||||
|
declare_def_snprint(marginal_pathgroups, print_yes_no)
|
||||||
|
|
||||||
|
-declare_def_handler(ignore_udev_uid, set_yes_no)
|
||||||
|
-declare_def_snprint(ignore_udev_uid, print_yes_no)
|
||||||
|
-
|
||||||
|
static int
|
||||||
|
def_uxsock_timeout_handler(struct config *conf, vector strvec)
|
||||||
|
{
|
||||||
|
@@ -1819,7 +1816,6 @@ init_keywords(vector keywords)
|
||||||
|
install_keyword("enable_foreign", &def_enable_foreign_handler,
|
||||||
|
&snprint_def_enable_foreign);
|
||||||
|
install_keyword("marginal_pathgroups", &def_marginal_pathgroups_handler, &snprint_def_marginal_pathgroups);
|
||||||
|
- install_keyword("ignore_udev_uid", &def_ignore_udev_uid_handler, &snprint_def_ignore_udev_uid);
|
||||||
|
__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
|
||||||
|
__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
|
||||||
|
__deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL);
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index f0e92227..002d3d18 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -2010,7 +2010,7 @@ static bool has_uid_fallback(struct path *pp)
|
||||||
|
|
||||||
|
int
|
||||||
|
get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
- int fallback)
|
||||||
|
+ int allow_fallback)
|
||||||
|
{
|
||||||
|
char *c;
|
||||||
|
const char *origin = "unknown";
|
||||||
|
@@ -2043,9 +2043,7 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
} else
|
||||||
|
len = strlen(pp->wwid);
|
||||||
|
origin = "callout";
|
||||||
|
- } else if (fallback == UID_FALLBACK_FORCE)
|
||||||
|
- len = uid_fallback(pp, path_state, &origin);
|
||||||
|
- else {
|
||||||
|
+ } else {
|
||||||
|
bool udev_available = udev && pp->uid_attribute
|
||||||
|
&& *pp->uid_attribute;
|
||||||
|
|
||||||
|
@@ -2058,9 +2056,8 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
else
|
||||||
|
origin = "udev";
|
||||||
|
}
|
||||||
|
- if ((!udev_available ||
|
||||||
|
- (len <= 0 && fallback == UID_FALLBACK_ALLOW)) &&
|
||||||
|
- has_uid_fallback(pp)) {
|
||||||
|
+ if ((!udev_available || (len <= 0 && allow_fallback))
|
||||||
|
+ && has_uid_fallback(pp)) {
|
||||||
|
used_fallback = 1;
|
||||||
|
len = uid_fallback(pp, path_state, &origin);
|
||||||
|
}
|
||||||
|
@@ -2200,10 +2197,8 @@ int pathinfo(struct path *pp, struct config *conf, int mask)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mask & DI_WWID) && !strlen(pp->wwid)) {
|
||||||
|
- int fallback = conf->ignore_udev_uid? UID_FALLBACK_FORCE :
|
||||||
|
- (pp->retriggers >= conf->retrigger_tries)?
|
||||||
|
- UID_FALLBACK_ALLOW : UID_FALLBACK_NONE;
|
||||||
|
- get_uid(pp, path_state, pp->udev, fallback);
|
||||||
|
+ get_uid(pp, path_state, pp->udev,
|
||||||
|
+ (pp->retriggers >= conf->retrigger_tries));
|
||||||
|
if (!strlen(pp->wwid)) {
|
||||||
|
if (pp->bus == SYSFS_BUS_UNDEF)
|
||||||
|
return PATHINFO_SKIPPED;
|
||||||
|
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
|
||||||
|
index ca8542d6..6444887d 100644
|
||||||
|
--- a/libmultipath/discovery.h
|
||||||
|
+++ b/libmultipath/discovery.h
|
||||||
|
@@ -54,14 +54,8 @@ ssize_t sysfs_get_inquiry(struct udev_device *udev,
|
||||||
|
unsigned char *buff, size_t len);
|
||||||
|
int sysfs_get_asymmetric_access_state(struct path *pp,
|
||||||
|
char *buff, int buflen);
|
||||||
|
-
|
||||||
|
-enum {
|
||||||
|
- UID_FALLBACK_NONE,
|
||||||
|
- UID_FALLBACK_ALLOW,
|
||||||
|
- UID_FALLBACK_FORCE,
|
||||||
|
-};
|
||||||
|
int get_uid(struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
- int fallback);
|
||||||
|
+ int allow_fallback);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* discovery bitmask
|
||||||
|
diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c
|
||||||
|
index d67129d1..e0d13b11 100644
|
||||||
|
--- a/libmultipath/uevent.c
|
||||||
|
+++ b/libmultipath/uevent.c
|
||||||
|
@@ -179,7 +179,7 @@ uevent_need_merge(void)
|
||||||
|
bool need_merge = false;
|
||||||
|
|
||||||
|
conf = get_multipath_config();
|
||||||
|
- if (!conf->ignore_udev_uid && VECTOR_SIZE(&conf->uid_attrs) > 0)
|
||||||
|
+ if (VECTOR_SIZE(&conf->uid_attrs) > 0)
|
||||||
|
need_merge = true;
|
||||||
|
put_multipath_config(conf);
|
||||||
|
|
||||||
|
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
|
||||||
|
index 175ca095..42a192f6 100644
|
||||||
|
--- a/multipath/multipath.conf.5
|
||||||
|
+++ b/multipath/multipath.conf.5
|
||||||
|
@@ -286,19 +286,6 @@ The default is: \fB<unset>\fR
|
||||||
|
.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
-.B ignore_udev_uid
|
||||||
|
-Setting this option to yes will force multipath to ignore the the uid_attrs
|
||||||
|
-and uid_attribute settings, and generate the WWID by the \fIsysfs\fR
|
||||||
|
-method. This will cause devices that cannot get their WWID from the standard
|
||||||
|
-locations for their device type to not get a WWID; see \fBWWID generation\fR
|
||||||
|
-below.
|
||||||
|
-.RS
|
||||||
|
-.TP
|
||||||
|
-The default is: \fBno\fR
|
||||||
|
-.RE
|
||||||
|
-.
|
||||||
|
-.
|
||||||
|
-.TP
|
||||||
|
.B prio
|
||||||
|
The name of the path priority routine. The specified routine
|
||||||
|
should return a numeric value specifying the relative priority
|
||||||
|
diff --git a/multipathd/main.c b/multipathd/main.c
|
||||||
|
index 6a4b8b83..94926b57 100644
|
||||||
|
--- a/multipathd/main.c
|
||||||
|
+++ b/multipathd/main.c
|
||||||
|
@@ -1223,7 +1223,6 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
|
||||||
|
if (pp) {
|
||||||
|
struct multipath *mpp = pp->mpp;
|
||||||
|
char wwid[WWID_SIZE];
|
||||||
|
- int fallback;
|
||||||
|
|
||||||
|
if (pp->initialized == INIT_REQUESTED_UDEV) {
|
||||||
|
needs_reinit = 1;
|
||||||
|
@@ -1235,11 +1234,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
strcpy(wwid, pp->wwid);
|
||||||
|
- conf = get_multipath_config();
|
||||||
|
- fallback = conf->ignore_udev_uid? UID_FALLBACK_FORCE:
|
||||||
|
- UID_FALLBACK_NONE;
|
||||||
|
- put_multipath_config(conf);
|
||||||
|
- rc = get_uid(pp, pp->state, uev->udev, fallback);
|
||||||
|
+ rc = get_uid(pp, pp->state, uev->udev, 0);
|
||||||
|
|
||||||
|
if (rc != 0)
|
||||||
|
strcpy(pp->wwid, wwid);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Date: Tue, 22 Sep 2020 16:03:31 -0500
|
||||||
|
Subject: [PATCH] libmultipath: change log level for null uid_attribute
|
||||||
|
|
||||||
|
If uid_attribute is explicitly set to an empty string, multipath should
|
||||||
|
log the uid at the default log level, since using the fallback code is
|
||||||
|
the expected behavior.
|
||||||
|
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/discovery.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||||||
|
index 002d3d18..77468524 100644
|
||||||
|
--- a/libmultipath/discovery.c
|
||||||
|
+++ b/libmultipath/discovery.c
|
||||||
|
@@ -2058,7 +2058,8 @@ get_uid (struct path * pp, int path_state, struct udev_device *udev,
|
||||||
|
}
|
||||||
|
if ((!udev_available || (len <= 0 && allow_fallback))
|
||||||
|
&& has_uid_fallback(pp)) {
|
||||||
|
- used_fallback = 1;
|
||||||
|
+ if (udev_available || !(udev && pp->uid_attribute))
|
||||||
|
+ used_fallback = 1;
|
||||||
|
len = uid_fallback(pp, path_state, &origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
33
0087-libmultipath-orphan_paths-avoid-BUG-message.patch
Normal file
33
0087-libmultipath-orphan_paths-avoid-BUG-message.patch
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Wilck <mwilck@suse.com>
|
||||||
|
Date: Tue, 11 Aug 2020 21:08:27 +0200
|
||||||
|
Subject: [PATCH] libmultipath: orphan_paths(): avoid BUG message
|
||||||
|
|
||||||
|
Since c44d769, we print a BUG message when we orphan a path that
|
||||||
|
holds the mpp->hwe pointer. But if this called via orphan_paths(),
|
||||||
|
this is expected and we shouldn't warn.
|
||||||
|
|
||||||
|
Fixes: c44d769 ("libmultipath: warn if freeing path that holds mpp->hwe")
|
||||||
|
|
||||||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||||||
|
---
|
||||||
|
libmultipath/structs_vec.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
|
||||||
|
index ede14297..d70bb6ad 100644
|
||||||
|
--- a/libmultipath/structs_vec.c
|
||||||
|
+++ b/libmultipath/structs_vec.c
|
||||||
|
@@ -114,6 +114,8 @@ void orphan_paths(vector pathvec, struct multipath *mpp, const char *reason)
|
||||||
|
int i;
|
||||||
|
struct path * pp;
|
||||||
|
|
||||||
|
+ /* Avoid BUG message from orphan_path() */
|
||||||
|
+ mpp->hwe = NULL;
|
||||||
|
vector_foreach_slot (pathvec, pp, i) {
|
||||||
|
if (pp->mpp == mpp) {
|
||||||
|
orphan_path(pp, reason);
|
||||||
|
--
|
||||||
|
2.17.2
|
||||||
|
|
1898
device-mapper-multipath.spec
Normal file
1898
device-mapper-multipath.spec
Normal file
File diff suppressed because it is too large
Load Diff
2
sources
Normal file
2
sources
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
SHA512 (multipath-tools-0.8.4.tgz) = 130308e61d6dce31085fc2763219f4df0f3ad9153e0e6e7a5a1c3c948a2305cff9413699025c28f9b81dd24d2a9263f9fa825253060e44232c3bb6600cd1f07f
|
||||||
|
SHA512 (multipath.conf) = 71953dce5a68adcf60a942305f5a66023e6f4c4baf53b1bfdb4edf65ed5b8e03db804363c36d1dcfd85591f4766f52b515269904c53b84d7b076da0b80b09942
|
1
tests/.fmf/version
Normal file
1
tests/.fmf/version
Normal file
@ -0,0 +1 @@
|
|||||||
|
1
|
675
tests/bindings/LICENSE
Normal file
675
tests/bindings/LICENSE
Normal file
@ -0,0 +1,675 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
|
7
tests/bindings/PURPOSE
Normal file
7
tests/bindings/PURPOSE
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
make sure modify /etc/multipath/bindings changes alias
|
||||||
|
|
||||||
|
steps:
|
||||||
|
1. edit the /etc/multipath/bindings
|
||||||
|
2. multipath -r
|
||||||
|
check if the mpath is changed
|
||||||
|
|
57
tests/bindings/main.sh
Executable file
57
tests/bindings/main.sh
Executable file
@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Author: Lin Li <lilin@redhat.com>
|
||||||
|
|
||||||
|
#set -x
|
||||||
|
source ../include/ec.sh || exit 200
|
||||||
|
|
||||||
|
tlog "running $0"
|
||||||
|
|
||||||
|
trun "service multipathd stop"
|
||||||
|
rpm -q device-mapper-multipath || yum install -y device-mapper-multipath
|
||||||
|
trun "mpathconf --enable --with_multipathd y --user_friendly_names y"
|
||||||
|
trun "service multipathd status"
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
trun "multipath -F"
|
||||||
|
sleep 5
|
||||||
|
terr "modprobe -r scsi_debug"
|
||||||
|
terr "modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 \
|
||||||
|
max_luns=2 no_lun_0=1"
|
||||||
|
sleep 60
|
||||||
|
|
||||||
|
disk_path=$(get_scsi_debug_devices)
|
||||||
|
disk=$(basename $disk_path)
|
||||||
|
mpath_name=$(get_mpath_disk_by_scsi_device $disk)
|
||||||
|
new_alias="mpath_test_$$"
|
||||||
|
|
||||||
|
trun "sed -i 's/$mpath_name/$new_alias/' /etc/multipath/bindings"
|
||||||
|
trun "multipath -r"
|
||||||
|
sleep 5
|
||||||
|
tok "[[ -b /dev/mapper/$new_alias ]]"
|
||||||
|
tok is_mpath $new_alias
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
trun "multipath -F"
|
||||||
|
sleep 5
|
||||||
|
trun "modprobe -r scsi_debug"
|
||||||
|
trun "service multipathd stop"
|
||||||
|
sleep 3
|
||||||
|
trun "multipath -W"
|
||||||
|
trun "rm /etc/multipath/bindings"
|
||||||
|
tend
|
675
tests/find_multipaths/LICENSE
Normal file
675
tests/find_multipaths/LICENSE
Normal file
@ -0,0 +1,675 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
|
49
tests/find_multipaths/Makefile
Normal file
49
tests/find_multipaths/Makefile
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Red Hat, Inc.
|
||||||
|
# #
|
||||||
|
# # This program is free software: you can redistribute it and/or modify
|
||||||
|
# # it under the terms of the GNU General Public License as published by
|
||||||
|
# # the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# # (at your option) any later version.
|
||||||
|
# #
|
||||||
|
# # This program is distributed in the hope that it will be useful,
|
||||||
|
# # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# # GNU General Public License for more details.
|
||||||
|
# #
|
||||||
|
# # You should have received a copy of the GNU General Public License
|
||||||
|
# # along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# # Author: Lin Li <lilin@redhat.com>
|
||||||
|
|
||||||
|
.PHONY: all install download clean
|
||||||
|
|
||||||
|
BUILT_FILES=
|
||||||
|
|
||||||
|
FILES=$(METADATA) Makefile PURPOSE main.sh
|
||||||
|
|
||||||
|
run: $(FILES) build
|
||||||
|
./main.sh
|
||||||
|
|
||||||
|
build: $(BUILT_FILES)
|
||||||
|
chmod a+x ./main.sh
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~ *.rpm $(BUILT_FILES)
|
||||||
|
|
||||||
|
include /usr/share/rhts/lib/rhts-make.include
|
||||||
|
|
||||||
|
$(METADATA): Makefile
|
||||||
|
@touch $(METADATA)
|
||||||
|
@echo "Owner: LiLin <lilin@redhat.com>" > $(METADATA)
|
||||||
|
@echo "Name: $(TEST)" >> $(METADATA)
|
||||||
|
@echo "Path: $(TEST_DIR)" >> $(METADATA)
|
||||||
|
@echo "License: GPLv3" >> $(METADATA)
|
||||||
|
@echo "TestVersion: $(TESTVERSION)" >> $(METADATA)
|
||||||
|
@echo "Description: find_multipaths" >> $(METADATA)
|
||||||
|
@echo "TestTime: 15m" >> $(METADATA)
|
||||||
|
@echo "RunFor: device-mapper-multipath" >> $(METADATA)
|
||||||
|
@echo "Requires: device-mapper-multipath" >> $(METADATA)
|
||||||
|
|
||||||
|
rhts-lint $(METADATA)
|
10
tests/find_multipaths/PURPOSE
Normal file
10
tests/find_multipaths/PURPOSE
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
testing environment:
|
||||||
|
1. enable|disable find_multipaths and do multipath reload
|
||||||
|
mpathconf --find_multipaths y|n --with_multipathd y
|
||||||
|
|
||||||
|
test cases:
|
||||||
|
1. find_multipaths = no
|
||||||
|
multipath will not blacklist the single devices
|
||||||
|
2. find_multipaths = yes
|
||||||
|
multipath will blacklist the single devices
|
||||||
|
multipath will not blacklist the non-single devices
|
94
tests/find_multipaths/main.sh
Executable file
94
tests/find_multipaths/main.sh
Executable file
@ -0,0 +1,94 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Author: Lin Li <lilin@redhat.com>
|
||||||
|
|
||||||
|
#set -x
|
||||||
|
source ../include/ec.sh || exit 200
|
||||||
|
|
||||||
|
tlog "running $0"
|
||||||
|
|
||||||
|
# which not set find_multipaths yes, so multipath always create a multipath device for single device
|
||||||
|
# so stop service and reconfig with --find_multipaths y, and reload/start the service again.
|
||||||
|
trun "service multipathd stop"
|
||||||
|
rpm -q device-mapper-multipath || yum install -y device-mapper-multipath
|
||||||
|
|
||||||
|
# test with find_multipath=y, will not multipath for the single device; reload/start the service to enable the config
|
||||||
|
trun "mpathconf --enable --user_friendly_names y --find_multipaths y --with_multipathd y"
|
||||||
|
trun "service multipathd status"
|
||||||
|
# use scsi_debug to simulate a drive
|
||||||
|
trun "multipath -F"
|
||||||
|
terr "modprobe -r scsi_debug"
|
||||||
|
trun "modprobe scsi_debug"
|
||||||
|
sleep 3
|
||||||
|
trun "multipath -W"
|
||||||
|
cat /etc/multipath/wwids
|
||||||
|
trun "multipath"
|
||||||
|
disk_path=$(get_scsi_debug_devices)
|
||||||
|
disk_node=$(basename $disk_path)
|
||||||
|
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
|
||||||
|
tok '[[ -z $mpath_name ]]'
|
||||||
|
|
||||||
|
# test with find_multipath=n, will multipath for the single device
|
||||||
|
trun "mpathconf --enable --user_friendly_names y --find_multipaths n --with_multipathd y"
|
||||||
|
sleep 5
|
||||||
|
trun "multipath"
|
||||||
|
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
|
||||||
|
tok "is_mpath $mpath_name"
|
||||||
|
|
||||||
|
# flush new created path
|
||||||
|
sleep 3
|
||||||
|
trun "multipath -F"
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
# test with find_multipath=y, A path has the same WWID as a multipath device that was previously created
|
||||||
|
trun "mpathconf --enable --user_friendly_names y --find_multipaths y --with_multipathd y"
|
||||||
|
sleep 5
|
||||||
|
trun "multipath"
|
||||||
|
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
|
||||||
|
tok "is_mpath $mpath_name"
|
||||||
|
|
||||||
|
# Clear wwid, test with find_multipath=y, will not multipath for the single device
|
||||||
|
trun "multipath -W"
|
||||||
|
trun "mpathconf --disable --with_multipathd y"
|
||||||
|
sleep 5
|
||||||
|
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
|
||||||
|
tok '[[ -z $mpath_name ]]'
|
||||||
|
|
||||||
|
trun "multipath -F"
|
||||||
|
sleep 5
|
||||||
|
trun "modprobe -r scsi_debug"
|
||||||
|
|
||||||
|
# test find_multipaths=y create device for paths have same wwid
|
||||||
|
tok "modprobe scsi_debug num_tgts=1 vpd_use_hostno=0 add_host=2 delay=20 max_luns=2 no_lun_0=1"
|
||||||
|
sleep 10
|
||||||
|
disk_paths=$(get_scsi_debug_devices)
|
||||||
|
disk_node=$(basename $disk_paths)
|
||||||
|
mpath_name=$(get_mpath_disk_by_scsi_device $disk_node)
|
||||||
|
tok "is_mpath $mpath_name"
|
||||||
|
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
trun "multipath -F"
|
||||||
|
sleep 5
|
||||||
|
trun "modprobe -r scsi_debug"
|
||||||
|
# remove the scsi_debug wwid
|
||||||
|
trun "service multipathd stop"
|
||||||
|
sleep 3
|
||||||
|
trun "multipath -W"
|
||||||
|
cat /etc/multipath/wwids
|
||||||
|
tend
|
256
tests/include/ec.sh
Executable file
256
tests/include/ec.sh
Executable file
@ -0,0 +1,256 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Author: Lin Li <lilin@redhat.com>
|
||||||
|
|
||||||
|
path=$(pwd)
|
||||||
|
source ../include/utils.sh || exit 1
|
||||||
|
source ../include/include.sh || exit 1
|
||||||
|
source ../include/tc.sh || exit 1
|
||||||
|
source ../include/mpath.sh || exit 1
|
||||||
|
source ../include/scsi_debug.sh || exit 1
|
||||||
|
|
||||||
|
#this script usually is only used by current case
|
||||||
|
#private global variables, lower case and no under line is okay
|
||||||
|
mpath=
|
||||||
|
|
||||||
|
function _isconfig (){
|
||||||
|
[ -z $mpath ] && return 2
|
||||||
|
Cmd "multipath -ll $mpath"
|
||||||
|
}
|
||||||
|
|
||||||
|
function _init (){
|
||||||
|
#will improve this function
|
||||||
|
#should return the multipathed disk created by scsi_debug, don't consider the other mutipathed disks
|
||||||
|
#olnly append the black list exception to /etc/multipath.conf not override
|
||||||
|
Setup_Multipath || Fail "failed to create multipathed device via scsi_debug"
|
||||||
|
mpath=$RETURN_STR
|
||||||
|
|
||||||
|
_isconfig
|
||||||
|
}
|
||||||
|
|
||||||
|
function _destroy (){
|
||||||
|
sleep 10
|
||||||
|
Cmd "multipath -F"
|
||||||
|
sleep 5
|
||||||
|
Cmd "modprobe -r scsi_debug"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Mutipath_installation()
|
||||||
|
# Usage:
|
||||||
|
# check if multipath starts, if not install it with yum
|
||||||
|
# Parameter:
|
||||||
|
# NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
function Multipath_installation (){
|
||||||
|
Cmd "rpm -qi device-mapper-multipath" && return 0
|
||||||
|
Cmd "yum install -y device-mapper-multipath"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Print_kernel_info()
|
||||||
|
# Usage:
|
||||||
|
# print the detail running kernel information.
|
||||||
|
# Parameter: # NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
function Print_kernel_info (){
|
||||||
|
Cmd "lsb_release -a"
|
||||||
|
Cmd "uname -a"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Print_multipath_pkginfo()()
|
||||||
|
# Usage:
|
||||||
|
# print the multipath pacakge information
|
||||||
|
# Parameter:
|
||||||
|
# NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
function Print_multipath_pkginfo (){
|
||||||
|
Cmd "rpm -qi device-mapper-multipath"
|
||||||
|
Cmd "rpm -qi kpartx"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Setup_Multipath ()
|
||||||
|
# Usage:
|
||||||
|
# return mpath_name if we have multipath devices, if not,
|
||||||
|
# we use scsi_debug to create a multipath device.
|
||||||
|
# Parameter:
|
||||||
|
# NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# RETURN_STR # $mpath_name_list, like "mpath0 mpath1"
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
|
||||||
|
function Setup_Multipath (){
|
||||||
|
RETURN_STR=''
|
||||||
|
local mpath_name_list=$(dmsetup table \
|
||||||
|
| perl -ne 'print "$1 " if /(mpath[a-z0-9]+):[0-9 ]+multipath.*/')
|
||||||
|
if [ "CHK${mpath_name_list}" != "CHK" ];then
|
||||||
|
mpath_name_list="$(echo ${mpath_name_list} | sed -e 's/ $//')"
|
||||||
|
echo "INFO: Found multipath devices: ${mpath_name_list}"
|
||||||
|
#RHEL 5 will disable some wwn mpath if we install OS with ondisk=mapper/mpath0
|
||||||
|
# option, so we need to enable them all
|
||||||
|
if [ "CHK$(uname -r | egrep "2\.6\.18.*el5")" != "CHK" ];then
|
||||||
|
cat << AA > /etc/multipath.conf
|
||||||
|
defaults {
|
||||||
|
user_friendly_names yes
|
||||||
|
}
|
||||||
|
blacklist {
|
||||||
|
device {
|
||||||
|
vendor .*
|
||||||
|
product .*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blacklist_exceptions {
|
||||||
|
device {
|
||||||
|
vendor Linux
|
||||||
|
product scsi_debug
|
||||||
|
}
|
||||||
|
device {
|
||||||
|
vendor IQSTOR
|
||||||
|
product .*
|
||||||
|
}
|
||||||
|
device {
|
||||||
|
vendor NETAPP
|
||||||
|
product .*
|
||||||
|
}
|
||||||
|
device {
|
||||||
|
vendor HITACHI
|
||||||
|
product .*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AA
|
||||||
|
service multipathd start
|
||||||
|
sleep 5s #multipathd return premature
|
||||||
|
multipath -r
|
||||||
|
multipathd -k'reconfigure'
|
||||||
|
sleep 5s
|
||||||
|
mpath_name_list=$(dmsetup table \
|
||||||
|
| perl -ne 'print "$1 " if /(mpath[a-z0-9]+):[0-9 ]+multipath.*/')
|
||||||
|
fi
|
||||||
|
if [ "CHK${mpath_name_list}" == "CHK" ];then
|
||||||
|
echo -n "FATAL: still no mulipath devices setup,"
|
||||||
|
echo " check code in Setup_Multipath()"
|
||||||
|
RETURN_STR=''
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
RETURN_STR="${mpath_name_list}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
#setup scsi_debug
|
||||||
|
echo "INFO: Loading scsi_debug module for simulation of mpath"
|
||||||
|
modprobe scsi_debug \
|
||||||
|
num_tgts=1 vpd_use_hostno=0 \
|
||||||
|
add_host=4 delay=20 \
|
||||||
|
max_luns=2 no_lun_0=1 2>&1 1>/dev/null
|
||||||
|
|
||||||
|
echo "INFO: Waiting for udev to create /dev/sdX"
|
||||||
|
sleep 15s #wait for udev to create /dev/sdX
|
||||||
|
rpm -q device-mapper-multipath 2>/dev/null 1>/dev/null
|
||||||
|
if [ $? -ne 0 ];then
|
||||||
|
echo "INFO: Installing device-mapper-multipath via yum"
|
||||||
|
yum -y install device-mapper-multipath
|
||||||
|
fi
|
||||||
|
#enable multipath for scsi_debug.
|
||||||
|
cat << AA > /etc/multipath.conf
|
||||||
|
defaults {
|
||||||
|
#Enable multibus is for mutlbus testing
|
||||||
|
path_grouping_policy multibus
|
||||||
|
user_friendly_names yes
|
||||||
|
}
|
||||||
|
blacklist {
|
||||||
|
device {
|
||||||
|
vendor .*
|
||||||
|
product .*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blacklist_exceptions {
|
||||||
|
device {
|
||||||
|
vendor Linux
|
||||||
|
product scsi_debug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AA
|
||||||
|
echo "INFO: /etc/multipath.conf updated"
|
||||||
|
cat /etc/multipath.conf
|
||||||
|
echo "INFO: Restarting multiapth and reload configuration"
|
||||||
|
service multipathd restart
|
||||||
|
sleep 5s #multipathd return premature
|
||||||
|
multipathd -k'reconfig'
|
||||||
|
sleep 5s
|
||||||
|
|
||||||
|
mpath_name_list=$(dmsetup table | perl -ne 'print "$1 " if /(mpath[a-z0-9]+):[0-9 ]+multipath.*/')
|
||||||
|
if [ "CHK${mpath_name_list}" != "CHK" ];then
|
||||||
|
mpath_name_list="$(echo ${mpath_name_list} | sed -e 's/ $//')"
|
||||||
|
echo "INFO: found mpath: ${mpath_name_list}"
|
||||||
|
RETURN_STR="${mpath_name_list}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
} #end of functoin Setup_Multipath
|
||||||
|
|
||||||
|
|
||||||
|
get_wwid_of_disk()
|
||||||
|
{
|
||||||
|
# we should not use scsi_id or /dev/disk/by-id to get the wwid
|
||||||
|
# since multipath could replace the white spaces of wwid if
|
||||||
|
# having white spaces. we should use
|
||||||
|
# multipathd show paths format %w %d
|
||||||
|
# to get the wwid
|
||||||
|
|
||||||
|
for dev in `ls /dev/disk/by-id/*`
|
||||||
|
do
|
||||||
|
if readlink $dev | grep -qw "$disk$"
|
||||||
|
then
|
||||||
|
wwid=$(basename $dev | sed 's/^[^-]*-//g')
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test X$wwid = X
|
||||||
|
then
|
||||||
|
wwid=$(/lib/udev/scsi_id --page=0x83 --whitelisted --device=/dev/$disk)
|
||||||
|
fi
|
||||||
|
echo $wwid
|
||||||
|
|
||||||
|
# multipathd_running || texit "multipathd is not running"
|
||||||
|
# local disk=$1
|
||||||
|
# local wwid=$(multipathd show paths format %d,%w | grep "^$disk\s*," | \
|
||||||
|
# awk -F, '{ print $2 }' | sed 's/\s//g')
|
||||||
|
# echo $wwid
|
||||||
|
}
|
||||||
|
|
124
tests/include/include.sh
Executable file
124
tests/include/include.sh
Executable file
@ -0,0 +1,124 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright (c) 2016 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Author: Lin Li <lilin@redhat.com>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
# Mp_Conf_Up_Def ()
|
||||||
|
# Usage:
|
||||||
|
# Update default section of /etc/multipath.conf, will also reload conf.
|
||||||
|
# Parameter:
|
||||||
|
# $config_change #config string want to change, like 'polling_interval 5'
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# Return string:
|
||||||
|
# NULL
|
||||||
|
#----------------------------------------------------------------------------#
|
||||||
|
|
||||||
|
function Mp_Conf_Up_Def (){
|
||||||
|
EX_USAGE=64 # Bad arg format
|
||||||
|
if [ $# -lt 1 ]; then
|
||||||
|
echo 'Usage: Mp_Conf_Up_Def $config_change'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
RETURN_STR=''
|
||||||
|
local multipath_conf_filename="/etc/multipath.conf"
|
||||||
|
local config_change="$1"
|
||||||
|
echo ${config_change}
|
||||||
|
if [ "CHK${config_change}" == "CHK" ];then
|
||||||
|
echo 'Usage: Mp_Conf_Up_Def $config_change'
|
||||||
|
exit "${EX_USAGE}"
|
||||||
|
fi
|
||||||
|
python2 -c "
|
||||||
|
import sys
|
||||||
|
sys.path.append('"${MP_INCLUDE_PATH}"')
|
||||||
|
from mpconf import *
|
||||||
|
update_df_section('""${config_change}""')
|
||||||
|
"
|
||||||
|
#TODO: we need to check configuration before we return 0
|
||||||
|
RETURN_STR=""
|
||||||
|
return 0
|
||||||
|
} #end of functoin Mp_Conf_Up_Def
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Print_multipath_pkginfo()()
|
||||||
|
# Usage:
|
||||||
|
# print the multipath pacakge information
|
||||||
|
# Parameter:
|
||||||
|
# NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
function Print_multipath_pkginfo (){
|
||||||
|
Cmd "rpm -qi device-mapper-multipath"
|
||||||
|
Cmd "rpm -qi kpartx"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Mutipathd_stop()
|
||||||
|
# Usage:
|
||||||
|
# check if multipathd stops, if not stop it
|
||||||
|
# Parameter:
|
||||||
|
# NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
function Multipathd_stop (){
|
||||||
|
# { ! Cmd pidof multipathd ; } || Cmd "service multipathd stop"
|
||||||
|
{ ! Cmd pidof multipathd ; } || Cmd "kill -9 `pidof multipathd`"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Mutipathd_start()
|
||||||
|
# Usage:
|
||||||
|
# check if multipathd is installed, if not start it
|
||||||
|
# Parameter:
|
||||||
|
# NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
function Multipathd_start (){
|
||||||
|
# { Cmd pidof multipathd ; } || Cmd "service multipathd start"
|
||||||
|
{ Cmd pidof multipathd ; } || Cmd "multipathd"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
# Mutipath_installation()
|
||||||
|
# Usage:
|
||||||
|
# check if multipath starts, if not install it with yum
|
||||||
|
# Parameter:
|
||||||
|
# NULL
|
||||||
|
# Returns:
|
||||||
|
# Return code:
|
||||||
|
# 0 on success
|
||||||
|
# 1 if something went wrong.
|
||||||
|
# ---------------------------------------------------------#
|
||||||
|
function Multipath_installation (){
|
||||||
|
Cmd "rpm -qi device-mapper-multipath" && return 0
|
||||||
|
Cmd "yum install -y device-mapper-multipath"
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user