import device-mapper-multipath-0.8.6-7.el9

This commit is contained in:
CentOS Sources 2021-11-03 23:04:41 -04:00 committed by Stepan Oksanichenko
commit 9ddf9f007a
26 changed files with 4351 additions and 0 deletions

View File

@ -0,0 +1 @@
a8afc76e75aeaba7e21c066ca95e236be3bfc5b4 SOURCES/multipath-tools-0.8.6.tgz

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/multipath-tools-0.8.6.tgz

View File

@ -0,0 +1,63 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 13 Apr 2017 07:22:23 -0500
Subject: [PATCH] RH: fixup udev rules for redhat
The multipath rules need to run after scsi_id is run. This means moving
them after 60-persistent-storage.rules for redhat. Redhat also uses a
different naming scheme for partitions than SuSE.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 2 +-
kpartx/kpartx.rules | 2 +-
multipath/Makefile | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index f1e23131..c593fd3b 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -55,7 +55,7 @@ endif
prefix =
exec_prefix = $(prefix)
usr_prefix = $(prefix)
-bindir = $(exec_prefix)/sbin
+bindir = $(exec_prefix)/usr/sbin
libudevdir = $(prefix)/$(SYSTEMDPATH)/udev
udevrulesdir = $(libudevdir)/rules.d
multipathdir = $(TOPDIR)/libmultipath
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index d7527d7d..0e0d70d5 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -36,6 +36,6 @@ LABEL="mpath_kpartx_end"
GOTO="kpartx_end"
LABEL="run_kpartx"
-RUN+="/sbin/kpartx -un -p -part /dev/$name"
+RUN+="/sbin/kpartx -un /dev/$name"
LABEL="kpartx_end"
diff --git a/multipath/Makefile b/multipath/Makefile
index 0828a8f7..b9bbb3cf 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -24,7 +24,7 @@ install:
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
- $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
@@ -33,7 +33,7 @@ install:
uninstall:
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
- $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz

View File

