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