device-mapper-multipath-0.8.4-2

Rebased on top of Martin Wilck's queue of ACKed upstream commits
  * https://github.com/openSUSE/multipath-tools/tree/upstream-queue
  * All previous patches have been reordered, with the exception of
    0011-libdmmp-Add-support-for-upcoming-json-c-0.14.0.patch
    which has been replaced with
    0029-fix-boolean-value-with-json-c-0.14.patch
Modify 0054-RH-add-mpathconf.patch
  * remove default enable_foreign and property blacklist_exceptions
    settings, and deal with the builtin default change from
    0031-libmultipath-set-enable_foreign-to-NONE-by-default.patch.
    Fixes bz #1853668
Add 0048-Makefile.inc-trim-extra-information-from-systemd-ver.patch
Add 0049-kpartx-fix-Wsign-compare-error.patch
  * The above two patches have been submitted upstream
This commit is contained in:
Benjamin Marzinski 2020-07-08 23:16:57 -05:00
parent c80b4a3ee2
commit 2b0cd7cceb
62 changed files with 4862 additions and 165 deletions

View File

@ -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

View File

@ -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(&paramp->private_buffer[buff_offset], &paramp->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(&paramp->private_buffer[buff_offset], &paramp->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(&paramp->private_buffer[buff_offset], &paramp->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

View File

@ -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

View File

@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 17 Mar 2020 17:28:24 -0500
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

View File

@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Sat, 21 Mar 2020 23:49:59 -0500
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

View File

@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 19 Mar 2020 22:17:51 -0500
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,

View File

@ -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

View File

@ -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

View File

@ -1,13 +1,12 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 12 May 2020 00:39:21 +0200
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: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile | 5 +++--

View File

@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Mon, 13 Apr 2020 19:22:02 +0200
Subject: [PATCH] libdmmp: Add support for upcoming json-c 0.14.0.
TRUE/FALSE are not defined anymore. 1 and 0 are used instead.
This is backwards compatible, as earlier versions of json-c are
using the same integer values in their present definitions.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libdmmp/libdmmp_private.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libdmmp/libdmmp_private.h b/libdmmp/libdmmp_private.h
index ac85b63f..4378962b 100644
--- a/libdmmp/libdmmp_private.h
+++ b/libdmmp/libdmmp_private.h
@@ -82,7 +82,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) != 1) { \
_error(ctx, "Invalid JSON output from multipathd IPC: " \
"key '%s' not found", key); \
rc = DMMP_ERR_IPC_ERROR; \
--
2.17.2

View File

@ -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

View File

@ -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

View File

@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 12 May 2020 00:39:24 +0200
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
@ -9,14 +9,13 @@ 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: Martin Wilck <mwilck@suse.com>
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 d4d1e0dd..9060ac9b 100644
index 671dd1ca..e7256e3a 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -91,7 +91,7 @@ TEST_CC_OPTION = $(shell \
@ -26,8 +25,8 @@ index d4d1e0dd..9060ac9b 100644
-WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered,)
+WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered -Wno-error=clobbered,)
OPTFLAGS = -O2 -g -pipe -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int \
-Werror=implicit-function-declaration -Werror=format-security \
OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int \
--
2.17.2

View File

@ -1,11 +1,10 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 12 May 2020 00:39:25 +0200
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: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 16 ++++++++--------

View File

@ -1,21 +1,34 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 12 May 2020 00:39:26 +0200
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: Martin Wilck <mwilck@suse.com>
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 +-
4 files changed, 18 insertions(+), 18 deletions(-)
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

View File

@ -1,13 +1,12 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 12 May 2020 00:39:27 +0200
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: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/dict.c | 11 +++++++----

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -1,13 +1,12 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 12 May 2020 22:38:22 +0200
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: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile | 4 ++++

View 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

View 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

View 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

View 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

View 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

View File

@ -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

View 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

View File

@ -1,6 +1,6 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 29 May 2020 15:13:59 -0500
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,

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View 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

View 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

View 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

View 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

View 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

View File

@ -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

View 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, &params);
+ if (dm_get_next_target(dmt, NULL, &start, &length,
+ &target_type, &params) != 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, &params[0]) &&
+ dm_get_map(names->name, &size, &params[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

View 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

View File

@ -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

View 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

View 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

View 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

View File

@ -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

View File

@ -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

View 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

View File

@ -15,7 +15,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 9060ac9b..034752d9 100644
index 8ea3352d..873fb62f 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -53,7 +53,7 @@ endif
@ -28,10 +28,10 @@ index 9060ac9b..034752d9 100644
udevrulesdir = $(libudevdir)/rules.d
multipathdir = $(TOPDIR)/libmultipath
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index 8f990494..8a3a1718 100644
index d7527d7d..0e0d70d5 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -32,6 +32,6 @@ LABEL="mpath_kpartx_end"
@@ -36,6 +36,6 @@ LABEL="mpath_kpartx_end"
GOTO="kpartx_end"
LABEL="run_kpartx"

View File

@ -19,10 +19,10 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
3 files changed, 10 insertions(+), 16 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 00e8dbdb..d9691b17 100644
index db58ccca..0c58aa32 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -204,12 +204,6 @@ setup_default_blist (struct config * conf)
@@ -187,12 +187,6 @@ setup_default_blist (struct config * conf)
if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
return 1;
@ -35,7 +35,7 @@ index 00e8dbdb..d9691b17 100644
vector_foreach_slot (conf->hwtable, hwe, i) {
if (hwe->bl_product) {
if (find_blacklist_device(conf->blist_device,
@@ -411,7 +405,8 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl,
@@ -394,7 +388,8 @@ filter_property(struct config *conf, struct udev_device *udev, int lvl,
*uid_attribute != '\0';
bool uid_attr_seen = false;
@ -46,10 +46,10 @@ index 00e8dbdb..d9691b17 100644
udev_device_get_properties_list_entry(udev)) {
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 05a5e8ff..3455b1cc 100644
index 5adaced6..42a192f6 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1286,9 +1286,14 @@ keywords. Both are regular expressions. For a full description of these keywords
@@ -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,
@ -65,7 +65,7 @@ index 05a5e8ff..3455b1cc 100644
.
.RS
.PP
@@ -1299,10 +1304,6 @@ Blacklisting by missing properties is only applied to devices which do have the
@@ -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.
@ -77,10 +77,10 @@ index 05a5e8ff..3455b1cc 100644
.TP
.B protocol
diff --git a/tests/blacklist.c b/tests/blacklist.c
index 6e7c1864..cc8a9a4a 100644
index d5c40898..d20e97af 100644
--- a/tests/blacklist.c
+++ b/tests/blacklist.c
@@ -271,7 +271,7 @@ static void test_property_missing(void **state)
@@ -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"),
@ -89,7 +89,7 @@ index 6e7c1864..cc8a9a4a 100644
assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"),
MATCH_NOTHING);
assert_int_equal(filter_property(&conf, &udev, 3, ""),
@@ -363,9 +363,7 @@ static void test_filter_path_missing1(void **state)
@@ -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;

View File

@ -20,7 +20,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
5 files changed, 20 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index b4d87689..b36778b0 100644
index 658bec8b..1c02e230 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -26,6 +26,7 @@
@ -53,7 +53,7 @@ index b4d87689..b36778b0 100644
conf->processed_main_config = 1;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index ceecff2d..3368d8c9 100644
index 92c61a0d..160867cd 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -9,6 +9,7 @@

View File

@ -9,26 +9,28 @@ still being generic.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 29 +++++++++++++++++++++--------
1 file changed, 21 insertions(+), 8 deletions(-)
Makefile.inc | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index 034752d9..c2abd301 100644
index 873fb62f..479523bc 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -89,16 +89,29 @@ TEST_CC_OPTION = $(shell \
@@ -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 -pipe -Wall -Werror=format-security \
+ -Wp,-D_FORTIFY_SOURCE=2 -fexceptions \
+ $(STACKPROT) -grecord-gcc-switches \
+ -fasynchronous-unwind-tables
+ 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
@ -36,24 +38,18 @@ index 034752d9..c2abd301 100644
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1
+ endif
+else
+ OPTFLAGS = $(RPM_OPT_FLAGS)
+ OPTFLAGS := $(RPM_OPT_FLAGS) --param=ssp-buffer-size=4
+endif
+OPTFLAGS += -Werror -Wextra -Wstrict-prototypes -Wformat=2 \
+ -Werror=implicit-int -Werror=implicit-function-declaration \
+ $(WNOCLOBBERED) \
+ -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
+ --param=ssp-buffer-size=4
-OPTFLAGS = -O2 -g -pipe -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
+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
CFLAGS := $(OPTFLAGS) -DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
-MMD -MP $(CFLAGS)
BIN_CFLAGS = -fPIE -DPIE
@@ -135,4 +148,4 @@ check_file = $(shell \
+ $(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 $?

View File

@ -14,14 +14,14 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 2 +
multipath/Makefile | 5 +
multipath/mpathconf | 555 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf | 565 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf.8 | 135 ++++++++++
4 files changed, 697 insertions(+)
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 b36778b0..26f8e050 100644
index 1c02e230..a253a936 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -781,6 +781,8 @@ load_config (char * file)
@ -69,10 +69,10 @@ index b9bbb3cf..e720c7f6 100644
$(RM) core *.o $(EXEC) *.gz
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 00000000..f34003c9
index 00000000..f0d09cbb
--- /dev/null
+++ b/multipath/mpathconf
@@ -0,0 +1,555 @@
@@ -0,0 +1,565 @@
+#!/bin/bash
+#
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
@ -107,11 +107,6 @@ index 00000000..f34003c9
+defaults {
+ user_friendly_names yes
+ find_multipaths yes
+ enable_foreign \"^$\"
+}
+
+blacklist_exceptions {
+ property \"(SCSI_IDENT_|ID_WWN)\"
+}"
+
+CONFIGFILE="/etc/multipath.conf"
@ -130,7 +125,7 @@ index 00000000..f34003c9
+ 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 y): --property_blacklist <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>"
@ -288,12 +283,13 @@ index 00000000..f34003c9
+
+function validate_args
+{
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" ]; then
+ 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'"
@ -311,7 +307,7 @@ index 00000000..f34003c9
+ echo "--enable_foreign must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" ]; then
+ 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
@ -416,8 +412,12 @@ index 00000000..f34003c9
+ 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" ; then
+ 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
+
@ -451,9 +451,11 @@ index 00000000..f34003c9
+ echo "default property blacklist is enabled"
+ fi
+ if [ -z "$HAVE_FOREIGN" -o "$HAVE_FOREIGN" = 0 ]; then
+ echo "enable_foreign is not set (all foreign multipath devices will be shown)"
+ 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
@ -570,7 +572,15 @@ index 00000000..f34003c9
+ CHANGED_CONFIG=1
+ fi
+elif [ "$PROPERTY" = "y" ]; then
+ if [ -z "$HAVE_PROPERTY" ]; 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
@ -582,18 +592,18 @@ index 00000000..f34003c9
+fi
+
+if [ "$FOREIGN" = "y" ]; then
+ if [ "$HAVE_FOREIGN" = 1 -o "$HAVE_FOREIGN" = 2 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*enable_foreign/# enable_foreign/' $TMPFILE
+ 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 [ -z "$HAVE_FOREIGN" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ enable_foreign "^$"
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_FOREIGN" = 0 -o "$HAVE_FOREIGN" = 2 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*#\?[[:space:]]*enable_foreign.*$/ enable_foreign "^$"/' $TMPFILE
+ 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

View File

@ -22,13 +22,13 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
5 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index 28a2150d..fab6fc8f 100644
index 61d9c39e..c7a16636 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -454,3 +454,47 @@ int op ## _wwid(const char *wwid) \
declare_failed_wwid_op(is_failed, false)
declare_failed_wwid_op(mark_failed, true)
declare_failed_wwid_op(unmark_failed, true)
@@ -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)
+{
@ -86,10 +86,10 @@ index 0c6ee54d..e32a0b0e 100644
enum {
WWID_IS_NOT_FAILED = 0,
diff --git a/multipath/main.c b/multipath/main.c
index cf9d2a28..78822ee1 100644
index 4c43314e..c73f6963 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -138,7 +138,7 @@ usage (char * progname)
@@ -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);
@ -98,7 +98,7 @@ index cf9d2a28..78822ee1 100644
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);
@@ -151,6 +151,8 @@ usage (char * 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"
@ -107,16 +107,16 @@ index cf9d2a28..78822ee1 100644
" -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"
@@ -907,7 +909,7 @@ main (int argc, char *argv[])
@@ -893,7 +895,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, ":aAdcChl::FfM:v:p:b:BrR:itTquUwW")) != EOF ) {
- 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;
@@ -977,6 +979,10 @@ main (int argc, char *argv[])
@@ -970,6 +972,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
@ -128,7 +128,7 @@ index cf9d2a28..78822ee1 100644
usage(argv[0]);
exit(RTVL_OK);
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 9cdd05a3..8befc45a 100644
index 5b29a5d9..0478f4e7 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.

View File

@ -81,10 +81,10 @@ index 0e9ea387..184d4b22 100644
declare_hw_handler(hwhandler, set_str)
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index d478b177..a184511b 100644
index 11a6168c..a7285a35 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -382,6 +382,19 @@ oom:
@@ -384,6 +384,19 @@ oom:
return NULL;
}

View File

@ -12,7 +12,7 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index e5ee6afe..52fe05b9 100644
index 01a501bd..984d8dd8 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -22,7 +22,7 @@

View File

@ -14,18 +14,18 @@ Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.inc b/Makefile.inc
index c2abd301..bb642931 100644
index 479523bc..e2f5d0dc 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -108,7 +108,7 @@ else
endif
OPTFLAGS += -Werror -Wextra -Wstrict-prototypes -Wformat=2 \
-Werror=implicit-int -Werror=implicit-function-declaration \
- $(WNOCLOBBERED) \
+ $(WNOCLOBBERED) -Wno-error=format-truncation \
-Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
--param=ssp-buffer-size=4
@@ -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

View File

@ -1,6 +1,6 @@
Name: device-mapper-multipath
Version: 0.8.4
Release: 1%{?dist}
Release: 2%{?dist}
Summary: Tools to manage multipath devices using device-mapper
License: GPLv2
URL: http://christophe.varoqui.free.fr/
@ -10,29 +10,66 @@ URL: http://christophe.varoqui.free.fr/
# curl "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;h=refs/tags/0.8.4;sf=tgz" -o multipath-tools-0.8.4.tgz
Source0: multipath-tools-0.8.4.tgz
Source1: multipath.conf
Patch0001:0001-libmultipath-assign-variable-to-make-gcc-happy.patch
Patch0002: 0002-libmutipath-don-t-close-fd-on-dm_lib_release.patch
Patch0003: 0003-libmultipath-allow-force-reload-with-no-active-paths.patch
Patch0004: 0004-libmpathpersist-depend-on-libmultipath.patch
Patch0005: 0005-multipath-tools-Makefile-more-dependency-fixes-for-p.patch
Patch0006: 0006-multipath-tools-Makefile.inc-set-Wno-error-clobbered.patch
Patch0007: 0007-libmultipath-discovery.c-use-z-qualifier-for-size_t.patch
Patch0008: 0008-libmultipath-eliminate-more-signed-unsigned-comparis.patch
Patch0009: 0009-libmultipath-set_uint-fix-parsing-for-32bit.patch
Patch0010: 0010-multipath-tools-Makefile-add-install-dependency.patch
Patch0011: 0011-libdmmp-Add-support-for-upcoming-json-c-0.14.0.patch
Patch0012: 0012-libmultipath-fix-condlog-NULL-argument-in-uevent_get.patch
Patch0013: 0013-RH-fixup-udev-rules-for-redhat.patch
Patch0014: 0014-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0015: 0015-RH-don-t-start-without-a-config-file.patch
Patch0016: 0016-RH-use-rpm-optflags-if-present.patch
Patch0017: 0017-RH-add-mpathconf.patch
Patch0018: 0018-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0019: 0019-RH-warn-on-invalid-regex-instead-of-failing.patch
Patch0020: 0020-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0021: 0021-RH-Fix-nvme-compilation-warning.patch
Patch0022: 0022-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0023: 0023-RH-work-around-gcc-10-format-truncation-issue.patch
Patch0001: 0001-libmpathpersist-limit-PRIN-allocation-length-to-8192.patch
Patch0002: 0002-libmpathpersist-format_transportids-avoid-PROUT-over.patch
Patch0003: 0003-libmpathpersist-mpath_format_readfullstatus-use-real.patch
Patch0004: 0004-libmultipath-assign-variable-to-make-gcc-happy.patch
Patch0005: 0005-libmutipath-don-t-close-fd-on-dm_lib_release.patch
Patch0006: 0006-libmultipath-allow-force-reload-with-no-active-paths.patch
Patch0007: 0007-kpartx.rules-honor-DM_UDEV_DISABLE_OTHER_RULES_FLAG.patch
Patch0008: 0008-kpartx.rules-check-for-skip_kpartx-on-synthetic-ueve.patch
Patch0009: 0009-libmpathpersist-depend-on-libmultipath.patch
Patch0010: 0010-multipath-tools-Makefile-more-dependency-fixes-for-p.patch
Patch0011: 0011-multipath-tools-Makefile.inc-separate-out-OPTFLAGS.patch
Patch0012: 0012-multipath-tools-Makefile.inc-allow-user-settings-for.patch
Patch0013: 0013-multipath-tools-Makefile.inc-set-Wno-error-clobbered.patch
Patch0014: 0014-libmultipath-discovery.c-use-z-qualifier-for-size_t.patch
Patch0015: 0015-libmultipath-eliminate-more-signed-unsigned-comparis.patch
Patch0016: 0016-libmultipath-set_uint-fix-parsing-for-32bit.patch
Patch0017: 0017-multipath-tools-tests-Makefile-add-lmpathcmd-to-LIBD.patch
Patch0018: 0018-multipath-tools-tests-Makefile-Fix-OBJDEPS-for-hwtab.patch
Patch0019: 0019-multipath-tools-tests-test-lib.c-drop-__wrap_is_clai.patch
Patch0020: 0020-multipath-tools-tests-directio-fix-Wmaybe-uninitaliz.patch
Patch0021: 0021-libmultipath-move-libsg-into-libmultipath.patch
Patch0022: 0022-multipath-tools-Makefile-add-install-dependency.patch
Patch0023: 0023-libmultipath-make-libmp_dm_init-optional.patch
Patch0024: 0024-libmultipath-make-sysfs_is_multipathed-able-to-retur.patch
Patch0025: 0025-multipath-centralize-validation-code.patch
Patch0026: 0026-Unit-tests-for-is_path_valid.patch
Patch0027: 0027-libmultipath-simplify-failed-wwid-code.patch
Patch0028: 0028-libmultipath-use-atomic-linkat-in-mark_failed_wwid.patch
Patch0029: 0029-fix-boolean-value-with-json-c-0.14.patch
Patch0030: 0030-libmultipath-fix-condlog-NULL-argument-in-uevent_get.patch
Patch0031: 0031-libmultipath-set-enable_foreign-to-NONE-by-default.patch
Patch0032: 0032-multipath-add-e-option-to-enable-foreign-libraries.patch
Patch0033: 0033-libmultipath-remove-_blacklist_exceptions-functions.patch
Patch0034: 0034-libmultipath-fix-parser-issue-with-comments-in-strin.patch
Patch0035: 0035-libmultipath-invert-regexes-that-start-with-exclamat.patch
Patch0036: 0036-multipath-Fix-compiler-warnings-when-built-without-s.patch
Patch0037: 0037-libmultipath-fix-sysfs-dev_loss_tmo-parsing.patch
Patch0038: 0038-kpartx-read-devices-with-direct-IO.patch
Patch0039: 0039-kpartx-handle-alternate-bsd-disklabel-location.patch
Patch0040: 0040-libmultipath-fix-checker-detection-for-nvme-devices.patch
Patch0041: 0041-libmultipath-make-dm_get_map-status-return-codes-sym.patch
Patch0042: 0042-multipathd-fix-check_path-errors-with-removed-map.patch
Patch0043: 0043-libmultipath-make-dm_flush_maps-only-return-0-on-suc.patch
Patch0044: 0044-multipathd-add-del-maps-multipathd-command.patch
Patch0045: 0045-multipath-make-flushing-maps-work-like-other-command.patch
Patch0046: 0046-multipath-delegate-flushing-maps-to-multipathd.patch
Patch0047: 0047-multipath-add-option-to-skip-multipathd-delegation.patch
Patch0048: 0048-Makefile.inc-trim-extra-information-from-systemd-ver.patch
Patch0049: 0049-kpartx-fix-Wsign-compare-error.patch
Patch0050: 0050-RH-fixup-udev-rules-for-redhat.patch
Patch0051: 0051-RH-Remove-the-property-blacklist-exception-builtin.patch
Patch0052: 0052-RH-don-t-start-without-a-config-file.patch
Patch0053: 0053-RH-use-rpm-optflags-if-present.patch
Patch0054: 0054-RH-add-mpathconf.patch
Patch0055: 0055-RH-add-wwids-from-kernel-cmdline-mpath.wwids-with-A.patch
Patch0056: 0056-RH-warn-on-invalid-regex-instead-of-failing.patch
Patch0057: 0057-RH-reset-default-find_mutipaths-value-to-off.patch
Patch0058: 0058-RH-Fix-nvme-compilation-warning.patch
Patch0059: 0059-RH-attempt-to-get-ANA-info-via-sysfs-first.patch
Patch0060: 0060-RH-work-around-gcc-10-format-truncation-issue.patch
# runtime
Requires: %{name}-libs = %{version}-%{release}
@ -227,8 +264,24 @@ fi
%{_pkgconfdir}/libdmmp.pc
%changelog
* Wed Jul 8 2020 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.4-2
- Rebased on top of Martin Wilck's queue of ACKed upstream commits
* https://github.com/openSUSE/multipath-tools/tree/upstream-queue
* All previous patches have been reordered, with the exception of
0011-libdmmp-Add-support-for-upcoming-json-c-0.14.0.patch
which has been replaced with
0029-fix-boolean-value-with-json-c-0.14.patch
- Modify 0054-RH-add-mpathconf.patch
* remove default enable_foreign and property blacklist_exceptions
settings, and deal with the builtin default change from
0031-libmultipath-set-enable_foreign-to-NONE-by-default.patch.
Fixes bz #1853668
- Add 0048-Makefile.inc-trim-extra-information-from-systemd-ver.patch
- Add 0049-kpartx-fix-Wsign-compare-error.patch
* The above two patches have been submitted upstream
* Fri May 29 2020 Benjamin Marzinski <bmarzins@redhat.com> - 0.8.4-1
- Update Source to upstream version 0.8.2
- Update Source to upstream version 0.8.4
* Previoud patches 0001-0020 & 0031 are included in this commit
- Rename files
* Previous patches 0021-0032 are now patches 0012-0022
@ -509,7 +562,7 @@ fi
- Rename files
* Previous patches 0007-0014 are now patches 0008-0015
* Tue Apr 02 2018 Björn Esser <besser82@fedoraproject.org> - 0.7.6-1.git1cb704b
* Mon Apr 02 2018 Benjamin Marzinski <bmarzins@redhat.com> 0.7.6-1.git1cb704b
- Update Source to the latest upstream commit
* Previous patches 0001-0014 are included in this commit
* Previous patches 0015-0022 are now patches 0007-0014