@ -0,0 +1,101 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 2 Jul 2014 12:49:53 -0500
Subject: [PATCH] RH: Remove the property blacklist exception builtin
Multipath set the default property blacklist exceptions to
(ID_SCSI_VPD|ID_WWN). This has the effect of blacklisting some internal
devices. These devices may never have multiple paths, but it is nice
to be able to set multipath up on them all the same. This patch simply
removes the default, and makes it so that if no property
blacklist_exception is given, then devices aren't failed for not matching
it.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/blacklist.c | 6 ++----
multipath/multipath.conf.5 | 11 ++++++-----
tests/blacklist.c | 7 ++-----
3 files changed, 10 insertions(+), 14 deletions(-)
diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
index 6c6a5979..785f5ee9 100644
--- a/libmultipath/blacklist.c
+++ b/libmultipath/blacklist.c
@@ -201,9 +201,6 @@ setup_default_blist (struct config * conf)
if (store_ble(conf->blist_devnode, "!^(sd[a-z]|dasd[a-z]|nvme[0-9])", ORIGIN_DEFAULT))
return 1;
- if (store_ble(conf->elist_property, "(SCSI_IDENT_|ID_WWN)", ORIGIN_DEFAULT))
- return 1;
-
vector_foreach_slot (conf->hwtable, hwe, i) {
if (hwe->bl_product) {
if (find_blacklist_device(conf->blist_device,
@@ -407,7 +404,8 @@ filter_property(const struct config *conf, struct udev_device *udev,
*uid_attribute != '\0';
bool uid_attr_seen = false;
- r = MATCH_PROPERTY_BLIST_MISSING;
+ if (VECTOR_SIZE(conf->elist_property))
+ r = MATCH_PROPERTY_BLIST_MISSING;
udev_list_entry_foreach(list_entry,
udev_device_get_properties_list_entry(udev)) {
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 064e4826..0d2bce09 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1347,9 +1347,14 @@ keywords. Both are regular expressions. For a full description of these keywords
Regular expression for an udev property. All
devices that have matching udev properties will be excluded/included.
The handling of the \fIproperty\fR keyword is special,
-because devices \fBmust\fR have at least one whitelisted udev property;
+because if a property blacklist_exception is set, devices \fBmust\fR have at
+least one whitelisted udev property;
otherwise they're treated as blacklisted, and the message
"\fIblacklisted, udev property missing\fR" is displayed in the logs.
+For example, setting the property blacklist_exception to
+\fB(SCSI_IDENT_|ID_WWN)\fR, will cause well-behaved SCSI devices and devices
+that provide a WWN (World Wide Number) to be included, and all others to be
+excluded. This works to exclude most non-multipathable devices.
.
.RS
.PP
@@ -1360,10 +1365,6 @@ Blacklisting by missing properties is only applied to devices which do have the
property specified by \fIuid_attribute\fR (e.g. \fIID_SERIAL\fR)
set. Previously, it was applied to every device, possibly causing devices to be
blacklisted because of temporary I/O error conditions.
-.PP
-The default \fIblacklist exception\fR is: \fB(SCSI_IDENT_|ID_WWN)\fR, causing
-well-behaved SCSI devices and devices that provide a WWN (World Wide Number)
-to be included, and all others to be excluded.
.RE
.TP
.B protocol
diff --git a/tests/blacklist.c b/tests/blacklist.c
index 882aa3a1..6a22b660 100644
--- a/tests/blacklist.c
+++ b/tests/blacklist.c
@@ -375,9 +375,8 @@ static void test_property_missing(void **state)
{
static struct udev_device udev = { "sdb", { "ID_FOO", "ID_BAZ", "ID_BAR", "ID_SERIAL", NULL } };
conf.blist_property = blist_property_wwn;
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
assert_int_equal(filter_property(&conf, &udev, 3, "ID_SERIAL"),
- MATCH_PROPERTY_BLIST_MISSING);
+ MATCH_NOTHING);
assert_int_equal(filter_property(&conf, &udev, 3, "ID_BLAH"),
MATCH_NOTHING);
assert_int_equal(filter_property(&conf, &udev, 3, ""),
@@ -469,9 +468,7 @@ static void test_filter_path_missing1(void **state)
conf.blist_device = blist_device_foo_bar;
conf.blist_protocol = blist_protocol_fcp;
conf.blist_wwid = blist_wwid_xyzzy;
- expect_condlog(3, "sdb: blacklisted, udev property missing\n");
- assert_int_equal(filter_path(&conf, &miss1_pp),
- MATCH_PROPERTY_BLIST_MISSING);
+ assert_int_equal(filter_path(&conf, &miss1_pp), MATCH_NOTHING);
}
/* This one matches the property whitelist, to test the other missing

View File

@ -0,0 +1,94 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 15 Oct 2014 10:39:30 -0500
Subject: [PATCH] RH: don't start without a config file
If /etc/multipath.conf doesn't exist, don't start multipathd and blacklist
all devices when running multipath. A completely blank configuration file
is almost never what users want. Also, people may have the multipath
packages installed but don't want to use them. This patch provides a
simple way to disable multipath. Simply removing or renaming
/etc/multipath.conf will keep multipath from doing anything.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 13 +++++++++++++
libmultipath/config.h | 1 +
multipath/multipath.rules | 1 +
multipathd/multipathd.8 | 2 ++
multipathd/multipathd.service | 1 +
5 files changed, 18 insertions(+)
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 30046a17..5f35c3d3 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -895,6 +895,19 @@ int _init_config (const char *file, struct config *conf)
goto out;
}
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
+ } else {
+ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ if (conf->blist_devnode == NULL) {
+ conf->blist_devnode = vector_alloc();
+ if (!conf->blist_devnode) {
+ condlog(0, "cannot allocate blacklist\n");
+ goto out;
+ }
+ }
+ if (store_ble(conf->blist_devnode, ".*", ORIGIN_NO_CONFIG)) {
+ condlog(0, "cannot store default no-config blacklist\n");
+ goto out;
+ }
}
conf->processed_main_config = 1;
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 933fe0d1..5f01c1fc 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -9,6 +9,7 @@
#define ORIGIN_DEFAULT 0
#define ORIGIN_CONFIG 1
+#define ORIGIN_NO_CONFIG 2
enum devtypes {
DEV_NONE,
diff --git a/multipath/multipath.rules b/multipath/multipath.rules
index 9df11a95..0486bf70 100644
--- a/multipath/multipath.rules
+++ b/multipath/multipath.rules
@@ -9,6 +9,7 @@ IMPORT{cmdline}="nompath"
ENV{nompath}=="?*", GOTO="end_mpath"
IMPORT{cmdline}="multipath"
ENV{multipath}=="off", GOTO="end_mpath"
+TEST!="/etc/multipath.conf", GOTO="end_mpath"
ENV{DEVTYPE}!="partition", GOTO="test_dev"
IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH"
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index 048a838d..8bd47a80 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -39,6 +39,8 @@ map regains its maximum performance and redundancy.
This daemon executes the external \fBmultipath\fR tool when events occur.
In turn, the multipath tool signals the multipathd daemon when it is done with
devmap reconfiguration, so that it can refresh its failed path list.
+
+In this Linux distribution, multipathd does not run unless a /etc/multipath.conf file exists.
.
.
.\" ----------------------------------------------------------------------------
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index 7d547fa7..af592057 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -4,6 +4,7 @@ Wants=systemd-udev-trigger.service systemd-udev-settle.service
Before=iscsi.service iscsid.service lvm2-activation-early.service
Before=local-fs-pre.target blk-availability.service shutdown.target
After=multipathd.socket systemd-udev-trigger.service systemd-udev-settle.service
+ConditionPathExists=/etc/multipath.conf
DefaultDependencies=no
Conflicts=shutdown.target
ConditionKernelCommandLine=!nompath

View File

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 25 Jan 2019 14:54:56 -0600
Subject: [PATCH] RH: Fix nvme function missing argument
A future patch will change the compilation options to error when
function declarations have unspecified arguments.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/nvme/argconfig.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/nvme/argconfig.h b/libmultipath/nvme/argconfig.h
index adb192b6..bfd10ef8 100644
--- a/libmultipath/nvme/argconfig.h
+++ b/libmultipath/nvme/argconfig.h
@@ -76,7 +76,7 @@ struct argconfig_commandline_options {
extern "C" {
#endif
-typedef void argconfig_help_func();
+typedef void argconfig_help_func(void);
void argconfig_append_usage(const char *str);
void argconfig_print_help(const char *program_desc,
const struct argconfig_commandline_options *options);

View File

@ -0,0 +1,57 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Wed, 19 Apr 2017 06:10:01 -0500
Subject: [PATCH] RH: use rpm optflags if present
Use the passed in optflags when compiling as an RPM, and keep the
default flags as close as possible to the current fedora flags, while
still being generic.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
Makefile.inc | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/Makefile.inc b/Makefile.inc
index c593fd3b..87fb39f2 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -92,15 +92,27 @@ TEST_CC_OPTION = $(shell \
echo "$(2)"; \
fi)
-STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
ERROR_DISCARDED_QUALIFIERS := $(call TEST_CC_OPTION,-Werror=discarded-qualifiers,)
WNOCLOBBERED := $(call TEST_CC_OPTION,-Wno-clobbered -Wno-error=clobbered,)
-OPTFLAGS := -O2 -g $(STACKPROT) --param=ssp-buffer-size=4
-WARNFLAGS := -Werror -Wall -Wextra -Wformat=2 -Werror=implicit-int \
+ifndef RPM_OPT_FLAGS
+ STACKPROT := $(call TEST_CC_OPTION,-fstack-protector-strong,-fstack-protector)
+ OPTFLAGS := -O2 -g -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions \
+ $(STACKPROT) -grecord-gcc-switches \
+ -fasynchronous-unwind-tables --param=ssp-buffer-size=4
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-hardened-cc1 && echo 1),1)
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1
+ endif
+ ifeq ($(shell test -f /usr/lib/rpm/redhat/redhat-annobin-cc1 && echo 1),1)
+ OPTFLAGS += -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1
+ endif
+else
+ OPTFLAGS := $(RPM_OPT_FLAGS) --param=ssp-buffer-size=4
+endif
+WARNFLAGS := -Werror -Wextra -Wformat=2 -Werror=implicit-int \
-Werror=implicit-function-declaration -Werror=format-security \
- $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS)
-CPPFLAGS := -Wp,-D_FORTIFY_SOURCE=2
+ $(WNOCLOBBERED) -Werror=cast-qual $(ERROR_DISCARDED_QUALIFIERS) \
+ -Wstrict-prototypes
CFLAGS := --std=gnu99 $(CFLAGS) $(OPTFLAGS) $(WARNFLAGS) -pipe \
-DBIN_DIR=\"$(bindir)\" -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\" \
-MMD -MP
@@ -138,4 +150,4 @@ check_file = $(shell \
%.o: %.c
@echo building $@ because of $?
- $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+ $(CC) $(CFLAGS) -c -o $@ $<

View File

@ -0,0 +1,771 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 16 Oct 2014 15:49:01 -0500
Subject: [PATCH] RH: add mpathconf
mpathconf is a program (largely based on lvmcomf) to help users
configure /etc/multipath.conf and enable or disable multipathing. It
has a couple of built-in options that can be set directly from the
command line. But, mostly it is used to get a multipath.conf file
with the OS defaults, and to enable and disable multipathing via
a single command.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/config.c | 2 +
multipath/Makefile | 5 +
multipath/mpathconf | 555 ++++++++++++++++++++++++++++++++++++++++++
multipath/mpathconf.8 | 135 ++++++++++
4 files changed, 697 insertions(+)
create mode 100644 multipath/mpathconf
create mode 100644 multipath/mpathconf.8
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 5f35c3d3..cee3bbb7 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -897,6 +897,8 @@ int _init_config (const char *file, struct config *conf)
factorize_hwtable(conf->hwtable, builtin_hwtable_size, file);
} else {
condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices.");
+ condlog(0, "You can run \"/sbin/mpathconf --enable\" to create");
+ condlog(0, "/etc/multipath.conf. See man mpathconf(8) for more details");
if (conf->blist_devnode == NULL) {
conf->blist_devnode = vector_alloc();
if (!conf->blist_devnode) {
diff --git a/multipath/Makefile b/multipath/Makefile
index b9bbb3cf..e720c7f6 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -18,10 +18,12 @@ $(EXEC): $(OBJS) $(multipathdir)/libmultipath.so $(mpathcmddir)/libmpathcmd.so
$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) $(LIBDEPS)
$(GZIP) $(EXEC).8 > $(EXEC).8.gz
$(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
+ $(GZIP) mpathconf.8 > mpathconf.8.gz
install:
$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+ $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/
$(INSTALL_PROGRAM) -d $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)$(udevrulesdir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).rules $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
@@ -29,13 +31,16 @@ install:
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(man8dir)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
+ $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(man8dir)
uninstall:
$(RM) $(DESTDIR)$(bindir)/$(EXEC)
$(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
$(RM) $(DESTDIR)$(libudevdir)/rules.d/62-multipath.rules
+ $(RM) $(DESTDIR)$(bindir)/mpathconf
$(RM) $(DESTDIR)$(man8dir)/$(EXEC).8.gz
$(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
+ $(RM) $(DESTDIR)$(man8dir)/mpathconf.8.gz
clean: dep_clean
$(RM) core *.o $(EXEC) *.gz
diff --git a/multipath/mpathconf b/multipath/mpathconf
new file mode 100644
index 00000000..2f4f3eaf
--- /dev/null
+++ b/multipath/mpathconf
@@ -0,0 +1,555 @@
+#!/bin/bash
+#
+# Copyright (C) 2010 Red Hat, Inc. All rights reserved.
+#
+# This file is part of the device-mapper-multipath package.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#
+# Simple editting of /etc/multipath.conf
+# This program was largely ripped off from lvmconf
+#
+
+unset ENABLE FIND FRIENDLY PROPERTY FOREIGN MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_PROPERTY HAVE_FOREIGN HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST
+
+DEFAULT_CONFIG="# device-mapper-multipath configuration file
+
+# For a complete list of the default configuration values, run either:
+# # multipath -t
+# or
+# # multipathd show config
+
+# For a list of configuration options with descriptions, see the
+# multipath.conf man page.
+
+defaults {
+ user_friendly_names yes
+ find_multipaths yes
+ enable_foreign \"^$\"
+}
+
+blacklist_exceptions {
+ property \"(SCSI_IDENT_|ID_WWN)\"
+}"
+
+CONFIGFILE="/etc/multipath.conf"
+OUTPUTFILE="/etc/multipath.conf"
+MULTIPATHDIR="/etc/multipath"
+TMPFILE="/etc/multipath/.multipath.conf.tmp"
+WWIDS=0
+
+function usage
+{
+ echo "usage: $0 <command>"
+ echo ""
+ echo "Commands:"
+ echo "Enable: --enable "
+ echo "Disable: --disable"
+ echo "Only allow certain wwids (instead of enable): --allow <WWID>"
+ echo "Set user_friendly_names (Default y): --user_friendly_names <y|n>"
+ echo "Set find_multipaths (Default y): --find_multipaths <yes|no|strict|greedy|smart>"
+ echo "Set default property blacklist (Default y): --property_blacklist <y|n>"
+ echo "Set enable_foreign to show foreign devices (Default n): --enable_foreign <y|n>"
+ echo "Load the dm-multipath modules on enable (Default y): --with_module <y|n>"
+ echo "start/stop/reload multipathd (Default n): --with_multipathd <y|n>"
+ echo "select output file (Default /etc/multipath.conf): --outfile <FILE>"
+ echo ""
+}
+
+function add_wwid
+{
+ INDEX=0
+ while [ "$INDEX" -lt "$WWIDS" ] ; do
+ if [ "$1" = "${WWID_LIST[$INDEX]}" ] ; then
+ return
+ fi
+ ((INDEX++))
+ done
+ WWID_LIST[$WWIDS]="$1"
+ ((WWIDS++))
+}
+
+function get_dm_deps
+{
+ shift 3
+ while [ -n "$1" -a -n "$2" ]; do
+ MAJOR=$(echo $1 | tr -d '(,')
+ MINOR=$(echo $2 | tr -d ')')
+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null`
+ if [ -n "$UUID" ] ; then
+ set_dm_wwid $UUID
+ fi
+ shift 2
+ done
+}
+
+function set_dm_wwid
+{
+ if [[ "$1" =~ ^part[[:digit:]]+-mpath- ]] ; then
+ add_wwid "${1##part*-mpath-}"
+ elif [[ "$1" =~ ^mpath- ]] ; then
+ add_wwid "${1##mpath-}"
+ else
+ get_dm_deps `dmsetup deps -u $1`
+ fi
+}
+
+function set_wwid
+{
+ UUID=""
+ if [[ "$1" =~ ^[[:digit:]]+:[[:digit:]]+$ ]] ; then
+ MAJOR=${1%%:*}
+ MINOR=${1##*:}
+ UUID=`dmsetup info -c --noheadings -o uuid -j $MAJOR -m $MINOR 2> /dev/null`
+ else
+ UUID=`dmsetup info -c --noheadings -o uuid $1 2> /dev/null`
+ fi
+ if [ -n "$UUID" ] ; then
+ set_dm_wwid $UUID
+ else
+ add_wwid "$1"
+ fi
+}
+
+function parse_args
+{
+ while [ -n "$1" ]; do
+ case $1 in
+ --enable)
+ ENABLE=1
+ shift
+ ;;
+ --disable)
+ ENABLE=0
+ shift
+ ;;
+ --allow)
+ ENABLE=2
+ if [ -n "$2" ]; then
+ set_wwid $2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --user_friendly_names)
+ if [ -n "$2" ]; then
+ FRIENDLY=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --find_multipaths)
+ if [ -n "$2" ]; then
+ FIND=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --property_blacklist)
+ if [ -n "$2" ]; then
+ PROPERTY=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --enable_foreign)
+ if [ -n "$2" ]; then
+ FOREIGN=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --with_module)
+ if [ -n "$2" ]; then
+ MODULE=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --with_multipathd)
+ if [ -n "$2" ]; then
+ MULTIPATHD=$2
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ --outfile)
+ if [ -n "$2" ]; then
+ OUTPUTFILE=$2
+ HAVE_OUTFILE=1
+ shift 2
+ else
+ usage
+ exit 1
+ fi
+ ;;
+ *)
+ usage
+ exit
+ esac
+ done
+}
+
+function validate_args
+{
+ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$PROPERTY" -o -n "$MODULE" ]; then
+ echo "ignoring extra parameters on disable"
+ FRIENDLY=""
+ FIND=""
+ PROPERTY=""
+ MODULE=""
+ fi
+ if [ -n "$FRIENDLY" ] && [ "$FRIENDLY" != "y" -a "$FRIENDLY" != "n" ]; then
+ echo "--user_friendly_names must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ "$FIND" = "y" ]; then
+ FIND="yes"
+ elif [ "$FIND" = "n" ]; then
+ FIND="no"
+ elif [ -n "$FIND" ] && [ "$FIND" != "yes" -a "$FIND" != "no" -a "$FIND" != "strict" -a "$FIND" != "greedy" -a "$FIND" != "smart" ]; then
+ echo "--find_multipaths must be one of 'yes' 'no' 'strict' 'greedy' or 'smart'"
+ exit 1
+ fi
+ if [ -n "$PROPERTY" ] && [ "$PROPERTY" != "y" -a "$PROPERTY" != "n" ]; then
+ echo "--property_blacklist must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ -n "$FOREIGN" ] && [ "$FOREIGN" != "y" -a "$FOREIGN" != "n" ]; then
+ echo "--enable_foreign must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" -a -z "$PROPERTY" ]; then
+ SHOW_STATUS=1
+ fi
+ if [ -n "$MODULE" ] && [ "$MODULE" != "y" -a "$MODULE" != "n" ]; then
+ echo "--with_module must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ -n "$MULTIPATHD" ] && [ "$MULTIPATHD" != "y" -a "$MULTIPATHD" != "n" ]; then
+ echo "--with_multipathd must be either 'y' or 'n'"
+ exit 1
+ fi
+ if [ "$ENABLE" = 2 -a -z "$HAVE_OUTFILE" ]; then
+ echo "Because --allow makes changes that cannot be automatically reversed,"
+ echo "you must set --outfile when you set --allow"
+ exit 1
+ fi
+}
+
+function add_blacklist_exceptions
+{
+ INDEX=0
+ while [ "$INDEX" -lt "$WWIDS" ] ; do
+ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
+ wwid '"\"${WWID_LIST[$INDEX]}\""'
+' $TMPFILE
+ ((INDEX++))
+ done
+}
+
+umask 0077
+
+parse_args "$@"
+
+validate_args
+
+if [ ! -d "$MULTIPATHDIR" ]; then
+ echo "/etc/multipath/ does not exist. failing"
+ exit 1
+fi
+
+rm $TMPFILE 2> /dev/null
+echo "$DEFAULT_CONFIG" > $TMPFILE
+if [ -f "$CONFIGFILE" ]; then
+ cp $CONFIGFILE $TMPFILE
+fi
+
+if grep -q "^blacklist[[:space:]]*{" $TMPFILE ; then
+ HAVE_BLACKLIST=1
+fi
+
+if grep -q "^blacklist_exceptions[[:space:]]*{" $TMPFILE ; then
+ HAVE_EXCEPTIONS=1
+fi
+
+if grep -q "^defaults[[:space:]]*{" $TMPFILE ; then
+ HAVE_DEFAULTS=1
+fi
+
+if [ -z "$MODULE" -o "$MODULE" = "y" ]; then
+ if lsmod | grep -q "dm_multipath" ; then
+ HAVE_MODULE=1
+ else
+ HAVE_MODULE=0
+ fi
+fi
+
+if [ "$MULTIPATHD" = "y" ]; then
+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then
+ HAVE_MULTIPATHD=1
+ else
+ HAVE_MULTIPATHD=0
+ fi
+fi
+
+if [ "$HAVE_BLACKLIST" = "1" ]; then
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then
+ HAVE_DISABLE=1
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then
+ HAVE_DISABLE=0
+ fi
+fi
+
+if [ "$HAVE_BLACKLIST" = "1" ]; then
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then
+ HAVE_WWID_DISABLE=1
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then
+ HAVE_WWID_DISABLE=0
+ fi
+fi
+
+if [ "$HAVE_DEFAULTS" = "1" ]; then
+ HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p`
+ if [ "$HAVE_FIND" = "1" ]; then
+ HAVE_FIND="yes"
+ elif [ "$HAVE_FIND" = "0" ]; then
+ HAVE_FIND="no"
+ fi
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then
+ HAVE_FRIENDLY=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then
+ HAVE_FRIENDLY=0
+ fi
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*enable_foreign" ; then
+ HAVE_FOREIGN=0
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]]*\"\^\$\"" ; then
+ HAVE_FOREIGN=1
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
+ HAVE_FOREIGN=2
+ fi
+fi
+
+if [ "$HAVE_EXCEPTIONS" = "1" ]; then
+ if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
+ HAVE_PROPERTY=1
+ elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
+ HAVE_PROPERTY=0
+ fi
+fi
+
+if [ -n "$SHOW_STATUS" ]; then
+ if [ -z "$HAVE_DISABLE" -o "$HAVE_DISABLE" = 0 ]; then
+ echo "multipath is enabled"
+ else
+ echo "multipath is disabled"
+ fi
+ if [ -z "$HAVE_FIND" ]; then
+ echo "find_multipaths is no"
+ else
+ echo "find_multipaths is $HAVE_FIND"
+ fi
+ if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then
+ echo "user_friendly_names is disabled"
+ else
+ echo "user_friendly_names is enabled"
+ fi
+ if [ -z "$HAVE_PROPERTY" -o "$HAVE_PROPERTY" = 0 ]; then
+ echo "default property blacklist is disabled"
+ else
+ echo "default property blacklist is enabled"
+ fi
+ if [ -z "$HAVE_FOREIGN" -o "$HAVE_FOREIGN" = 0 ]; then
+ echo "enable_foreign is not set (all foreign multipath devices will be shown)"
+ elif [ "$HAVE_FOREIGN" = 1 ]; then
+ echo "enable_foreign is set (no foreign multipath devices will be shown)"
+ else
+ echo "enable_foreign is set (foreign multipath devices may not be shown)"
+ fi
+ if [ -n "$HAVE_MODULE" ]; then
+ if [ "$HAVE_MODULE" = 1 ]; then
+ echo "dm_multipath module is loaded"
+ else
+ echo "dm_multipath module is not loaded"
+ fi
+ fi
+ if [ -z "$HAVE_MULTIPATHD" ]; then
+ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then
+ HAVE_MULTIPATHD=1
+ else
+ HAVE_MULTIPATHD=0
+ fi
+ fi
+ if [ "$HAVE_MULTIPATHD" = 1 ]; then
+ echo "multipathd is running"
+ else
+ echo "multipathd is not running"
+ fi
+ exit 0
+fi
+
+if [ -z "$HAVE_BLACKLIST" ]; then
+ cat >> $TMPFILE <<- _EOF_
+
+blacklist {
+}
+_EOF_
+fi
+
+if [ -z "$HAVE_DEFAULTS" ]; then
+ cat >> $TMPFILE <<- _EOF_
+
+defaults {
+}
+_EOF_
+fi
+
+if [ "$ENABLE" = 2 ]; then
+ if [ "$HAVE_DISABLE" = 1 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ fi
+ if [ -z "$HAVE_WWID_DISABLE" ]; then
+ sed -i '/^blacklist[[:space:]]*{/ a\
+ wwid ".*"
+' $TMPFILE
+ elif [ "$HAVE_WWID_DISABLE" = 0 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE
+ fi
+ if [ "$HAVE_EXCEPTIONS" = 1 ]; then
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE
+ else
+ cat >> $TMPFILE <<- _EOF_
+
+blacklist_exceptions {
+}
+_EOF_
+ fi
+ add_blacklist_exceptions
+elif [ "$ENABLE" = 1 ]; then
+ if [ "$HAVE_DISABLE" = 1 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ fi
+elif [ "$ENABLE" = 0 ]; then
+ if [ -z "$HAVE_DISABLE" ]; then
+ sed -i '/^blacklist[[:space:]]*{/ a\
+ devnode ".*"
+' $TMPFILE
+ elif [ "$HAVE_DISABLE" = 0 ]; then
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE
+ fi
+fi
+
+if [ -n "$FIND" ]; then
+ if [ -z "$HAVE_FIND" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ find_multipaths '"$FIND"'
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$FIND" != "$HAVE_FIND" ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ "$FRIENDLY" = "n" ]; then
+ if [ "$HAVE_FRIENDLY" = 1 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ "$FRIENDLY" = "y" ]; then
+ if [ -z "$HAVE_FRIENDLY" ]; then
+ sed -i '/^defaults[[:space:]]*{/ a\
+ user_friendly_names yes
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_FRIENDLY" = 0 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ "$PROPERTY" = "n" ]; then
+ if [ "$HAVE_PROPERTY" = 1 ]; then
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+elif [ "$PROPERTY" = "y" ]; then
+ if [ -z "$HAVE_PROPERTY" ]; then
+ sed -i '/^blacklist_exceptions[[:space:]]*{/ a\
+ property "(SCSI_IDENT_|ID_WWN)"
+' $TMPFILE
+ CHANGED_CONFIG=1
+ elif [ "$HAVE_PROPERTY" = 0 ]; then
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ "$FOREIGN" = "y" ]; then
+ if [ "$HAVE_FOREIGN" = 1 -o "$HAVE_FOREIGN" = 2 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[: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
+ CHANGED_CONFIG=1
+ fi
+fi
+
+if [ -f "$OUTPUTFILE" ]; then
+ cp $OUTPUTFILE $OUTPUTFILE.old
+ if [ $? != 0 ]; then
+ echo "failed to backup old config file, $OUTPUTFILE not updated"
+ exit 1
+ fi
+fi
+
+cp $TMPFILE $OUTPUTFILE
+if [ $? != 0 ]; then
+ echo "failed to copy new config file into place, check $OUTPUTFILE is still OK"
+ exit 1
+fi
+
+rm -f $TMPFILE
+
+if [ "$ENABLE" = 1 ]; then
+ if [ "$HAVE_MODULE" = 0 ]; then
+ modprobe dm_multipath
+ fi
+ if [ "$HAVE_MULTIPATHD" = 0 ]; then
+ systemctl start multipathd.service
+ fi
+elif [ "$ENABLE" = 0 ]; then
+ if [ "$HAVE_MULTIPATHD" = 1 ]; then
+ systemctl stop multipathd.service
+ fi
+elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then
+ systemctl reload multipathd.service
+fi
diff --git a/multipath/mpathconf.8 b/multipath/mpathconf.8
new file mode 100644
index 00000000..83515eb4
--- /dev/null
+++ b/multipath/mpathconf.8
@@ -0,0 +1,135 @@
+.TH MPATHCONF 8 "June 2010" "" "Linux Administrator's Manual"
+.SH NAME
+mpathconf - A tool for configuring device-mapper-multipath
+.SH SYNOPSIS
+.B mpathconf
+.RB [\| commands \|]
+.RB [\| options \|]
+.SH DESCRIPTION
+.B mpathconf
+is a utility that creates or modifies
+.B /etc/multipath.conf.
+It can enable or disable multipathing and configure some common options.
+.B mpathconf
+can also load the
+.B dm_multipath
+module, start and stop the
+.B multipathd
+daemon, and configure the
+.B multipathd
+service to start automatically or not. If
+.B mpathconf
+is called with no commands, it will display the current configuration, but
+will not create of modify
+.B /etc/multipath.conf
+
+The default options for mpathconf are
+.B --with_module
+The
+.B --with_multipathd
+option is not set by default. Enabling multipathing will load the
+.B dm_multipath
+module but it will not immediately start it. This is so
+that users can manually edit their config file if necessary, before starting
+.B multipathd.
+
+If
+.B /etc/multipath.conf
+already exists, mpathconf will edit it. If it does not exist, mpathconf will
+create a default file with
+.B user_friendly_names
+set and
+.B find_multipaths
+set to \fByes\fP. To disable these, use the
+.B --user_friendly_names n
+and
+.B --find_multipaths n
+options
+.SH COMMANDS
+.TP
+.B --enable
+Removes any line that blacklists all device nodes from the
+.B /etc/multipath.conf
+blacklist section. Also, creates
+.B /etc/multipath.conf
+if it doesn't exist.
+.TP
+.B --disable
+Adds a line that blacklists all device nodes to the
+.B /etc/multipath.conf
+blacklist section. If no blacklist section exists, it will create one.
+.TP
+.B --allow \fB<device>\fP
+Modifies the \fB/etc/multipath/conf\fP blacklist to blacklist all
+wwids and the blacklist_exceptions to whitelist \fB<device>\fP. \fB<device>\fP
+can be in the form of MAJOR:MINOR, a wwid, or the name of a device-mapper
+device, either a multipath device, or any device on stacked on top of one or
+more multipath devices. This command can be used multiple times to allow
+multiple devices. \fBNOTE:\fP This action will create a configuration file that
+mpathconf will not be able to revert back to its previous state. Because
+of this, \fB--outfile\fP is required when using \fB--allow\fP.
+.TP
+.B --user_friendly_names \fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B user_friendly_names yes
+to the
+.B /etc/multipath.conf
+defaults section. If set to \fBn\fP, this removes the line, if present. This
+command can be used along with any other command.
+.TP
+.B --find_multipaths\fP { \fByes\fP | \fBno\fP | \fBstrict\fP | \fBgreedy\fP | \fBsmart\fP }
+If set to \fB<value>\fP, this adds the line
+.B find_multipaths <value>
+to the
+.B /etc/multipath.conf
+defaults section. This command can be used along with any other command.
+\fBy\fP and \fBn\fP can be used instead of \fByes\fP and \fBno\fP.
+.TP
+.B --property_blacklist \fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this adds the line
+.B property "(SCSI_IDENT_|ID_WWN)"
+to the
+.B /etc/multipath.conf
+blacklist_exceptions section. If set to \fBn\fP, this removes the line, if
+present. This command can be used along with any other command.
+.TP
+.B --enable_foreign\fP { \fBy\fP | \fBn\fP }
+If set to \fBn\fP, this adds the line
+.B enable_foreign "^$"
+to the
+.B /etc/multipath.conf
+defaults section. if set to \fBy\fP, this removes the line, if present. This
+command can be used along with any other command.
+.TP
+.B --outfile \fB<filename>\fP
+Write the resulting multipath configuration to \fB<filename>\fP instead of
+\fB/etc/multipath.conf\fP.
+.SH OPTIONS
+.TP
+.B --with_module\fP { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this runs
+.B modprobe dm_multipath
+to install the multipath modules. This option only works with the
+.B --enable
+command. This option is set to \fBy\fP by default.
+.TP
+.B --with_multipathd { \fBy\fP | \fBn\fP }
+If set to \fBy\fP, this runs
+.B service multipathd start
+to start the multipathd daemon on \fB--enable\fP,
+.B service multipathd stop
+to stop the multipathd daemon on \fB--disable\fP, and
+.B service multipathd reload
+to reconfigure multipathd on \fB--user_frindly_names\fP and
+\fB--find_multipaths\fP.
+This option is set to \fBn\fP by default.
+.SH FILES
+.BR /etc/multipath.conf
+.SH "SEE ALSO"
+.BR multipath.conf (5),
+.BR modprobe (8),
+.BR multipath (8),
+.BR multipathd (8),
+.BR service (8),
+.SH AUTHOR
+Benjamin Marzinski <bmarzins@redhat.com>

View File

@ -0,0 +1,151 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 17 Oct 2014 11:20:34 -0500
Subject: [PATCH] RH: add wwids from kernel cmdline mpath.wwids with -A
This patch adds another option to multipath, "-A", which reads
/proc/cmdline for mpath.wwid=<WWID> options, and adds any wwids it finds
to /etc/multipath/wwids. While this isn't usually important during
normal operation, since these wwids should already be added, it can be
helpful during installation, to make sure that multipath can claim
devices as its own, before LVM or something else makes use of them. The
patch also execs "/sbin/multipath -A" before running multipathd in
multipathd.service
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 54 +++++++++++++++++++++++++++++++++--
multipath/multipath.8 | 7 ++++-
multipathd/multipathd.service | 1 +
3 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/multipath/main.c b/multipath/main.c
index ef89c7cf..f618550d 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -122,7 +122,7 @@ usage (char * progname)
fprintf (stderr, " %s [-v level] [-R retries] -F\n", progname);
fprintf (stderr, " %s [-v level] [-l|-ll] [device]\n", progname);
fprintf (stderr, " %s [-v level] [-a|-w] device\n", progname);
- fprintf (stderr, " %s [-v level] -W\n", progname);
+ fprintf (stderr, " %s [-v level] [-A|-W]\n", progname);
fprintf (stderr, " %s [-v level] [-i] [-c|-C] device\n", progname);
fprintf (stderr, " %s [-v level] [-i] [-u|-U]\n", progname);
fprintf (stderr, " %s [-h|-t|-T]\n", progname);
@@ -136,6 +136,8 @@ usage (char * progname)
" -f flush a multipath device map\n"
" -F flush all multipath device maps\n"
" -a add a device wwid to the wwids file\n"
+ " -A add devices from kernel command line mpath.wwids\n"
+ " parameters to wwids file\n"
" -c check if a device should be a path in a multipath device\n"
" -C check if a multipath device has usable paths\n"
" -q allow queue_if_no_path when multipathd is not running\n"
@@ -450,6 +452,50 @@ static void cleanup_vecs(void)
free_pathvec(vecs.pathvec, FREE_PATHS);
}
+static int remember_cmdline_wwid(void)
+{
+ FILE *f = NULL;
+ char buf[LINE_MAX], *next, *ptr;
+ int ret = 0;
+
+ f = fopen("/proc/cmdline", "re");
+ if (!f) {
+ condlog(0, "can't open /proc/cmdline : %s", strerror(errno));
+ return -1;
+ }
+
+ if (!fgets(buf, sizeof(buf), f)) {
+ if (ferror(f))
+ condlog(0, "read of /proc/cmdline failed : %s",
+ strerror(errno));
+ else
+ condlog(0, "couldn't read /proc/cmdline");
+ fclose(f);
+ return -1;
+ }
+ fclose(f);
+ next = buf;
+ while((ptr = strstr(next, "mpath.wwid="))) {
+ ptr += 11;
+ next = strpbrk(ptr, " \t\n");
+ if (next) {
+ *next = '\0';
+ next++;
+ }
+ if (strlen(ptr)) {
+ if (remember_wwid(ptr) != 0)
+ ret = -1;
+ }
+ else {
+ condlog(0, "empty mpath.wwid kernel command line option");
+ ret = -1;
+ }
+ if (!next)
+ break;
+ }
+ return ret;
+}
+
static int
configure (struct config *conf, enum mpath_cmds cmd,
enum devtypes dev_type, char *devpath)
@@ -823,7 +869,7 @@ main (int argc, char *argv[])
conf = get_multipath_config();
conf->retrigger_tries = 0;
conf->force_sync = 1;
- while ((arg = getopt(argc, argv, ":adDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
+ while ((arg = getopt(argc, argv, ":aAdDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
switch(arg) {
case 1: printf("optarg : %s\n",optarg);
break;
@@ -900,6 +946,10 @@ main (int argc, char *argv[])
case 'T':
cmd = CMD_DUMP_CONFIG;
break;
+ case 'A':
+ if (remember_cmdline_wwid() != 0)
+ exit(RTVL_FAIL);
+ exit(RTVL_OK);
case 'h':
usage(argv[0]);
exit(RTVL_OK);
diff --git a/multipath/multipath.8 b/multipath/multipath.8
index 5b29a5d9..0478f4e7 100644
--- a/multipath/multipath.8
+++ b/multipath/multipath.8
@@ -63,7 +63,7 @@ multipath \- Device mapper target autoconfig.
.B multipath
.RB [\| \-v\ \c
.IR level \|]
-.B -W
+.RB [\| \-A | \-W \|]
.
.LP
.B multipath
@@ -145,6 +145,11 @@ device mapper, path checkers ...).
Add the WWID for the specified device to the WWIDs file.
.
.TP
+.B \-A
+Add the WWIDs from any kernel command line \fImpath.wwid\fR parameters to the
+WWIDs file.
+.
+.TP
.B \-w
Remove the WWID for the specified device from the WWIDs file.
.
diff --git a/multipathd/multipathd.service b/multipathd/multipathd.service
index af592057..bc8fa07a 100644
--- a/multipathd/multipathd.service
+++ b/multipathd/multipathd.service
@@ -15,6 +15,7 @@ Type=notify
NotifyAccess=main
LimitCORE=infinity
ExecStartPre=-/sbin/modprobe -a scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm-multipath
+ExecStartPre=-/sbin/multipath -A
ExecStart=/sbin/multipathd -d -s
ExecReload=/sbin/multipathd reconfigure
TasksMax=infinity

View File

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 7 Jun 2018 17:43:52 -0500
Subject: [PATCH] RH: reset default find_mutipaths value to off
Upstream has changed to default find_multipaths to "strict". For now
Redhat will retain the previous default of "off".
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/defaults.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index c27946c7..e0dd32ad 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -23,7 +23,7 @@
#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 0
-#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_STRICT
+#define DEFAULT_FIND_MULTIPATHS FIND_MULTIPATHS_OFF
#define DEFAULT_FAST_IO_FAIL 5
#define DEFAULT_DEV_LOSS_TMO 600
#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON

View File

@ -0,0 +1,84 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 11 Apr 2019 13:25:42 -0500
Subject: [PATCH] RH: attempt to get ANA info via sysfs first
When the ANA prioritizer is run, first see if the "ana_state" sysfs file
exists, and if it does, try to read the state from there. If that fails,
fallback to using an ioctl.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/prioritizers/ana.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/libmultipath/prioritizers/ana.c b/libmultipath/prioritizers/ana.c
index b5c7873d..e139360c 100644
--- a/libmultipath/prioritizers/ana.c
+++ b/libmultipath/prioritizers/ana.c
@@ -24,6 +24,7 @@
#include "prio.h"
#include "util.h"
#include "structs.h"
+#include "sysfs.h"
enum {
ANA_ERR_GETCTRL_FAILED = 1,
@@ -36,6 +37,7 @@ enum {
ANA_ERR_GETNS_FAILED,
ANA_ERR_NO_MEMORY,
ANA_ERR_NO_INFORMATION,
+ ANA_ERR_INVALID_STATE,
};
static const char *ana_errmsg[] = {
@@ -49,6 +51,7 @@ static const char *ana_errmsg[] = {
[ANA_ERR_GETNS_FAILED] = "couldn't get namespace info",
[ANA_ERR_NO_MEMORY] = "out of memory",
[ANA_ERR_NO_INFORMATION] = "invalid fd",
+ [ANA_ERR_INVALID_STATE] = "invalid state",
};
static const char *anas_string[] = {
@@ -107,6 +110,27 @@ static int get_ana_state(__u32 nsid, __u32 anagrpid, void *ana_log,
return -ANA_ERR_GETANAS_NOTFOUND;
}
+static int get_ana_info_sysfs(struct path *pp)
+{
+ char state[32];
+
+ if (!pp->udev || sysfs_attr_get_value(pp->udev, "ana_state", state,
+ sizeof(state)) <= 0)
+ return -ANA_ERR_NO_INFORMATION;
+
+ if (strcmp(state, "optimized") == 0)
+ return NVME_ANA_OPTIMIZED;
+ if (strcmp(state, "non-optimized") == 0)
+ return NVME_ANA_NONOPTIMIZED;
+ if (strcmp(state, "inaccessible") == 0)
+ return NVME_ANA_INACCESSIBLE;
+ if (strcmp(state, "persistent-loss") == 0)
+ return NVME_ANA_PERSISTENT_LOSS;
+ if (strcmp(state, "change") == 0)
+ return NVME_ANA_CHANGE;
+ return -ANA_ERR_INVALID_STATE;
+}
+
static int get_ana_info(struct path * pp)
{
int rc;
@@ -210,8 +234,11 @@ int getprio(struct path *pp, __attribute__((unused)) char *args,
if (pp->fd < 0)
rc = -ANA_ERR_NO_INFORMATION;
- else
- rc = get_ana_info(pp);
+ else {
+ rc = get_ana_info_sysfs(pp);
+ if (rc < 0)
+ rc = get_ana_info(pp);
+ }
switch (rc) {
case NVME_ANA_OPTIMIZED:

View File

@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 25 Mar 2021 13:05:10 -0500
Subject: [PATCH] RH: make parse_vpd_pg83 match scsi_id output
Red Hat sets ID_SERIAL based on the result of scsi_id, instead of using
the result of sg_inq and 55-scsi-sg3_id.rules. Make parse_vpd_pg83 match
that.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/discovery.c | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index ec99a7aa..2704270e 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -1135,12 +1135,9 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
naa_prio = 7;
break;
case 2:
- /* IEEE Extended: Prio 6 */
- naa_prio = 6;
- break;
case 3:
- /* IEEE Locally assigned: Prio 1 */
- naa_prio = 1;
+ /* IEEE Extended or Locally assigned: Prio 6 */
+ naa_prio = 6;
break;
default:
/* Default: no priority */
@@ -1159,17 +1156,6 @@ parse_vpd_pg83(const unsigned char *in, size_t in_len,
vpd = d;
}
break;
- case 0x8:
- /* SCSI Name: Prio 3 */
- if (memcmp(d + 4, "eui.", 4) &&
- memcmp(d + 4, "naa.", 4) &&
- memcmp(d + 4, "iqn.", 4))
- break;
- if (prio < 3) {
- prio = 3;
- vpd = d;
- }
- break;
case 0x1:
/* T-10 Vendor ID: Prio 2 */
if (prio < 2) {

View File

@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 11 May 2021 11:15:47 -0500
Subject: [PATCH] multipathd: don't fail to remove path once the map is removed
In ev_remove_path(), if update_mpp_paths() fails, we delete the entire
map. However, since update_mpp_paths() happens before we call
set_path_removed(), pp->initialized isn't set to INIT_REMOVED, so
remove_map_and_stop_waiter() doesn't remove the path when in removes the
map. But with the map removed, there's nothing to keep us from removing
the path.
Call set_path_removed() before update_mpp_paths() to avoid the odd case
of ev_remove_path() removing the map but not the path.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/structs_vec.c | 4 ++--
multipathd/main.c | 13 ++++++++-----
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index d242c06b..75390198 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -45,8 +45,8 @@ int update_mpp_paths(struct multipath *mpp, vector pathvec)
/*
* Avoid adding removed paths to the map again
- * when we reload it. Such paths may exist if
- * domap fails in ev_remove_path().
+ * when we reload it. Such paths may exist in
+ * ev_remove_paths() or if it returns failure.
*/
pp1 = find_path_by_devt(pathvec, pp->dev_t);
if (pp1 && pp->initialized != INIT_REMOVED &&
diff --git a/multipathd/main.c b/multipathd/main.c
index 102946bf..449ce384 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1199,6 +1199,13 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
* avoid referring to the map of an orphaned path
*/
if ((mpp = pp->mpp)) {
+ /*
+ * Mark the path as removed. In case of success, we
+ * will delete it for good. Otherwise, it will be deleted
+ * later, unless all attempts to reload this map fail.
+ */
+ set_path_removed(pp);
+
/*
* transform the mp->pg vector of vectors of paths
* into a mp->params string to feed the device-mapper
@@ -1210,13 +1217,9 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
}
/*
- * Mark the path as removed. In case of success, we
- * will delete it for good. Otherwise, it will be deleted
- * later, unless all attempts to reload this map fail.
- * Note: we have to explicitly remove pp from mpp->paths,
+ * we have to explicitly remove pp from mpp->paths,
* update_mpp_paths() doesn't do that.
*/
- set_path_removed(pp);
i = find_slot(mpp->paths, pp);
if (i != -1)
vector_del_slot(mpp->paths, i);

View File

@ -0,0 +1,26 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 11 May 2021 11:55:14 -0500
Subject: [PATCH] multipathd: remove duplicate orphan_paths in flush_map
remove_map_and_stop_waiter() already calls orphan_paths() so flush_map()
doesn't need to call orphan_paths() before calling
remove_map_and_stop_waiter().
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 449ce384..6090434c 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -660,7 +660,6 @@ flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths)
else
condlog(2, "%s: map flushed", mpp->alias);
- orphan_paths(vecs->pathvec, mpp, "map flushed");
remove_map_and_stop_waiter(mpp, vecs);
return 0;

View File

@ -0,0 +1,225 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 11 May 2021 13:58:57 -0500
Subject: [PATCH] multipathd: fix ev_remove_path return code handling
When ev_remove_path() returned success, callers assumed that the path
(and possibly the map) had been removed. When ev_remove_path() returned
failure, callers assumed that the path had not been removed. However,
the path could be removed on both success or failure. This could cause
callers to dereference the path after it was removed.
To deal with this, make ev_remove_path() return a different symbolic
value for each outcome, and make the callers react appropriately for
the different values. Found by coverity.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/cli_handlers.c | 24 +++++++++++++++++++++--
multipathd/main.c | 41 ++++++++++++++++++++-------------------
multipathd/main.h | 14 +++++++++++++
3 files changed, 57 insertions(+), 22 deletions(-)
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 1de6ad8e..6765fcf0 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -752,7 +752,8 @@ cli_add_path (void * v, char ** reply, int * len, void * data)
/* Have the checker reinstate this path asap */
pp->tick = 1;
return 0;
- } else if (!ev_remove_path(pp, vecs, true))
+ } else if (ev_remove_path(pp, vecs, true) &
+ REMOVE_PATH_SUCCESS)
/* Path removed in ev_remove_path() */
pp = NULL;
else {
@@ -813,6 +814,7 @@ cli_del_path (void * v, char ** reply, int * len, void * data)
struct vectors * vecs = (struct vectors *)data;
char * param = get_keyparam(v, PATH);
struct path *pp;
+ int ret;
param = convert_dev(param, 1);
condlog(2, "%s: remove path (operator)", param);
@@ -821,7 +823,25 @@ cli_del_path (void * v, char ** reply, int * len, void * data)
condlog(0, "%s: path already removed", param);
return 1;
}
- return ev_remove_path(pp, vecs, 1);
+ ret = ev_remove_path(pp, vecs, 1);
+ if (ret == REMOVE_PATH_DELAY) {
+ *reply = strdup("delayed\n");
+ if (*reply)
+ *len = strlen(*reply) + 1;
+ else {
+ *len = 0;
+ ret = REMOVE_PATH_FAILURE;
+ }
+ } else if (ret == REMOVE_PATH_MAP_ERROR) {
+ *reply = strdup("map reload error. removed\n");
+ if (*reply)
+ *len = strlen(*reply) + 1;
+ else {
+ *len = 0;
+ ret = REMOVE_PATH_FAILURE;
+ }
+ }
+ return (ret == REMOVE_PATH_FAILURE);
}
int
diff --git a/multipathd/main.c b/multipathd/main.c
index 6090434c..8e2beddd 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -838,7 +838,7 @@ handle_path_wwid_change(struct path *pp, struct vectors *vecs)
return;
udd = udev_device_ref(pp->udev);
- if (ev_remove_path(pp, vecs, 1) != 0 && pp->mpp) {
+ if (!(ev_remove_path(pp, vecs, 1) & REMOVE_PATH_SUCCESS) && pp->mpp) {
pp->dmstate = PSTATE_FAILED;
dm_fail_path(pp->mpp->alias, pp->dev_t);
}
@@ -948,8 +948,8 @@ uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map)
* Make another attempt to remove the path
*/
pp->mpp = prev_mpp;
- ret = ev_remove_path(pp, vecs, true);
- if (ret != 0) {
+ if (!(ev_remove_path(pp, vecs, true) &
+ REMOVE_PATH_SUCCESS)) {
/*
* Failure in ev_remove_path will keep
* path in pathvec in INIT_REMOVED state
@@ -960,6 +960,7 @@ uev_add_path (struct uevent *uev, struct vectors * vecs, int need_do_map)
dm_fail_path(pp->mpp->alias, pp->dev_t);
condlog(1, "%s: failed to re-add path still mapped in %s",
pp->dev, pp->mpp->alias);
+ ret = 1;
} else if (r == PATHINFO_OK)
/*
* Path successfully freed, move on to
@@ -1167,7 +1168,6 @@ static int
uev_remove_path (struct uevent *uev, struct vectors * vecs, int need_do_map)
{
struct path *pp;
- int ret;
condlog(3, "%s: remove path (uevent)", uev->kernel);
delete_foreign(uev->udev);
@@ -1177,21 +1177,18 @@ uev_remove_path (struct uevent *uev, struct vectors * vecs, int need_do_map)
pthread_testcancel();
pp = find_path_by_dev(vecs->pathvec, uev->kernel);
if (pp)
- ret = ev_remove_path(pp, vecs, need_do_map);
+ ev_remove_path(pp, vecs, need_do_map);
lock_cleanup_pop(vecs->lock);
- if (!pp) {
- /* Not an error; path might have been purged earlier */
+ if (!pp) /* Not an error; path might have been purged earlier */
condlog(0, "%s: path already removed", uev->kernel);
- return 0;
- }
- return ret;
+ return 0;
}
int
ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
{
struct multipath * mpp;
- int i, retval = 0;
+ int i, retval = REMOVE_PATH_SUCCESS;
char params[PARAMS_SIZE] = {0};
/*
@@ -1245,7 +1242,6 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
condlog(2, "%s: removed map after"
" removing all paths",
alias);
- retval = 0;
/* flush_map() has freed the path */
goto out;
}
@@ -1262,11 +1258,14 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
if (mpp->wait_for_udev) {
mpp->wait_for_udev = 2;
+ retval = REMOVE_PATH_DELAY;
goto out;
}
- if (!need_do_map)
+ if (!need_do_map) {
+ retval = REMOVE_PATH_DELAY;
goto out;
+ }
/*
* reload the map
*/
@@ -1275,7 +1274,7 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
condlog(0, "%s: failed in domap for "
"removal of path %s",
mpp->alias, pp->dev);
- retval = 1;
+ retval = REMOVE_PATH_FAILURE;
} else {
/*
* update our state from kernel
@@ -1283,12 +1282,12 @@ ev_remove_path (struct path *pp, struct vectors * vecs, int need_do_map)
char devt[BLK_DEV_SIZE];
strlcpy(devt, pp->dev_t, sizeof(devt));
+
+ /* setup_multipath will free the path
+ * regardless of whether it succeeds or
+ * fails */
if (setup_multipath(vecs, mpp))
- return 1;
- /*
- * Successful map reload without this path:
- * sync_map_state() will free it.
- */
+ return REMOVE_PATH_MAP_ERROR;
sync_map_state(mpp);
condlog(2, "%s: path removed from map %s",
@@ -1304,8 +1303,10 @@ out:
return retval;
fail:
+ condlog(0, "%s: error removing path. removing map %s", pp->dev,
+ mpp->alias);
remove_map_and_stop_waiter(mpp, vecs);
- return 1;
+ return REMOVE_PATH_MAP_ERROR;
}
static int
diff --git a/multipathd/main.h b/multipathd/main.h
index ddd953f9..bc1f938f 100644
--- a/multipathd/main.h
+++ b/multipathd/main.h
@@ -13,6 +13,20 @@ enum daemon_status {
DAEMON_STATUS_SIZE,
};
+enum remove_path_result {
+ REMOVE_PATH_FAILURE = 0x0, /* path could not be removed. It is still
+ * part of the kernel map, but its state
+ * is set to INIT_REMOVED, and it will be
+ * removed at the next possible occassion */
+ REMOVE_PATH_SUCCESS = 0x1, /* path was removed */
+ REMOVE_PATH_DELAY = 0x2, /* path is set to be removed later. it
+ * currently still exists and is part of the
+ * kernel map */
+ REMOVE_PATH_MAP_ERROR = 0x5, /* map was removed because of error. value
+ * includes REMOVE_PATH_SUCCESS bit
+ * because the path was also removed */
+};
+
struct prout_param_descriptor;
struct prin_resp;

View File

@ -0,0 +1,46 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 11 May 2021 15:25:21 -0500
Subject: [PATCH] multipath: free vectors in configure
configure() can retry multiple times, each time reallocing a maps and
paths vector, and leaking the previous ones. Fix this by always freeing
the vectors before configure() exits. Found by coverity.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/main.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/multipath/main.c b/multipath/main.c
index f618550d..9fe53dcd 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -512,7 +512,6 @@ configure (struct config *conf, enum mpath_cmds cmd,
*/
curmp = vector_alloc();
pathvec = vector_alloc();
- atexit(cleanup_vecs);
if (!curmp || !pathvec) {
condlog(0, "can not allocate memory");
@@ -624,6 +623,11 @@ out:
if (refwwid)
FREE(refwwid);
+ free_multipathvec(curmp, KEEP_PATHS);
+ vecs.mpvec = NULL;
+ free_pathvec(pathvec, FREE_PATHS);
+ vecs.pathvec = NULL;
+
return r;
}
@@ -869,6 +873,7 @@ main (int argc, char *argv[])
conf = get_multipath_config();
conf->retrigger_tries = 0;
conf->force_sync = 1;
+ atexit(cleanup_vecs);
while ((arg = getopt(argc, argv, ":aAdDcChl::eFfM:v:p:b:BrR:itTquUwW")) != EOF ) {
switch(arg) {
case 1: printf("optarg : %s\n",optarg);

View File

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Tue, 11 May 2021 16:03:13 -0500
Subject: [PATCH] kpartx: Don't leak memory when getblock returns NULL
If a new block was allocated, but couldn't be filled, getblock will
discard it. When it does so, it needs to free the block to avoid leaking
memory. Found by coverity.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
kpartx/kpartx.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
index 8ff116b8..7bc64543 100644
--- a/kpartx/kpartx.c
+++ b/kpartx/kpartx.c
@@ -766,6 +766,8 @@ getblock (int fd, unsigned int blknr) {
if (read(fd, bp->block, secsz) != secsz) {
fprintf(stderr, "read error, sector %d\n", secnr);
blockhead = bp->next;
+ free(bp->block);
+ free(bp);
return NULL;
}

View File

@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 14 May 2021 13:45:28 -0500
Subject: [PATCH] multipathd: don't rescan_path on wwid change in
uev_update_path
If get_uid() is returning a different wwid in uev_update_path(), then
the uid_attribute must have already gotten updated, which was the
purpose behind calling rescan_path() in the first place.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/main.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/multipathd/main.c b/multipathd/main.c
index 8e2beddd..2750f5e9 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -1359,7 +1359,6 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
condlog(0, "%s: path wwid changed from '%s' to '%s'",
uev->kernel, wwid, pp->wwid);
ev_remove_path(pp, vecs, 1);
- rescan_path(uev->udev);
needs_reinit = 1;
goto out;
} else {

View File

@ -0,0 +1,204 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 9 Jul 2021 14:30:10 -0500
Subject: [PATCH] RH: mpathconf: correctly handle spaces after option names
mpathconf was either accepting any number of spaces, including zero,
after option names, or it was only accepting one space. It should
accept one or more spaces. Also, fix enable_foreign handling. It was
still working like it did in RHEL8, where the default was to enable
all foreign devices.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/mpathconf | 62 +++++++++++++++++++++++++--------------------
1 file changed, 34 insertions(+), 28 deletions(-)
diff --git a/multipath/mpathconf b/multipath/mpathconf
index 2f4f3eaf..039b3e47 100644
--- a/multipath/mpathconf
+++ b/multipath/mpathconf
@@ -240,7 +240,7 @@ function validate_args
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
@@ -315,46 +315,50 @@ if [ "$MULTIPATHD" = "y" ]; then
fi
if [ "$HAVE_BLACKLIST" = "1" ]; then
- if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode \"\.\?\*\"" ; then
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"" ; then
HAVE_DISABLE=1
- elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"" ; then
HAVE_DISABLE=0
fi
fi
if [ "$HAVE_BLACKLIST" = "1" ]; then
- if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then
+ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"" ; then
HAVE_WWID_DISABLE=1
- elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then
+ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"" ; then
HAVE_WWID_DISABLE=0
fi
fi
if [ "$HAVE_DEFAULTS" = "1" ]; then
- HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p`
+ HAVE_FIND=`sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | sed -n 's/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*\([^[:blank:]]*\).*$/\1/p' | sed -n 1p`
if [ "$HAVE_FIND" = "1" ]; then
HAVE_FIND="yes"
elif [ "$HAVE_FIND" = "0" ]; then
HAVE_FIND="no"
fi
- if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then
+ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(yes\|1\)" ; then
HAVE_FRIENDLY=1
- elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(no\|0\)" ; then
HAVE_FRIENDLY=0
fi
if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*enable_foreign" ; then
HAVE_FOREIGN=0
- elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]]*\"\^\$\"" ; then
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]][[: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:]][[:space:]]*\"\^\$\"" ; then
+ HAVE_FOREIGN=2
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign[[:space:]][[:space:]]*\"NONE\"" ; then
HAVE_FOREIGN=2
+ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*enable_foreign" ; then
+ HAVE_FOREIGN=3
fi
fi
if [ "$HAVE_EXCEPTIONS" = "1" ]; then
- if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
+ if sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
HAVE_PROPERTY=1
- elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
+ elif sed -n '/^blacklist_exceptions[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"" ; then
HAVE_PROPERTY=0
fi
fi
@@ -381,8 +385,10 @@ if [ -n "$SHOW_STATUS" ]; then
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 (all foreign multipath devices will be shown)"
+ elif [ "$HAVE_FOREIGN" = 2 ]; then
echo "enable_foreign is set (no foreign multipath devices will be shown)"
else
echo "enable_foreign is set (foreign multipath devices may not be shown)"
@@ -427,14 +433,14 @@ fi
if [ "$ENABLE" = 2 ]; then
if [ "$HAVE_DISABLE" = 1 ]; then
- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE
fi
if [ -z "$HAVE_WWID_DISABLE" ]; then
sed -i '/^blacklist[[:space:]]*{/ a\
wwid ".*"
' $TMPFILE
elif [ "$HAVE_WWID_DISABLE" = 0 ]; then
- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"/ wwid ".*"/' $TMPFILE
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*wwid[[:space:]][[:space:]]*\"\.\?\*\"/ wwid ".*"/' $TMPFILE
fi
if [ "$HAVE_EXCEPTIONS" = 1 ]; then
sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ {/^[[:space:]]*wwid/ d}' $TMPFILE
@@ -448,7 +454,7 @@ _EOF_
add_blacklist_exceptions
elif [ "$ENABLE" = 1 ]; then
if [ "$HAVE_DISABLE" = 1 ]; then
- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/# devnode ".*"/' $TMPFILE
fi
elif [ "$ENABLE" = 0 ]; then
if [ -z "$HAVE_DISABLE" ]; then
@@ -456,7 +462,7 @@ elif [ "$ENABLE" = 0 ]; then
devnode ".*"
' $TMPFILE
elif [ "$HAVE_DISABLE" = 0 ]; then
- sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE
+ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*devnode[[:space:]][[:space:]]*\"\.\?\*\"/ devnode ".*"/' $TMPFILE
fi
fi
@@ -467,14 +473,14 @@ if [ -n "$FIND" ]; then
' $TMPFILE
CHANGED_CONFIG=1
elif [ "$FIND" != "$HAVE_FIND" ]; then
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:blank:]]*find_multipaths[[:blank:]][[:blank:]]*[^[:blank:]]*/ find_multipaths '"$FIND"'/' $TMPFILE
CHANGED_CONFIG=1
fi
fi
if [ "$FRIENDLY" = "n" ]; then
if [ "$HAVE_FRIENDLY" = 1 ]; then
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE
CHANGED_CONFIG=1
fi
elif [ "$FRIENDLY" = "y" ]; then
@@ -484,14 +490,14 @@ elif [ "$FRIENDLY" = "y" ]; then
' $TMPFILE
CHANGED_CONFIG=1
elif [ "$HAVE_FRIENDLY" = 0 ]; then
- sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]][[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE
CHANGED_CONFIG=1
fi
fi
if [ "$PROPERTY" = "n" ]; then
if [ "$HAVE_PROPERTY" = 1 ]; then
- sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/# property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
CHANGED_CONFIG=1
fi
elif [ "$PROPERTY" = "y" ]; then
@@ -501,24 +507,24 @@ elif [ "$PROPERTY" = "y" ]; then
' $TMPFILE
CHANGED_CONFIG=1
elif [ "$HAVE_PROPERTY" = 0 ]; then
- sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
+ sed -i '/^blacklist_exceptions[[:space:]]*{/,/^}/ s/^[[:space:]]*#[[:space:]]*property[[:space:]][[:space:]]*\"(SCSI_IDENT_|ID_WWN)\"/ property \"(SCSI_IDENT_|ID_WWN)\"/' $TMPFILE
CHANGED_CONFIG=1
fi
fi
-if [ "$FOREIGN" = "y" ]; then
- if [ "$HAVE_FOREIGN" = 1 -o "$HAVE_FOREIGN" = 2 ]; then
+if [ "$FOREIGN" = "n" ]; then
+ if [ "$HAVE_FOREIGN" = 1 -o "$HAVE_FOREIGN" = 3 ]; then
sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*enable_foreign/# enable_foreign/' $TMPFILE
CHANGED_CONFIG=1
fi
-elif [ "$FOREIGN" = "n" ]; then
+elif [ "$FOREIGN" = "y" ]; then
if [ -z "$HAVE_FOREIGN" ]; then
sed -i '/^defaults[[:space:]]*{/ a\
- enable_foreign "^$"
+ 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
+ elif [ "$HAVE_FOREIGN" = 0 -o "$HAVE_FOREIGN" = 2 -o "$HAVE_FOREIGN" = 3 ]; then
+ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*#\?[[:space:]]*enable_foreign.*$/ enable_foreign ".*"/' $TMPFILE
CHANGED_CONFIG=1
fi
fi

View File

@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 15 Jul 2021 14:46:49 -0500
Subject: [PATCH] multipath.conf: fix typo in ghost_delay description
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipath/multipath.conf.5 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 0d2bce09..689d09aa 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1251,7 +1251,7 @@ The default is: in \fB/sys/block/<dev>/queue/max_sectors_kb\fR
Sets the number of seconds that multipath will wait after creating a device
with only ghost paths before marking it ready for use in systemd. This gives
the active paths time to appear before the multipath runs the hardware handler
-to switch the ghost paths to active ones. Setting this to \fI0\fR or \fIon\fR
+to switch the ghost paths to active ones. Setting this to \fI0\fR or \fIno\fR
makes multipath immediately mark a device with only ghost paths as ready.
.RS
.TP

View File

@ -0,0 +1,41 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 15 Jul 2021 17:09:05 -0500
Subject: [PATCH] mpathpersist: fail commands when no usable paths exist
"mpathpersist -oCK <reservation_key> <device>" will return success if it
is run on devices with no usable paths, but nothing is actually done.
The -L command will fail, but it should give up sooner, and with a more
helpful error message.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmpathpersist/mpath_persist.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
index 190e9707..26710e79 100644
--- a/libmpathpersist/mpath_persist.c
+++ b/libmpathpersist/mpath_persist.c
@@ -604,7 +604,8 @@ int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope,
return ret ;
}
}
- return MPATH_PR_SUCCESS;
+ condlog (0, "%s: no path available", mpp->wwid);
+ return MPATH_PR_DMMP_ERROR;
}
int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
@@ -663,6 +664,11 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
active_pathcount = count_active_paths(mpp);
+ if (active_pathcount == 0) {
+ condlog (0, "%s: no path available", mpp->wwid);
+ return MPATH_PR_DMMP_ERROR;
+ }
+
struct threadinfo thread[active_pathcount];
memset(thread, 0, sizeof(thread));
for (i = 0; i < active_pathcount; i++){

View File

@ -0,0 +1,119 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Fri, 16 Jul 2021 12:39:17 -0500
Subject: [PATCH] multipath: print warning if multipathd is not running.
If multipath notices that multipath devices exist or were created, and
multipathd is not running, it now prints a warning message, so users are
notified of the issue.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/configure.c | 13 +++++++++++--
libmultipath/configure.h | 1 +
libmultipath/libmultipath.version | 5 +++++
multipath/main.c | 5 +++++
4 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index 6ca1f4bb..9da85ce6 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -1083,7 +1083,8 @@ deadmap (struct multipath * mpp)
return 1; /* dead */
}
-int check_daemon(void)
+extern int
+check_daemon(void)
{
int fd;
char *reply;
@@ -1138,6 +1139,8 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
struct config *conf;
int allow_queueing;
struct bitfield *size_mismatch_seen;
+ bool map_processed = false;
+ bool no_daemon = false;
/* ignore refwwid if it's empty */
if (refwwid && !strlen(refwwid))
@@ -1288,7 +1291,9 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
conf = get_multipath_config();
allow_queueing = conf->allow_queueing;
put_multipath_config(conf);
- if (!is_daemon && !allow_queueing && !check_daemon()) {
+ if (!is_daemon && !allow_queueing &&
+ (no_daemon || !check_daemon())) {
+ no_daemon = true;
if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
mpp->no_path_retry != NO_PATH_RETRY_FAIL)
condlog(3, "%s: multipathd not running, unset "
@@ -1311,6 +1316,7 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
else
remove_map(mpp, vecs->pathvec, vecs->mpvec,
KEEP_VEC);
+ map_processed = true;
}
/*
* Flush maps with only dead paths (ie not in sysfs)
@@ -1336,6 +1342,9 @@ int coalesce_paths (struct vectors *vecs, vector mpvec, char *refwwid,
condlog(2, "%s: remove (dead)", alias);
}
}
+ if (map_processed && !is_daemon && (no_daemon || !check_daemon()))
+ condlog(2, "multipath devices exist, but multipathd service is not running");
+
ret = CP_OK;
out:
free(size_mismatch_seen);
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
index 70cf77a3..741066b3 100644
--- a/libmultipath/configure.h
+++ b/libmultipath/configure.h
@@ -60,3 +60,4 @@ struct udev_device *get_udev_device(const char *dev, enum devtypes dev_type);
void trigger_paths_udev_change(struct multipath *mpp, bool is_mpath);
void trigger_partitions_udev_change(struct udev_device *dev, const char *action,
int len);
+int check_daemon(void);
diff --git a/libmultipath/libmultipath.version b/libmultipath/libmultipath.version
index 0cff3111..d8be5fd2 100644
--- a/libmultipath/libmultipath.version
+++ b/libmultipath/libmultipath.version
@@ -274,3 +274,8 @@ global:
local:
*;
};
+
+LIBMULTIPATH_5.1.0 {
+global:
+ check_daemon;
+} LIBMULTIPATH_5.0.0;
diff --git a/multipath/main.c b/multipath/main.c
index 9fe53dcd..85e4481d 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -182,6 +182,7 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
int i;
struct multipath * mpp;
int flags = (cmd == CMD_LIST_SHORT ? DI_NOIO : DI_ALL);
+ bool maps_present = false;
if (dm_get_maps(curmp))
return 1;
@@ -214,11 +215,15 @@ get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
if (cmd == CMD_CREATE)
reinstate_paths(mpp);
+
+ maps_present = true;
}
if (cmd == CMD_LIST_SHORT || cmd == CMD_LIST_LONG)
print_foreign_topology(libmp_verbosity);
+ if (maps_present && !check_daemon())
+ condlog(2, "multipath devices exist, but multipathd service is not running");
return 0;
}

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Thu, 29 Jul 2021 13:16:57 -0500
Subject: [PATCH] libmultipath: deal with dynamic PTHREAD_STACK_MIN
Starting in glibc-2.34 (commit 5d98a7da), PTHREAD_STACK_MIN is defined
as sysconf(_SC_THREAD_STACK_MIN) if _GNU_SOURCE is defined. sysconf()
returns a long and can, at least in theory, return -1. This change
causes compilation to fail in setup_thread_attr() due to a comparision
with different signedness, since stacksize is a size_t.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/util.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libmultipath/util.c b/libmultipath/util.c
index 0e37f3ff..17f8fcc6 100644
--- a/libmultipath/util.c
+++ b/libmultipath/util.c
@@ -223,8 +223,8 @@ setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached)
ret = pthread_attr_init(attr);
assert(ret == 0);
- if (stacksize < PTHREAD_STACK_MIN)
- stacksize = PTHREAD_STACK_MIN;
+ if (PTHREAD_STACK_MIN > 0 && stacksize < (size_t)PTHREAD_STACK_MIN)
+ stacksize = (size_t)PTHREAD_STACK_MIN;
ret = pthread_attr_setstacksize(attr, stacksize);
assert(ret == 0);
if (detached) {

View File

@ -0,0 +1,82 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Mon, 17 May 2021 22:37:34 +0200
Subject: [PATCH] multipathd: cli_handlers: cleanup setting reply length
Create a macro for setting the reply length for string literals
correctly, and use it where necessary.
In cli_del_path(), don't change the function's return code
if just the buffer allocation for the reply failed.
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
multipathd/cli_handlers.c | 33 ++++++++++++---------------------
1 file changed, 12 insertions(+), 21 deletions(-)
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 6765fcf0..96064944 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -32,6 +32,12 @@
#include "foreign.h"
#include "cli_handlers.h"
+#define SET_REPLY_AND_LEN(__rep, __len, string_literal) \
+ do { \
+ *(__rep) = strdup(string_literal); \
+ *(__len) = *(__rep) ? sizeof(string_literal) : 0; \
+ } while (0)
+
int
show_paths (char ** r, int * len, struct vectors * vecs, char * style,
int pretty)
@@ -802,8 +808,7 @@ cli_add_path (void * v, char ** reply, int * len, void * data)
}
return ev_add_path(pp, vecs, 1);
blacklisted:
- *reply = strdup("blacklisted\n");
- *len = strlen(*reply) + 1;
+ SET_REPLY_AND_LEN(reply, len, "blacklisted\n");
condlog(2, "%s: path blacklisted", param);
return 0;
}
@@ -824,23 +829,10 @@ cli_del_path (void * v, char ** reply, int * len, void * data)
return 1;
}
ret = ev_remove_path(pp, vecs, 1);
- if (ret == REMOVE_PATH_DELAY) {
- *reply = strdup("delayed\n");
- if (*reply)
- *len = strlen(*reply) + 1;
- else {
- *len = 0;
- ret = REMOVE_PATH_FAILURE;
- }
- } else if (ret == REMOVE_PATH_MAP_ERROR) {
- *reply = strdup("map reload error. removed\n");
- if (*reply)
- *len = strlen(*reply) + 1;
- else {
- *len = 0;
- ret = REMOVE_PATH_FAILURE;
- }
- }
+ if (ret == REMOVE_PATH_DELAY)
+ SET_REPLY_AND_LEN(reply, len, "delayed\n");
+ else if (ret == REMOVE_PATH_MAP_ERROR)
+ SET_REPLY_AND_LEN(reply, len, "map reload error. removed\n");
return (ret == REMOVE_PATH_FAILURE);
}
@@ -865,8 +857,7 @@ cli_add_map (void * v, char ** reply, int * len, void * data)
invalid = 1;
pthread_cleanup_pop(1);
if (invalid) {
- *reply = strdup("blacklisted\n");
- *len = strlen(*reply) + 1;
+ SET_REPLY_AND_LEN(reply, len, "blacklisted\n");
condlog(2, "%s: map blacklisted", param);
return 1;
}

93
SOURCES/multipath.conf Normal file
View File

@ -0,0 +1,93 @@
# This is a basic configuration file with some examples, for device mapper
# multipath.
#
# For a complete list of the default configuration values, run either
# multipath -t
# or
# multipathd show config
#
# For a list of configuration options with descriptions, see the multipath.conf
# man page
## By default, devices with vendor = "IBM" and product = "S/390.*" are
## blacklisted. To enable mulitpathing on these devies, uncomment the
## following lines.
#blacklist_exceptions {
# device {
# vendor "IBM"
# product "S/390.*"
# }
#}
## Use user friendly names, instead of using WWIDs as names.
defaults {
user_friendly_names yes
find_multipaths yes
}
##
## Here is an example of how to configure some standard options.
##
#
#defaults {
# udev_dir /dev
# polling_interval 10
# selector "round-robin 0"
# path_grouping_policy multibus
# prio alua
# path_checker readsector0
# rr_min_io 100
# max_fds 8192
# rr_weight priorities
# failback immediate
# no_path_retry fail
# user_friendly_names yes
#}
##
## The wwid line in the following blacklist section is shown as an example
## of how to blacklist devices by wwid. The 2 devnode lines are the
## compiled in default blacklist. If you want to blacklist entire types
## of devices, such as all scsi devices, you should use a devnode line.
## However, if you want to blacklist specific devices, you should use
## a wwid line. Since there is no guarantee that a specific device will
## not change names on reboot (from /dev/sda to /dev/sdb for example)
## devnode lines are not recommended for blacklisting specific devices.
##
#blacklist {
# wwid 26353900f02796769
# devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
# devnode "^hd[a-z]"
#}
#multipaths {
# multipath {
# wwid 3600508b4000156d700012000000b0000
# alias yellow
# path_grouping_policy multibus
# path_checker readsector0
# path_selector "round-robin 0"
# failback manual
# rr_weight priorities
# no_path_retry 5
# }
# multipath {
# wwid 1DEC_____321816758474
# alias red
# }
#}
#devices {
# device {
# vendor "COMPAQ "
# product "HSV110 (C)COMPAQ"
# path_grouping_policy multibus
# path_checker readsector0
# path_selector "round-robin 0"
# hardware_handler "0"
# failback 15
# rr_weight priorities
# no_path_retry queue
# }
# device {
# vendor "COMPAQ "
# product "MSA1000 "
# path_grouping_policy multibus
# }
#}

File diff suppressed because it is too large Load Diff