From 38852f366fed622a14f0357cc8a77d045a92efc5 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Oct 23 2019 14:35:22 +0000 Subject: import device-mapper-multipath-0.4.9-85.el7_2.2 --- diff --git a/.device-mapper-multipath.metadata b/.device-mapper-multipath.metadata new file mode 100644 index 0000000..5ba5987 --- /dev/null +++ b/.device-mapper-multipath.metadata @@ -0,0 +1 @@ +b9f18e2fe72b4f48858dce1ab4148218d39056ec SOURCES/multipath-tools-130222.tgz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85a8481 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/multipath-tools-130222.tgz diff --git a/SOURCES/0001-RH-dont_start_with_no_config.patch b/SOURCES/0001-RH-dont_start_with_no_config.patch new file mode 100644 index 0000000..e894632 --- /dev/null +++ b/SOURCES/0001-RH-dont_start_with_no_config.patch @@ -0,0 +1,16 @@ +--- + multipathd/multipathd.service | 1 + + 1 file changed, 1 insertion(+) + +Index: multipath-tools-130222/multipathd/multipathd.service +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.service ++++ multipath-tools-130222/multipathd/multipathd.service +@@ -2,6 +2,7 @@ + Description=Device-Mapper Multipath Device Controller + Before=iscsi.service iscsid.service lvm2-activation-early.service + After=syslog.target ++ConditionPathExists=/etc/multipath.conf + DefaultDependencies=no + Conflicts=shutdown.target + diff --git a/SOURCES/0002-RH-multipath.rules.patch b/SOURCES/0002-RH-multipath.rules.patch new file mode 100644 index 0000000..a910dc1 --- /dev/null +++ b/SOURCES/0002-RH-multipath.rules.patch @@ -0,0 +1,54 @@ +--- + multipath/Makefile | 3 +++ + multipath/multipath.rules | 24 ++++++++++++++++++++++++ + 2 files changed, 27 insertions(+) + +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- /dev/null ++++ multipath-tools-130222/multipath/multipath.rules +@@ -0,0 +1,24 @@ ++# multipath wants the devmaps presented as meaninglful device names ++# so name them after their devmap name ++SUBSYSTEM!="block", GOTO="end_mpath" ++ ++ENV{MPATH_SBIN_PATH}="/sbin" ++TEST!="$env{MPATH_SBIN_PATH}/multipath", ENV{MPATH_SBIN_PATH}="/usr/sbin" ++ ++ACTION=="add", ENV{DEVTYPE}!="partition", \ ++ ENV{DM_MULTIPATH_DEVICE_PATH}!="1", \ ++ TEST=="/etc/multipath.conf", \ ++ PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -c $tempnode", \ ++ ENV{DM_MULTIPATH_DEVICE_PATH}="1" ++ ++ENV{DM_MULTIPATH_DEVICE_PATH}=="1", ENV{DEVTYPE}!="partition", \ ++ RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}" ++ ++KERNEL!="dm-*", GOTO="end_mpath" ++ENV{DM_UUID}=="mpath-?*|part[0-9]*-mpath-?*", OPTIONS+="link_priority=10" ++ACTION!="change", GOTO="end_mpath" ++ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath" ++ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" ++ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" ++RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode" ++LABEL="end_mpath" +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -21,12 +21,15 @@ $(EXEC): $(OBJS) + install: + $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ ++ $(INSTALL_PROGRAM) -d $(DESTDIR)/lib/udev/rules.d ++ $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/lib/udev/rules.d/62-multipath.rules + $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir) + + uninstall: ++ rm $(DESTDIR)/lib/udev/rules.d/62-multipath.rules + rm $(DESTDIR)$(bindir)/$(EXEC) + rm $(DESTDIR)$(mandir)/$(EXEC).8.gz + rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz diff --git a/SOURCES/0003-RH-Make-build-system-RH-Fedora-friendly.patch b/SOURCES/0003-RH-Make-build-system-RH-Fedora-friendly.patch new file mode 100644 index 0000000..f293c80 --- /dev/null +++ b/SOURCES/0003-RH-Make-build-system-RH-Fedora-friendly.patch @@ -0,0 +1,109 @@ +From f5e11246063b07d6dce6d37d3b74662475baa981 Mon Sep 17 00:00:00 2001 +From: Fabio M. Di Nitto +Date: Thu, 15 Oct 2009 04:39:27 +0200 +Subject: [PATCH 08/12] RH: Make build system RH/Fedora friendly + +Signed-off-by: Fabio M. Di Nitto +--- +:100644 100644 7ec25d5... 06fb625... M Makefile.inc +:100644 100644 21e4ad4... 06d79c0... M kpartx/Makefile +:100644 100644 32d9ef5... 25e1483... M multipathd/Makefile + Makefile.inc | 2 +- + kpartx/Makefile | 10 +++++----- + libmpathpersist/Makefile | 7 ++----- + libmultipath/Makefile | 2 ++ + multipathd/Makefile | 1 + + 5 files changed, 11 insertions(+), 11 deletions(-) + +Index: multipath-tools-130222/Makefile.inc +=================================================================== +--- multipath-tools-130222.orig/Makefile.inc ++++ multipath-tools-130222/Makefile.inc +@@ -29,7 +29,7 @@ multipathdir = $(TOPDIR)/libmultipath + mandir = $(prefix)/usr/share/man/man8 + man5dir = $(prefix)/usr/share/man/man5 + man3dir = $(prefix)/usr/share/man/man3 +-rcdir = $(prefix)/etc/init.d ++rcdir = $(prefix)/etc/rc.d/init.d + syslibdir = $(prefix)/$(LIB) + libdir = $(prefix)/$(LIB)/multipath + unitdir = $(prefix)/lib/systemd/system +Index: multipath-tools-130222/kpartx/Makefile +=================================================================== +--- multipath-tools-130222.orig/kpartx/Makefile ++++ multipath-tools-130222/kpartx/Makefile +@@ -26,17 +26,17 @@ $(EXEC): $(OBJS) + install: $(EXEC) $(EXEC).8 + $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) +- $(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir) +- $(INSTALL_PROGRAM) -m 755 kpartx_id $(DESTDIR)$(libudevdir) +- $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d +- $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/ ++# $(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir) ++# $(INSTALL_PROGRAM) -m 755 kpartx_id $(DESTDIR)$(libudevdir) ++# $(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d ++# $(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/ + $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + + uninstall: + rm -f $(DESTDIR)$(bindir)/$(EXEC) + rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz +- rm -f $(DESTDIR)$(libudevdir)/kpartx_id ++# rm -f $(DESTDIR)$(libudevdir)/kpartx_id + + clean: + rm -f core *.o $(EXEC) *.gz +Index: multipath-tools-130222/multipathd/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipathd/Makefile ++++ multipath-tools-130222/multipathd/Makefile +@@ -35,6 +35,7 @@ install: + $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir) ++ $(INSTALL_PROGRAM) -m 755 multipathd.init.redhat $(DESTDIR)$(rcdir)/$(EXEC) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(unitdir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).service $(DESTDIR)$(unitdir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) +Index: multipath-tools-130222/libmultipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmultipath/Makefile ++++ multipath-tools-130222/libmultipath/Makefile +@@ -46,9 +46,11 @@ install: + $(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir) + $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS) + $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(libdir) ++ ln -sf $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB) + + uninstall: + rm -f $(DESTDIR)$(syslibdir)/$(LIBS) ++ rm -f $(DESTDIR)$(syslibdir)/$(DEVLIB) + + clean: + rm -f core *.a *.o *.gz *.so *.so.* +Index: multipath-tools-130222/libmpathpersist/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/Makefile ++++ multipath-tools-130222/libmpathpersist/Makefile +@@ -28,17 +28,14 @@ $(LIBS): + install: $(LIBS) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir) + $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS) +- $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(syslibdir) + $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(man3dir) +- $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)/usr/include/ +- $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)/usr/share/doc/mpathpersist/ +- ln -sf $(DESTDIR)$(syslibdir)/$(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB) ++ ln -sf $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB) + install -m 644 mpath_persistent_reserve_in.3.gz $(DESTDIR)$(man3dir) + install -m 644 mpath_persistent_reserve_out.3.gz $(DESTDIR)$(man3dir) +- install -m 644 mpath_persist.h $(DESTDIR)/usr/include/ + + uninstall: + rm -f $(DESTDIR)$(syslibdir)/$(LIBS) ++ rm -f $(DESTDIR)$(syslibdir)/$(DEVLIB) + rm $(DESTDIR)$(mandir)/mpath_persistent_reserve_in.3.gz + rm $(DESTDIR)$(mandir)/mpath_persistent_reserve_out.3.gz + diff --git a/SOURCES/0004-RH-multipathd-blacklist-all-by-default.patch b/SOURCES/0004-RH-multipathd-blacklist-all-by-default.patch new file mode 100644 index 0000000..2dda63c --- /dev/null +++ b/SOURCES/0004-RH-multipathd-blacklist-all-by-default.patch @@ -0,0 +1,64 @@ +From 61b2002c6b2752c15b431e400cd614edc8c5b039 Mon Sep 17 00:00:00 2001 +From: Fabio M. Di Nitto +Date: Mon, 19 Oct 2009 07:05:45 +0200 +Subject: [PATCH 09/12] RH: multipathd blacklist all by default + +If there is no configuration installed on the system, blacklist +everything by default. + +BZ#528059 + +Signed-off-by: Fabio M. Di Nitto +--- +:100644 100644 e7e962e... 5aa1ab0... M libmultipath/config.c +:100644 100644 86b1320... 7e90e75... M libmultipath/config.h + libmultipath/config.c | 16 ++++++++++++++++ + libmultipath/config.h | 1 + + 2 files changed, 17 insertions(+) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -21,6 +21,7 @@ + #include "defaults.h" + #include "prio.h" + #include "devmapper.h" ++#include "version.h" + + static int + hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2) +@@ -585,6 +586,21 @@ load_config (char * file) + + } else { + init_keywords(); ++ condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); ++ condlog(0, "A default multipath.conf file is located at"); ++ condlog(0, "/usr/share/doc/device-mapper-multipath-%d.%d.%d/multipath.conf", MULTIPATH_VERSION(VERSION_CODE)); ++ if (conf->blist_devnode == NULL) { ++ conf->blist_devnode = vector_alloc(); ++ if (!conf->blist_devnode) { ++ condlog(0, "cannot allocate blacklist\n"); ++ goto out; ++ } ++ } ++ if (store_ble(conf->blist_devnode, strdup(".*"), ++ ORIGIN_NO_CONFIG)) { ++ condlog(0, "cannot store default no-config blacklist\n"); ++ goto out; ++ } + } + + /* +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -6,6 +6,7 @@ + + #define ORIGIN_DEFAULT 0 + #define ORIGIN_CONFIG 1 ++#define ORIGIN_NO_CONFIG 2 + + /* + * In kernel, fast_io_fail == 0 means immediate failure on rport delete. diff --git a/SOURCES/0005-RH-add-mpathconf.patch b/SOURCES/0005-RH-add-mpathconf.patch new file mode 100644 index 0000000..ce1b2c7 --- /dev/null +++ b/SOURCES/0005-RH-add-mpathconf.patch @@ -0,0 +1,494 @@ +--- + libmultipath/config.c | 1 + multipath/Makefile | 5 + multipath/main.c | 4 + multipath/mpathconf | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++ + multipath/mpathconf.8 | 103 ++++++++++++++++ + 5 files changed, 423 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -589,6 +589,7 @@ load_config (char * file) + condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); + condlog(0, "A default multipath.conf file is located at"); + condlog(0, "/usr/share/doc/device-mapper-multipath-%d.%d.%d/multipath.conf", MULTIPATH_VERSION(VERSION_CODE)); ++ condlog(0, "You can run /sbin/mpathconf to create or modify /etc/multipath.conf"); + if (conf->blist_devnode == NULL) { + conf->blist_devnode = vector_alloc(); + if (!conf->blist_devnode) { +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -17,22 +17,27 @@ $(EXEC): $(OBJS) + $(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS) + $(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)/lib/udev/rules.d + $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/lib/udev/rules.d/62-multipath.rules + $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir) ++ $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(mandir) + + uninstall: + rm $(DESTDIR)/lib/udev/rules.d/62-multipath.rules + rm $(DESTDIR)$(bindir)/$(EXEC) ++ rm $(DESTDIR)$(bindir)/mpathconf + rm $(DESTDIR)$(mandir)/$(EXEC).8.gz + rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz ++ rm $(DESTDIR)$(mandir)/mpathconf.8.gz + + clean: + rm -f core *.o $(EXEC) *.gz +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -433,10 +433,10 @@ main (int argc, char *argv[]) + exit(1); + } + +- if (dm_prereq()) ++ if (load_config(DEFAULT_CONFIGFILE)) + exit(1); + +- if (load_config(DEFAULT_CONFIGFILE)) ++ if (dm_prereq()) + exit(1); + + while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:Brtq")) != EOF ) { +Index: multipath-tools-130222/multipath/mpathconf +=================================================================== +--- /dev/null ++++ multipath-tools-130222/multipath/mpathconf +@@ -0,0 +1,312 @@ ++#!/bin/sh ++# ++# 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 MODULE MULTIPATHD HAVE_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_DEFAULTS HAVE_FRIENDLY HAVE_MULTIPATHD HAVE_MODULE SHOW_STATUS CHANGED_CONFIG ++ ++DEFAULT_CONFIGFILE="/usr/share/doc/device-mapper-multipath-0.4.9/multipath.conf" ++CONFIGFILE="/etc/multipath.conf" ++MULTIPATHDIR="/etc/multipath" ++TMPFILE=/etc/multipath/.multipath.conf.tmp ++ ++function usage ++{ ++ echo "usage: $0 " ++ echo "" ++ echo "Commands:" ++ echo "Enable: --enable " ++ echo "Disable: --disable" ++ echo "Set user_friendly_names (Default n): --user_friendly_names " ++ echo "Set find_multipaths (Default n): --find_multipaths " ++ echo "Load the dm-multipath modules on enable (Default y): --with_module " ++ echo "start/stop/reload multipathd (Default n): --with_multipathd " ++ echo "" ++} ++ ++function parse_args ++{ ++ while [ -n "$1" ]; do ++ case $1 in ++ --enable) ++ ENABLE=1 ++ shift ++ ;; ++ --disable) ++ ENABLE=0 ++ shift ++ ;; ++ --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 ++ ;; ++ --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 ++ ;; ++ *) ++ usage ++ exit ++ esac ++ done ++} ++ ++function validate_args ++{ ++ if [ "$ENABLE" = "0" ] && [ -n "$FRIENDLY" -o -n "$FIND" -o -n "$MODULE" ]; then ++ echo "ignoring extra parameters on disable" ++ FRIENDLY="" ++ FIND="" ++ 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 [ -n "$FIND" ] && [ "$FIND" != "y" -a "$FIND" != "n" ]; then ++ echo "--find_multipaths must be either 'y' or 'n'" ++ exit 1 ++ fi ++ if [ -z "$ENABLE" -a -z "$FIND" -a -z "$FRIENDLY" ]; 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 ++} ++ ++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 ++if [ -f "$CONFIGFILE" ]; then ++ cp $CONFIGFILE $TMPFILE ++elif [ -f "$DEFAULT_CONFIGFILE" ]; then ++ cp $DEFAULT_CONFIGFILE $TMPFILE ++else ++ touch $TMPFILE ++fi ++ ++if grep -q "^blacklist[[:space:]]*{" $TMPFILE ; then ++ HAVE_BLACKLIST=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 service multipathd status > /dev/null ; 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_DEFAULTS" = "1" ]; then ++ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then ++ HAVE_FIND=1 ++ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)" ; then ++ HAVE_FIND=0 ++ fi ++ if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)" ; then ++ HAVE_FRIENDLY=1 ++ elif sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)" ; then ++ HAVE_FRIENDLY=0 ++ fi ++fi ++ ++if [ -n "$SHOW_STATUS" ]; then ++ if [ -z "$HAVE_DISABLE" -o "$HAVE_DISABLE" = 0 ]; then ++ echo "multipath is enabled" ++ else ++ echo "multipath is disabled" ++ fi ++ if [ -z "$HAVE_FIND" -o "$HAVE_FIND" = 0 ]; then ++ echo "find_multipaths is disabled" ++ else ++ echo "find_multipaths is enabled" ++ fi ++ if [ -z "$HAVE_FRIENDLY" -o "$HAVE_FRIENDLY" = 0 ]; then ++ echo "user_friendly_names is disabled" ++ else ++ echo "user_friendly_names is enabled" ++ fi ++ if [ -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 [ -n "$HAVE_MULTIPATHD" ]; then ++ service multipathd status ++ 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" = 1 ]; then ++ if [ "$HAVE_DISABLE" = 1 ]; then ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*devnode \"\.\?\*\"/# devnode ".*"/' $TMPFILE ++ fi ++elif [ "$ENABLE" = 0 ]; then ++ if [ -z "$HAVE_DISABLE" ]; then ++ sed -i '/^blacklist[[:space:]]*{/ a\ ++ devnode "*" ++' $TMPFILE ++ elif [ "$HAVE_DISABLE" = 0 ]; then ++ sed -i '/^blacklist[[:space:]]*{/,/^}/ s/^[[:space:]]*#[#[:space:]]*devnode \"\.\?\*\"/ devnode ".*"/' $TMPFILE ++ fi ++fi ++ ++if [ "$FIND" = "n" ]; then ++ if [ "$HAVE_FIND" = 1 ]; then ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)/ find_multipaths no/' $TMPFILE ++ CHANGED_CONFIG=1 ++ fi ++elif [ "$FIND" = "y" ]; then ++ if [ -z "$HAVE_FIND" ]; then ++ sed -i '/^defaults[[:space:]]*{/ a\ ++ find_multipaths yes ++' $TMPFILE ++ CHANGED_CONFIG=1 ++ elif [ "$HAVE_FIND" = 0 ]; then ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*find_multipaths[[:space:]]*\(no\|0\)/ find_multipaths yes/' $TMPFILE ++ CHANGED_CONFIG=1 ++ fi ++fi ++ ++if [ "$FRIENDLY" = "n" ]; then ++ if [ "$HAVE_FRIENDLY" = 1 ]; then ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(yes\|1\)/ user_friendly_names no/' $TMPFILE ++ CHANGED_CONFIG=1 ++ fi ++elif [ "$FRIENDLY" = "y" ]; then ++ if [ -z "$HAVE_FRIENDLY" ]; then ++ sed -i '/^defaults[[:space:]]*{/ a\ ++ user_friendly_names yes ++' $TMPFILE ++ CHANGED_CONFIG=1 ++ elif [ "$HAVE_FRIENDLY" = 0 ]; then ++ sed -i '/^defaults[[:space:]]*{/,/^}/ s/^[[:space:]]*user_friendly_names[[:space:]]*\(no\|0\)/ user_friendly_names yes/' $TMPFILE ++ CHANGED_CONFIG=1 ++ fi ++fi ++ ++if [ -f "$CONFIGFILE" ]; then ++ cp $CONFIGFILE $CONFIGFILE.old ++ if [ $? != 0 ]; then ++ echo "failed to backup old config file, $CONFIGFILE not updated" ++ exit 1 ++ fi ++fi ++ ++cp $TMPFILE $CONFIGFILE ++if [ $? != 0 ]; then ++ echo "failed to copy new config file into place, check $CONFIGFILE 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 ++ service multipathd start ++ fi ++elif [ "$ENABLE" = 0 ]; then ++ if [ "$HAVE_MULTIPATHD" = 1 ]; then ++ service multipathd stop ++ fi ++elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then ++ service multipathd reload ++fi +Index: multipath-tools-130222/multipath/mpathconf.8 +=================================================================== +--- /dev/null ++++ multipath-tools-130222/multipath/mpathconf.8 +@@ -0,0 +1,103 @@ ++.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. ++ ++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 ++use ++.B /usr/share/doc/device-mapper-multipath-0.4.9/multipath.conf ++as the starting file. This file has ++.B user_friendly_names ++set. If this file does not exist, mpathconf will create ++.B /etc/multipath.conf ++from scratch. For most users, this means that ++.B user_friendly_names ++will be set by default, unless they use the ++.B --user_friendly_names n ++command. ++.SH COMMANDS ++.TP ++.B --enable ++Removes any line that blacklists all device nodes from the ++.B /etc/multipath.conf ++blacklist section. ++.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 --user_friendly_name \fP { \fBy\fP | \fBn\fP } ++If set to \fBy\fP, this adds the line ++.B user_friendly_names yes ++to the ++.B /etc/multipath.conf ++defaults section. If set to \fBn\fP, this removes the line, if present. This ++command can be used along with any other command. ++.TP ++.B --find_multipaths\fP { \fBy\fP | \fBn\fP } ++If set to \fBy\fP, this adds the line ++.B find_multipaths yes ++to the ++.B /etc/multipath.conf ++defaults section. If set to \fBn\fP, this removes the line, if present. This ++command can be used aldong with any other command. ++.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 start 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 diff --git a/SOURCES/0006-RH-add-find-multipaths.patch b/SOURCES/0006-RH-add-find-multipaths.patch new file mode 100644 index 0000000..4a0c364 --- /dev/null +++ b/SOURCES/0006-RH-add-find-multipaths.patch @@ -0,0 +1,222 @@ +--- + libmultipath/config.c | 1 + + libmultipath/config.h | 1 + + libmultipath/configure.c | 11 +++++++++++ + libmultipath/defaults.h | 1 + + libmultipath/dict.c | 34 ++++++++++++++++++++++++++++++++++ + libmultipath/wwids.c | 26 ++++++++++++++++++++++++++ + libmultipath/wwids.h | 1 + + multipath/main.c | 2 +- + multipathd/main.c | 6 ++++++ + 9 files changed, 82 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -547,6 +547,7 @@ load_config (char * file) + conf->reassign_maps = DEFAULT_REASSIGN_MAPS; + conf->checkint = DEFAULT_CHECKINT; + conf->max_checkint = MAX_CHECKINT(conf->checkint); ++ conf->find_multipaths = DEFAULT_FIND_MULTIPATHS; + conf->fast_io_fail = DEFAULT_FAST_IO_FAIL; + conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER; + conf->detect_prio = DEFAULT_DETECT_PRIO; +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -508,6 +508,10 @@ coalesce_paths (struct vectors * vecs, v + + memset(empty_buff, 0, WWID_SIZE); + ++ /* ignore refwwid if it's empty */ ++ if (refwwid && !strlen(refwwid)) ++ refwwid = NULL; ++ + if (force_reload) { + vector_foreach_slot (pathvec, pp1, k) { + pp1->mpp = NULL; +@@ -537,6 +541,13 @@ coalesce_paths (struct vectors * vecs, v + if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE)) + continue; + ++ /* If find_multipaths was selected check if the path is valid */ ++ if (conf->find_multipaths && !refwwid && ++ !should_multipath(pp1, pathvec)) { ++ orphan_path(pp1); ++ continue; ++ } ++ + /* + * at this point, we know we really got a new mp + */ +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -15,6 +15,7 @@ + #define DEFAULT_USER_FRIENDLY_NAMES 0 + #define DEFAULT_VERBOSITY 2 + #define DEFAULT_REASSIGN_MAPS 1 ++#define DEFAULT_FIND_MULTIPATHS 0 + #define DEFAULT_FAST_IO_FAIL 5 + #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF + #define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -585,6 +585,27 @@ def_reservation_key_handler(vector strve + } + + static int ++def_find_multipaths_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->find_multipaths = 0; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ conf->find_multipaths = 1; ++ ++ FREE(buff); ++ return 0; ++} ++ ++static int + def_names_handler(vector strvec) + { + char * buff; +@@ -2700,6 +2721,18 @@ snprint_def_log_checker_err (char * buff + } + + static int ++snprint_def_find_multipaths (char * buff, int len, void * data) ++{ ++ if (conf->find_multipaths == DEFAULT_FIND_MULTIPATHS) ++ return 0; ++ if (!conf->find_multipaths) ++ return snprintf(buff, len, "no"); ++ ++ return snprintf(buff, len, "yes"); ++} ++ ++ ++static int + snprint_def_user_friendly_names (char * buff, int len, void * data) + { + if (conf->user_friendly_names == USER_FRIENDLY_NAMES_ON) +@@ -2833,6 +2866,7 @@ init_keywords(void) + install_keyword("wwids_file", &wwids_file_handler, &snprint_def_wwids_file); + install_keyword("log_checker_err", &def_log_checker_err_handler, &snprint_def_log_checker_err); + install_keyword("reservation_key", &def_reservation_key_handler, &snprint_def_reservation_key); ++ install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths); + install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler_handler); + install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); +Index: multipath-tools-130222/libmultipath/wwids.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.c ++++ multipath-tools-130222/libmultipath/wwids.c +@@ -125,6 +125,32 @@ out: + } + + int ++should_multipath(struct path *pp1, vector pathvec) ++{ ++ int i; ++ struct path *pp2; ++ ++ condlog(4, "checking if %s should be multipathed", pp1->dev); ++ vector_foreach_slot(pathvec, pp2, i) { ++ if (pp1->dev == pp2->dev) ++ continue; ++ if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) { ++ condlog(3, "found multiple paths with wwid %s, " ++ "multipathing %s", pp1->wwid, pp1->dev); ++ return 1; ++ } ++ } ++ if (check_wwids_file(pp1->wwid, 0) < 0) { ++ condlog(3, "wwid %s not in wwids file, skipping %s", ++ pp1->wwid, pp1->dev); ++ return 0; ++ } ++ condlog(3, "found wwid %s in wwids file, multipathing %s", pp1->wwid, ++ pp1->dev); ++ return 1; ++} ++ ++int + remember_wwid(char *wwid) + { + int ret = check_wwids_file(wwid, 1); +Index: multipath-tools-130222/libmultipath/wwids.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.h ++++ multipath-tools-130222/libmultipath/wwids.h +@@ -12,6 +12,7 @@ + "#\n" \ + "# Valid WWIDs:\n" + ++int should_multipath(struct path *pp, vector pathvec); + int remember_wwid(char *wwid); + int check_wwids_file(char *wwid, int write_wwid); + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -333,7 +333,7 @@ configure (void) + /* + * core logic entry point + */ +- r = coalesce_paths(&vecs, NULL, NULL, conf->force_reload); ++ r = coalesce_paths(&vecs, NULL, refwwid, conf->force_reload); + + out: + if (refwwid) +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -471,6 +472,11 @@ rescan: + return 1; + } + ++ if (conf->find_multipaths && ++ !should_multipath(pp, vecs->pathvec)) { ++ orphan_path(pp); ++ return 0; ++ } + condlog(4,"%s: creating new map", pp->dev); + if ((mpp = add_map_with_path(vecs, pp, 1))) { + mpp->action = ACT_CREATE; +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -106,6 +106,7 @@ struct config { + unsigned int dev_loss; + int log_checker_err; + int allow_queueing; ++ int find_multipaths; + uid_t uid; + gid_t gid; + mode_t mode; diff --git a/SOURCES/0007-RH-add-hp_tur-checker.patch b/SOURCES/0007-RH-add-hp_tur-checker.patch new file mode 100644 index 0000000..bc8d73b --- /dev/null +++ b/SOURCES/0007-RH-add-hp_tur-checker.patch @@ -0,0 +1,274 @@ +--- + libmultipath/checkers.h | 3 + + libmultipath/checkers/Makefile | 4 + + libmultipath/checkers/tur.c | 123 +++++++++++++++++++++++++++++++++++++++-- + multipath.conf.annotated | 5 + + 4 files changed, 128 insertions(+), 7 deletions(-) + +Index: multipath-tools-120613/libmultipath/checkers.h +=================================================================== +--- multipath-tools-120613.orig/libmultipath/checkers.h ++++ multipath-tools-120613/libmultipath/checkers.h +@@ -60,6 +60,7 @@ enum path_check_state { + + #define DIRECTIO "directio" + #define TUR "tur" ++#define HP_TUR "hp_tur" + #define HP_SW "hp_sw" + #define RDAC "rdac" + #define EMC_CLARIION "emc_clariion" +@@ -77,6 +78,7 @@ enum path_check_state { + #define CHECKER_MSG_LEN 256 + #define CHECKER_DEV_LEN 256 + #define LIB_CHECKER_NAMELEN 256 ++#define WWID_SIZE 128 + + struct checker { + struct list_head node; +@@ -88,6 +90,7 @@ struct checker { + int disable; + char name[CHECKER_NAME_LEN]; + char message[CHECKER_MSG_LEN]; /* comm with callers */ ++ char wwid[WWID_SIZE]; /* LUN wwid */ + void * context; /* store for persistent data */ + void ** mpcontext; /* store for persistent data shared + multipath-wide. Use MALLOC if +Index: multipath-tools-120613/libmultipath/checkers/Makefile +=================================================================== +--- multipath-tools-120613.orig/libmultipath/checkers/Makefile ++++ multipath-tools-120613/libmultipath/checkers/Makefile +@@ -8,6 +8,7 @@ LIBS= \ + libcheckcciss_tur.so \ + libcheckreadsector0.so \ + libchecktur.so \ ++ libcheckhp_tur.so \ + libcheckdirectio.so \ + libcheckemc_clariion.so \ + libcheckhp_sw.so \ +@@ -23,6 +24,9 @@ libcheckdirectio.so: libsg.o directio.o + libcheck%.so: libsg.o %.o + $(CC) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $^ + ++hp_tur.o: tur.c ++ $(CC) $(CFLAGS) -DCHECK_WWID -c -o $@ $< ++ + install: + $(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir) + +Index: multipath-tools-120613/libmultipath/checkers/tur.c +=================================================================== +--- multipath-tools-120613.orig/libmultipath/checkers/tur.c ++++ multipath-tools-120613/libmultipath/checkers/tur.c +@@ -24,12 +24,101 @@ + #define TUR_CMD_LEN 6 + #define HEAVY_CHECK_COUNT 10 + ++#ifdef CHECK_WWID ++#define MSG_TUR_UP "HP tur checker reports path is up" ++#define MSG_TUR_DOWN "HP tur checker reports path is down" ++#define MSG_TUR_GHOST "HP tur checker reports path is in standby state" ++#define MSG_TUR_RUNNING "HP tur checker still running" ++#define MSG_TUR_TIMEOUT "HP tur checker timed out" ++#define MSG_TUR_FAILED "HP tur checker failed to initialize" ++#define EVPD 0x01 ++#define PAGE_83 0x83 ++#define INQUIRY_CMD 0x12 ++#define INQUIRY_CMDLEN 6 ++#define SCSI_INQ_BUFF_LEN 96 ++#else + #define MSG_TUR_UP "tur checker reports path is up" + #define MSG_TUR_DOWN "tur checker reports path is down" + #define MSG_TUR_GHOST "tur checker reports path is in standby state" + #define MSG_TUR_RUNNING "tur checker still running" + #define MSG_TUR_TIMEOUT "tur checker timed out" + #define MSG_TUR_FAILED "tur checker failed to initialize" ++#endif ++ ++#ifdef CHECK_WWID ++static int ++do_inq(int fd, unsigned int timeout, char * wwid) ++{ ++ int ret = -1; ++ unsigned char inq_cmd[INQUIRY_CMDLEN] = ++ {INQUIRY_CMD, EVPD, PAGE_83, 0, SCSI_INQ_BUFF_LEN, 0 }; ++ unsigned char sense_buffer[32]; ++ unsigned char resp_buffer[SCSI_INQ_BUFF_LEN]; ++ char *pbuff; ++ ++ int m,k; ++ int retry_tur = 5; ++ struct sg_io_hdr io_hdr; ++ ++retry: ++ memset(resp_buffer, 0, sizeof(resp_buffer)); ++ memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); ++ ++ io_hdr.interface_id = 'S'; ++ io_hdr.cmd_len = sizeof(inq_cmd); ++ io_hdr.mx_sb_len = sizeof(sense_buffer); ++ io_hdr.dxfer_direction = -3; // Data transfer from the device. ++ io_hdr.dxfer_len = sizeof(resp_buffer); ++ io_hdr.dxferp = (unsigned char *)resp_buffer; ++ io_hdr.cmdp = inq_cmd; ++ io_hdr.sbp = sense_buffer; ++ io_hdr.timeout = timeout; // IOCTL timeout value. ++ ++ if (ioctl(fd, SG_IO, &io_hdr) < 0) { ++ condlog(0, "SG_IO ioctl failed: %s", strerror(errno)); ++ return ret; ++ } ++ if (io_hdr.info & SG_INFO_OK_MASK){ ++ int key = 0, asc, ascq; ++ ++ if (io_hdr.host_status == DID_BUS_BUSY || ++ io_hdr.host_status == DID_ERROR || ++ io_hdr.host_status == DID_TRANSPORT_DISRUPTED) { ++ if (--retry_tur) ++ goto retry; ++ } ++ if (io_hdr.sb_len_wr > 3) { ++ if (io_hdr.sbp[0] == 0x72 || io_hdr.sbp[0] == 0x73) { ++ key = io_hdr.sbp[1] & 0x0f; ++ asc = io_hdr.sbp[2]; ++ ascq = io_hdr.sbp[3]; ++ } else if (io_hdr.sb_len_wr > 13 && ++ ((io_hdr.sbp[0] & 0x7f) == 0x70 || ++ (io_hdr.sbp[0] & 0x7f) == 0x71)) { ++ key = io_hdr.sbp[2] & 0x0f; ++ asc = io_hdr.sbp[12]; ++ ascq = io_hdr.sbp[13]; ++ } ++ } ++ if (key == 0x6) { ++ /* Unit Attention, retry */ ++ if (--retry_tur) ++ goto retry; ++ } ++ return ret; ++ } ++ ++ pbuff = (char *) resp_buffer; ++ ++ wwid[0] = '3'; ++ for (m = 8, k = 1; m < 11; ++m, k+=2) ++ sprintf(&wwid[k], "%02x", (unsigned int)pbuff[m] & 0xff); ++ for (m = 11; m < 24; ++m, k+=2) ++ sprintf(&wwid[k], "%02x", (unsigned int)pbuff[m] & 0xff); ++ ++ return (ret = 0); ++} ++#endif + + struct tur_checker_context { + dev_t devt; +@@ -43,6 +132,7 @@ struct tur_checker_context { + pthread_cond_t active; + pthread_spinlock_t hldr_lock; + int holders; ++ char wwid[WWID_SIZE]; + char message[CHECKER_MSG_LEN]; + }; + +@@ -100,12 +190,15 @@ void libcheck_free (struct checker * c) + #define TUR_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args); + + int +-tur_check(int fd, unsigned int timeout, char *msg) ++tur_check (int fd, unsigned int timeout, char *msg, char *wwid) + { + struct sg_io_hdr io_hdr; + unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 }; + unsigned char sense_buffer[32]; + int retry_tur = 5; ++#ifdef CHECK_WWID ++ char new_wwid[WWID_SIZE]; ++#endif + + retry: + memset(&io_hdr, 0, sizeof (struct sg_io_hdr)); +@@ -179,6 +272,24 @@ tur_check(int fd, unsigned int timeout, + TUR_MSG(msg, MSG_TUR_DOWN); + return PATH_DOWN; + } ++#ifdef CHECK_WWID ++ if (!do_inq(fd, timeout, new_wwid)) { ++ ++ if(!strcmp(wwid, "\0")) { ++ strcpy(wwid, new_wwid); ++ goto up; ++ } ++ ++ if (strcmp(wwid , new_wwid)) { ++ condlog(0, ++ "hp_tur: Lun collided. new_wwid %s old_wwid %s", ++ new_wwid, wwid); ++ TUR_MSG(msg, MSG_TUR_DOWN); ++ return PATH_DOWN; ++ } ++ } ++up: ++#endif + TUR_MSG(msg, MSG_TUR_UP); + return PATH_UP; + } +@@ -215,7 +326,7 @@ void *tur_thread(void *ctx) + ct->state = PATH_PENDING; + pthread_mutex_unlock(&ct->lock); + +- state = tur_check(ct->fd, ct->timeout, ct->message); ++ state = tur_check(ct->fd, ct->timeout, ct->message, ct->wwid); + + /* TUR checker done */ + pthread_mutex_lock(&ct->lock); +@@ -275,7 +386,7 @@ libcheck_check (struct checker * c) + ct->devt = sb.st_rdev; + + if (c->sync) +- return tur_check(c->fd, c->timeout, c->message); ++ return tur_check(c->fd, c->timeout, c->message, ct->wwid); + + /* + * Async mode +@@ -319,7 +430,8 @@ libcheck_check (struct checker * c) + pthread_mutex_unlock(&ct->lock); + condlog(3, "%d:%d: tur thread not responding, " + "using sync mode", TUR_DEVT(ct)); +- return tur_check(c->fd, c->timeout, c->message); ++ return tur_check(c->fd, c->timeout, c->message, ++ ct->wwid); + } + /* Start new TUR checker */ + ct->state = PATH_UNCHECKED; +@@ -337,7 +449,8 @@ libcheck_check (struct checker * c) + ct->holders--; + condlog(3, "%d:%d: failed to start tur thread, using" + " sync mode", TUR_DEVT(ct)); +- return tur_check(c->fd, c->timeout, c->message); ++ return tur_check(c->fd, c->timeout, c->message, ++ ct->wwid); + } + pthread_attr_destroy(&attr); + tur_timeout(&tsp); +Index: multipath-tools-120613/multipath.conf.annotated +=================================================================== +--- multipath-tools-120613.orig/multipath.conf.annotated ++++ multipath-tools-120613/multipath.conf.annotated +@@ -96,7 +96,8 @@ + # # name : path_checker, checker + # # scope : multipath & multipathd + # # desc : the default method used to determine the paths' state +-# # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac|cciss_tur ++# # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac| ++# cciss_tur|hp_tur + # # default : directio + # # + # path_checker directio +@@ -493,7 +494,7 @@ + # # scope : multipathd & multipathd + # # desc : path checking algorithm to use to check path state + # # values : readsector0|tur|emc_clariion|hp_sw|directio|rdac| +-# # cciss_tur ++# # cciss_tur|hp_tur + # # + # path_checker directio + # diff --git a/SOURCES/0008-RH-revert-partition-changes.patch b/SOURCES/0008-RH-revert-partition-changes.patch new file mode 100644 index 0000000..c563b0e --- /dev/null +++ b/SOURCES/0008-RH-revert-partition-changes.patch @@ -0,0 +1,45 @@ +--- + kpartx/dos.c | 2 -- + kpartx/kpartx.c | 9 ++++++--- + 2 files changed, 6 insertions(+), 5 deletions(-) + +Index: multipath-tools-130222/kpartx/dos.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/dos.c ++++ multipath-tools-130222/kpartx/dos.c +@@ -98,8 +98,6 @@ read_dos_pt(int fd, struct slice all, st + break; + } + if (is_extended(p.sys_type)) { +- sp[i].size = 2; /* extended partitions only get two +- sectors mapped for LILO to install */ + n += read_extended_partition(fd, &p, i, sp+n, ns-n); + } + } +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -516,6 +516,7 @@ main(int argc, char **argv){ + d = c; + while (c) { + for (j = 0; j < n; j++) { ++ uint64_t start; + int k = slices[j].container - 1; + + if (slices[j].size == 0) +@@ -541,9 +542,11 @@ main(int argc, char **argv){ + } + strip_slash(partname); + +- if (safe_sprintf(params, "%s %" PRIu64, +- device, +- slices[j].start)) { ++ start = slices[j].start - slices[k].start; ++ if (safe_sprintf(params, "%d:%d %" PRIu64, ++ slices[k].major, ++ slices[k].minor, ++ start)) { + fprintf(stderr, "params too small\n"); + exit(1); + } diff --git a/SOURCES/0009-RH-RHEL5-style-partitions.patch b/SOURCES/0009-RH-RHEL5-style-partitions.patch new file mode 100644 index 0000000..a2691bb --- /dev/null +++ b/SOURCES/0009-RH-RHEL5-style-partitions.patch @@ -0,0 +1,327 @@ +--- + kpartx/bsd.c | 35 --------------- + kpartx/dos.c | 7 +-- + kpartx/kpartx.c | 123 +++++++------------------------------------------------- + kpartx/kpartx.h | 1 + kpartx/sun.c | 35 --------------- + 5 files changed, 24 insertions(+), 177 deletions(-) + +Index: multipath-tools-130222/kpartx/bsd.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/bsd.c ++++ multipath-tools-130222/kpartx/bsd.c +@@ -50,10 +50,10 @@ int + read_bsd_pt(int fd, struct slice all, struct slice *sp, int ns) { + struct bsd_disklabel *l; + struct bsd_partition *p; +- unsigned int offset = all.start, end; ++ unsigned int offset = all.start; + int max_partitions; + char *bp; +- int n = 0, i, j; ++ int n = 0; + + bp = getblock(fd, offset+1); /* 1 sector suffices */ + if (bp == NULL) +@@ -79,36 +79,5 @@ read_bsd_pt(int fd, struct slice all, st + break; + } + } +- /* +- * Convention has it that the bsd disklabel will always have +- * the 'c' partition spanning the entire disk. +- * So we have to check for contained slices. +- */ +- for(i = 0; i < n; i++) { +- if (sp[i].size == 0) +- continue; +- +- end = sp[i].start + sp[i].size; +- for(j = 0; j < n; j ++) { +- if ( i == j ) +- continue; +- if (sp[j].size == 0) +- continue; +- +- if (sp[i].start < sp[j].start) { +- if (end > sp[j].start && +- end < sp[j].start + sp[j].size) { +- /* Invalid slice */ +- fprintf(stderr, +- "bsd_disklabel: slice %d overlaps with %d\n", i , j); +- sp[i].size = 0; +- } +- } else { +- if (end <= sp[j].start + sp[j].size) { +- sp[i].container = j + 1; +- } +- } +- } +- } + return n; + } +Index: multipath-tools-130222/kpartx/dos.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/dos.c ++++ multipath-tools-130222/kpartx/dos.c +@@ -16,7 +16,7 @@ is_extended(int type) { + } + + static int +-read_extended_partition(int fd, struct partition *ep, int en, ++read_extended_partition(int fd, struct partition *ep, + struct slice *sp, int ns) + { + struct partition p; +@@ -53,7 +53,6 @@ read_extended_partition(int fd, struct p + if (n < ns) { + sp[n].start = here + le32_to_cpu(p.start_sect); + sp[n].size = le32_to_cpu(p.nr_sects); +- sp[n].container = en + 1; + n++; + } else { + fprintf(stderr, +@@ -98,7 +97,9 @@ read_dos_pt(int fd, struct slice all, st + break; + } + if (is_extended(p.sys_type)) { +- n += read_extended_partition(fd, &p, i, sp+n, ns-n); ++ n += read_extended_partition(fd, &p, sp+n, ns-n); ++ /* hide the extended partition itself */ ++ sp[i].size = 2; + } + } + return n; +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -192,7 +192,7 @@ get_hotplug_device(void) + + int + main(int argc, char **argv){ +- int i, j, m, n, op, off, arg, c, d, ro=0; ++ int i, j, m, n, op, off, arg, ro=0; + int fd = -1; + struct slice all; + struct pt *ptp; +@@ -381,49 +381,30 @@ main(int argc, char **argv){ + else + continue; + ++ /* ++ * test for overlap, as in the case of an extended partition ++ * zero their size to avoid mapping ++ */ ++ for (j = 0; j < n; j++) { ++ for (m = j + 1; m < n; m++) { ++ if (slices[m].start > slices[j].start && ++ slices[m].start < slices[j].start + ++ slices[j].size) ++ slices[j].size = 0; ++ } ++ } ++ + switch(what) { + case LIST: +- for (j = 0, c = 0, m = 0; j < n; j++) { ++ for (j = 0; j < n; j++) { + if (slices[j].size == 0) + continue; +- if (slices[j].container > 0) { +- c++; +- continue; +- } +- +- slices[j].minor = m++; + + printf("%s%s%d : 0 %" PRIu64 " %s %" PRIu64"\n", + mapname, delim, j+1, + slices[j].size, device, + slices[j].start); + } +- /* Loop to resolve contained slices */ +- d = c; +- while (c) { +- for (j = 0; j < n; j++) { +- uint64_t start; +- int k = slices[j].container - 1; +- +- if (slices[j].size == 0) +- continue; +- if (slices[j].minor > 0) +- continue; +- if (slices[j].container == 0) +- continue; +- slices[j].minor = m++; +- +- start = slices[j].start - slices[k].start; +- printf("%s%s%d : 0 %" PRIu64 " /dev/dm-%d %" PRIu64 "\n", +- mapname, delim, j+1, +- slices[j].size, +- slices[k].minor, start); +- c--; +- } +- /* Terminate loop if nothing more to resolve */ +- if (d == c) +- break; +- } + + break; + +@@ -462,16 +443,10 @@ main(int argc, char **argv){ + case ADD: + case UPDATE: + /* ADD and UPDATE share the same code that adds new partitions. */ +- for (j = 0, c = 0; j < n; j++) { ++ for (j = 0; j < n; j++) { + if (slices[j].size == 0) + continue; + +- /* Skip all contained slices */ +- if (slices[j].container > 0) { +- c++; +- continue; +- } +- + if (safe_sprintf(partname, "%s%s%d", + mapname, delim, j+1)) { + fprintf(stderr, "partname too small\n"); +@@ -512,72 +487,6 @@ main(int argc, char **argv){ + slices[j].minor, slices[j].size, + DM_TARGET, params); + } +- /* Loop to resolve contained slices */ +- d = c; +- while (c) { +- for (j = 0; j < n; j++) { +- uint64_t start; +- int k = slices[j].container - 1; +- +- if (slices[j].size == 0) +- continue; +- +- /* Skip all existing slices */ +- if (slices[j].minor > 0) +- continue; +- +- /* Skip all simple slices */ +- if (slices[j].container == 0) +- continue; +- +- /* Check container slice */ +- if (slices[k].size == 0) +- fprintf(stderr, "Invalid slice %d\n", +- k); +- +- if (safe_sprintf(partname, "%s%s%d", +- mapname, delim, j+1)) { +- fprintf(stderr, "partname too small\n"); +- exit(1); +- } +- strip_slash(partname); +- +- start = slices[j].start - slices[k].start; +- if (safe_sprintf(params, "%d:%d %" PRIu64, +- slices[k].major, +- slices[k].minor, +- start)) { +- fprintf(stderr, "params too small\n"); +- exit(1); +- } +- +- op = (dm_map_present(partname) ? +- DM_DEVICE_RELOAD : DM_DEVICE_CREATE); +- +- dm_addmap(op, partname, DM_TARGET, params, +- slices[j].size, ro, uuid, j+1, +- buf.st_mode & 0777, +- buf.st_uid, buf.st_gid, +- &cookie); +- +- if (op == DM_DEVICE_RELOAD) +- dm_simplecmd(DM_DEVICE_RESUME, +- partname, 1, +- &cookie); +- +- dm_devn(partname, &slices[j].major, +- &slices[j].minor); +- +- if (verbose) +- printf("add map %s : 0 %" PRIu64 " %s %s\n", +- partname, slices[j].size, +- DM_TARGET, params); +- c--; +- } +- /* Terminate loop */ +- if (d == c) +- break; +- } + + if (what == ADD) { + /* Skip code that removes devmappings for deleted partitions */ +Index: multipath-tools-130222/kpartx/kpartx.h +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.h ++++ multipath-tools-130222/kpartx/kpartx.h +@@ -24,7 +24,6 @@ + struct slice { + uint64_t start; + uint64_t size; +- int container; + int major; + int minor; + }; +Index: multipath-tools-130222/kpartx/sun.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/sun.c ++++ multipath-tools-130222/kpartx/sun.c +@@ -62,8 +62,8 @@ int + read_sun_pt(int fd, struct slice all, struct slice *sp, int ns) { + struct sun_disk_label *l; + struct sun_raw_part *s; +- unsigned int offset = all.start, end; +- int i, j, n; ++ unsigned int offset = all.start; ++ int i, n; + char *bp; + + bp = getblock(fd, offset); +@@ -95,37 +95,6 @@ read_sun_pt(int fd, struct slice all, st + break; + } + } +- /* +- * Convention has it that the SUN disklabel will always have +- * the 'c' partition spanning the entire disk. +- * So we have to check for contained slices. +- */ +- for(i = 0; i < SUN_DISK_MAXPARTITIONS; i++) { +- if (sp[i].size == 0) +- continue; +- +- end = sp[i].start + sp[i].size; +- for(j = 0; j < SUN_DISK_MAXPARTITIONS; j ++) { +- if ( i == j ) +- continue; +- if (sp[j].size == 0) +- continue; +- +- if (sp[i].start < sp[j].start) { +- if (end > sp[j].start && +- end < sp[j].start + sp[j].size) { +- /* Invalid slice */ +- fprintf(stderr, +- "sun_disklabel: slice %d overlaps with %d\n", i , j); +- sp[i].size = 0; +- } +- } else { +- if (end <= sp[j].start + sp[j].size) { +- sp[i].container = j + 1; +- } +- } +- } +- } + return n; + } + diff --git a/SOURCES/0010-RH-dont-remove-map-on-enomem.patch b/SOURCES/0010-RH-dont-remove-map-on-enomem.patch new file mode 100644 index 0000000..1740c10 --- /dev/null +++ b/SOURCES/0010-RH-dont-remove-map-on-enomem.patch @@ -0,0 +1,18 @@ +--- + multipathd/main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -990,7 +990,8 @@ mpvec_garbage_collector (struct vectors + return; + + vector_foreach_slot (vecs->mpvec, mpp, i) { +- if (mpp && mpp->alias && !dm_map_present(mpp->alias)) { ++ if (mpp && mpp->alias && !dm_map_present(mpp->alias) && ++ errno != ENOMEM) { + condlog(2, "%s: remove dead map", mpp->alias); + remove_map_and_stop_waiter(mpp, vecs, 1); + i--; diff --git a/SOURCES/0011-RH-deprecate-uid-gid-mode.patch b/SOURCES/0011-RH-deprecate-uid-gid-mode.patch new file mode 100644 index 0000000..9270d9d --- /dev/null +++ b/SOURCES/0011-RH-deprecate-uid-gid-mode.patch @@ -0,0 +1,90 @@ +--- + multipath.conf.annotated | 53 ----------------------------------------------- + multipath.conf.synthetic | 3 -- + 2 files changed, 56 deletions(-) + +Index: multipath-tools-120123/multipath.conf.annotated +=================================================================== +--- multipath-tools-120123.orig/multipath.conf.annotated ++++ multipath-tools-120123/multipath.conf.annotated +@@ -186,32 +186,6 @@ + # user_friendly_names no + # + # # +-# # name : mode +-# # scope : multipath & multipathd +-# # desc : The mode to use for the multipath device nodes, in octal. +-# # values : 0000 - 0777 +-# # default : determined by the process +-# mode 0644 +-# +-# # +-# # name : uid +-# # scope : multipath & multipathd +-# # desc : The user id to use for the multipath device nodes. You +-# # may use either the numeric or symbolic uid +-# # values : +-# # default : determined by the process +-# uid 0 +-# +-# # +-# # name : gid +-# # scope : multipath & multipathd +-# # desc : The group id to user for the multipath device nodes. You +-# # may use either the numeric or symbolic gid +-# # values : +-# # default : determined by the process +-# gid disk +-# +-# # + # # name : checker_timeout + # # scope : multipath & multipathd + # # desc : The timeout to use for path checkers that issue scsi +@@ -388,33 +362,6 @@ + # # + # flush_on_last_del yes + # +-# # +-# # name : mode +-# # scope : multipath & multipathd +-# # desc : The mode to use for the multipath device nodes, in +-# # octal. +-# # values : 0000 - 0777 +-# # default : determined by the process +-# mode 0644 +-# +-# # +-# # name : uid +-# # scope : multipath & multipathd +-# # desc : The user id to use for the multipath device nodes. +-# # You may use either the numeric or symbolic uid +-# # values : +-# # default : determined by the process +-# uid 0 +-# +-# # +-# # name : gid +-# # scope : multipath & multipathd +-# # desc : The group id to user for the multipath device nodes. +-# # You may use either the numeric or symbolic gid +-# # values : +-# # default : determined by the process +-# gid 0 +-# + # } + # multipath { + # wwid 1DEC_____321816758474 +Index: multipath-tools-120123/multipath.conf.synthetic +=================================================================== +--- multipath-tools-120123.orig/multipath.conf.synthetic ++++ multipath-tools-120123/multipath.conf.synthetic +@@ -18,9 +18,6 @@ + # no_path_retry fail + # queue_without_daemon no + # user_friendly_names no +-# mode 644 +-# uid 0 +-# gid disk + #} + #blacklist { + # wwid 26353900f02796769 diff --git a/SOURCES/0012-RH-kpartx-msg.patch b/SOURCES/0012-RH-kpartx-msg.patch new file mode 100644 index 0000000..7584c84 --- /dev/null +++ b/SOURCES/0012-RH-kpartx-msg.patch @@ -0,0 +1,24 @@ +--- + kpartx/lopart.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/kpartx/lopart.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/lopart.c ++++ multipath-tools-130222/kpartx/lopart.c +@@ -205,13 +205,13 @@ find_unused_loop_device (void) + fprintf(stderr, + "mount: Could not find any loop device, and, according to %s,\n" + " this kernel does not know about the loop device.\n" +- " (If so, then recompile or `insmod loop.o'.)", ++ " (If so, then recompile or `modprobe loop'.)", + PROC_DEVICES); + + else + fprintf(stderr, + "mount: Could not find any loop device. Maybe this kernel does not know\n" +- " about the loop device (then recompile or `insmod loop.o'), or\n" ++ " about the loop device (then recompile or `modprobe loop'), or\n" + " maybe /dev/loop# has the wrong major number?"); + + } else diff --git a/SOURCES/0013-RHBZ-883981-cleanup-rpmdiff-issues.patch b/SOURCES/0013-RHBZ-883981-cleanup-rpmdiff-issues.patch new file mode 100644 index 0000000..03bce17 --- /dev/null +++ b/SOURCES/0013-RHBZ-883981-cleanup-rpmdiff-issues.patch @@ -0,0 +1,148 @@ +--- + Makefile.inc | 9 +++++---- + kpartx/Makefile | 2 +- + libmpathpersist/Makefile | 4 ++-- + libmultipath/Makefile | 1 + + libmultipath/checkers/Makefile | 2 +- + libmultipath/prioritizers/Makefile | 2 +- + multipath/Makefile | 2 +- + multipathd/Makefile | 5 +++-- + 8 files changed, 15 insertions(+), 12 deletions(-) + +Index: multipath-tools-130222/Makefile.inc +=================================================================== +--- multipath-tools-130222.orig/Makefile.inc ++++ multipath-tools-130222/Makefile.inc +@@ -23,15 +23,15 @@ endif + + prefix = + exec_prefix = $(prefix) +-bindir = $(exec_prefix)/sbin ++bindir = $(exec_prefix)/usr/sbin + libudevdir = ${prefix}/lib/udev + multipathdir = $(TOPDIR)/libmultipath + mandir = $(prefix)/usr/share/man/man8 + man5dir = $(prefix)/usr/share/man/man5 + man3dir = $(prefix)/usr/share/man/man3 + rcdir = $(prefix)/etc/rc.d/init.d +-syslibdir = $(prefix)/$(LIB) +-libdir = $(prefix)/$(LIB)/multipath ++syslibdir = $(prefix)/usr/$(LIB) ++libdir = $(prefix)/usr/$(LIB)/multipath + unitdir = $(prefix)/lib/systemd/system + mpathpersistdir = $(TOPDIR)/libmpathpersist + +@@ -42,8 +42,9 @@ ifndef RPM_OPT_FLAGS + RPM_OPT_FLAGS = -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 + endif + ++LDFLAGS += -Wl,-z,relro + OPTFLAGS = $(RPM_OPT_FLAGS) -Wunused -Wstrict-prototypes +-CFLAGS = $(OPTFLAGS) -fPIC -DLIB_STRING=\"${LIB}\" ++CFLAGS = $(OPTFLAGS) -DLIB_STRING=\"${LIB}\" + SHARED_FLAGS = -shared + + %.o: %.c +Index: multipath-tools-130222/multipathd/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipathd/Makefile ++++ multipath-tools-130222/multipathd/Makefile +@@ -5,9 +5,10 @@ include ../Makefile.inc + # + # basic flags setting + # +-CFLAGS += -I$(multipathdir) -I$(mpathpersistdir) ++CFLAGS += -fPIE -DPIE -I$(multipathdir) -I$(mpathpersistdir) + LDFLAGS += -lpthread -ldevmapper -lreadline -ludev -ldl \ +- -L$(multipathdir) -lmultipath -L$(mpathpersistdir) -lmpathpersist ++ -L$(multipathdir) -lmultipath -L$(mpathpersistdir) -lmpathpersist \ ++ -Wl,-z,now -pie + + # + # debuging stuff +Index: multipath-tools-130222/kpartx/Makefile +=================================================================== +--- multipath-tools-130222.orig/kpartx/Makefile ++++ multipath-tools-130222/kpartx/Makefile +@@ -4,7 +4,7 @@ + # + include ../Makefile.inc + +-CFLAGS += -I. -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 ++CFLAGS += -fPIC -I. -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 + + LIBDM_API_COOKIE = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_set_cookie' /usr/include/libdevmapper.h) + +Index: multipath-tools-130222/libmpathpersist/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/Makefile ++++ multipath-tools-130222/libmpathpersist/Makefile +@@ -10,7 +10,7 @@ DEVLIB = libmpathpersist.so + LIBS = $(DEVLIB).$(SONAME) + + +-CFLAGS += -I$(multipathdir) -I$(mpathpersistdir) ++CFLAGS += -fPIC -I$(multipathdir) -I$(mpathpersistdir) + LIBDEPS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath + + OBJS = mpath_persist.o mpath_updatepr.o mpath_pr_ioctl.o +@@ -19,7 +19,7 @@ all: $(LIBS) + + + $(LIBS): +- $(CC) -Wall -fPIC -c $(CFLAGS) *.c ++ $(CC) -Wall -c $(CFLAGS) *.c + $(CC) -shared $(LIBDEPS) -Wl,-soname=$@ $(CFLAGS) -o $@ $(OBJS) + ln -s $(LIBS) $(DEVLIB) + $(GZIP) mpath_persistent_reserve_in.3 > mpath_persistent_reserve_in.3.gz +Index: multipath-tools-130222/libmultipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmultipath/Makefile ++++ multipath-tools-130222/libmultipath/Makefile +@@ -8,6 +8,7 @@ SONAME=0 + DEVLIB = libmultipath.so + LIBS = $(DEVLIB).$(SONAME) + LIBDEPS = -lpthread -ldl -ldevmapper -ludev ++CFLAGS += -fPIC + + OBJS = memory.o parser.o vector.o devmapper.o \ + hwtable.o blacklist.o util.o dmparser.o config.o \ +Index: multipath-tools-130222/libmultipath/checkers/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/Makefile ++++ multipath-tools-130222/libmultipath/checkers/Makefile +@@ -14,7 +14,7 @@ LIBS= \ + libcheckhp_sw.so \ + libcheckrdac.so + +-CFLAGS += -I.. ++CFLAGS += -fPIC -I.. + + all: $(LIBS) + +Index: multipath-tools-130222/libmultipath/prioritizers/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/Makefile ++++ multipath-tools-130222/libmultipath/prioritizers/Makefile +@@ -17,7 +17,7 @@ LIBS = \ + libprioweightedpath.so \ + libprioiet.so + +-CFLAGS += -I.. ++CFLAGS += -fPIC -I.. + + all: $(LIBS) + +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -6,7 +6,7 @@ include ../Makefile.inc + + OBJS = main.o + +-CFLAGS += -I$(multipathdir) ++CFLAGS += -fPIC -I$(multipathdir) + LDFLAGS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath + + EXEC = multipath diff --git a/SOURCES/0014-RH-handle-other-sector-sizes.patch b/SOURCES/0014-RH-handle-other-sector-sizes.patch new file mode 100644 index 0000000..d07e0d8 --- /dev/null +++ b/SOURCES/0014-RH-handle-other-sector-sizes.patch @@ -0,0 +1,31 @@ +--- + kpartx/gpt.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +Index: multipath-tools-120821/kpartx/gpt.c +=================================================================== +--- multipath-tools-120821.orig/kpartx/gpt.c ++++ multipath-tools-120821/kpartx/gpt.c +@@ -637,6 +637,7 @@ read_gpt_pt (int fd, struct slice all, s + uint32_t i; + int n = 0; + int last_used_index=-1; ++ int sector_size_mul = get_sector_size(fd)/512; + + if (!find_valid_gpt (fd, &gpt, &ptes) || !gpt || !ptes) { + if (gpt) +@@ -652,9 +653,11 @@ read_gpt_pt (int fd, struct slice all, s + sp[n].size = 0; + n++; + } else { +- sp[n].start = __le64_to_cpu(ptes[i].starting_lba); +- sp[n].size = __le64_to_cpu(ptes[i].ending_lba) - +- __le64_to_cpu(ptes[i].starting_lba) + 1; ++ sp[n].start = sector_size_mul * ++ __le64_to_cpu(ptes[i].starting_lba); ++ sp[n].size = sector_size_mul * ++ (__le64_to_cpu(ptes[i].ending_lba) - ++ __le64_to_cpu(ptes[i].starting_lba) + 1); + last_used_index=n; + n++; + } diff --git a/SOURCES/0015-RH-fix-output-buffer.patch b/SOURCES/0015-RH-fix-output-buffer.patch new file mode 100644 index 0000000..ffbbaad --- /dev/null +++ b/SOURCES/0015-RH-fix-output-buffer.patch @@ -0,0 +1,62 @@ +--- + libmultipath/print.c | 31 +++++++++++++++++++++++++++---- + 1 file changed, 27 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -8,6 +8,8 @@ + #include + #include + #include ++#include ++#include + + #include "checkers.h" + #include "vector.h" +@@ -24,6 +26,7 @@ + #include "switchgroup.h" + #include "devmapper.h" + #include "uevent.h" ++#include "debug.h" + + #define MAX(x,y) (x > y) ? x : y + #define TAIL (line + len - 1 - c) +@@ -754,12 +757,32 @@ snprint_pathgroup (char * line, int len, + extern void + print_multipath_topology (struct multipath * mpp, int verbosity) + { +- char buff[MAX_LINE_LEN * MAX_LINES] = {}; ++ int resize; ++ char *buff = NULL; ++ char *old = NULL; ++ int len, maxlen = MAX_LINE_LEN * MAX_LINES; + +- memset(&buff[0], 0, MAX_LINE_LEN * MAX_LINES); +- snprint_multipath_topology(&buff[0], MAX_LINE_LEN * MAX_LINES, +- mpp, verbosity); ++ buff = MALLOC(maxlen); ++ do { ++ if (!buff) { ++ if (old) ++ FREE(old); ++ condlog(0, "couldn't allocate memory for list: %s\n", ++ strerror(errno)); ++ return; ++ } ++ ++ len = snprint_multipath_topology(buff, maxlen, mpp, verbosity); ++ resize = (len == maxlen - 1); ++ ++ if (resize) { ++ maxlen *= 2; ++ old = buff; ++ buff = REALLOC(buff, maxlen); ++ } ++ } while (resize); + printf("%s", buff); ++ FREE(buff); + } + + extern int diff --git a/SOURCES/0016-RH-dont-print-ghost-messages.patch b/SOURCES/0016-RH-dont-print-ghost-messages.patch new file mode 100644 index 0000000..3387424 --- /dev/null +++ b/SOURCES/0016-RH-dont-print-ghost-messages.patch @@ -0,0 +1,18 @@ +--- + libmultipath/discovery.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -898,7 +898,8 @@ get_state (struct path * pp, int daemon) + c->timeout = DEF_TIMEOUT; + state = checker_check(c); + condlog(3, "%s: state = %s", pp->dev, checker_state_name(state)); +- if (state != PATH_UP && strlen(checker_message(c))) ++ if (state != PATH_UP && state != PATH_GHOST && ++ strlen(checker_message(c))) + condlog(3, "%s: checker msg is \"%s\"", + pp->dev, checker_message(c)); + return state; diff --git a/SOURCES/0018-RH-fix-factorize.patch b/SOURCES/0018-RH-fix-factorize.patch new file mode 100644 index 0000000..1dfcab5 --- /dev/null +++ b/SOURCES/0018-RH-fix-factorize.patch @@ -0,0 +1,17 @@ +--- + libmultipath/config.c | 2 ++ + 1 file changed, 2 insertions(+) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -437,6 +437,8 @@ restart: + merge_hwe(hwe2, hwe1); + if (hwe_strmatch(hwe2, hwe1) == 0) { + vector_del_slot(hw, i); ++ free_hwe(hwe1); ++ n -= 1; + /* + * Play safe here; we have modified + * the original vector so the outer diff --git a/SOURCES/0019-RH-fix-sockets.patch b/SOURCES/0019-RH-fix-sockets.patch new file mode 100644 index 0000000..8639e20 --- /dev/null +++ b/SOURCES/0019-RH-fix-sockets.patch @@ -0,0 +1,48 @@ +--- + libmpathpersist/mpath_updatepr.c | 3 ++- + libmultipath/uxsock.c | 4 ++-- + 2 files changed, 4 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/libmpathpersist/mpath_updatepr.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_updatepr.c ++++ multipath-tools-130222/libmpathpersist/mpath_updatepr.c +@@ -14,6 +14,7 @@ + #include + #include "memory.h" + #include "../libmultipath/uxsock.h" ++#include "../libmultipath/defaults.h" + + unsigned long mem_allocated; /* Total memory used in Bytes */ + +@@ -25,7 +26,7 @@ int update_prflag(char * arg1, char * ar + size_t len; + int ret = 0; + +- fd = ux_socket_connect("/var/run/multipathd.sock"); ++ fd = ux_socket_connect(DEFAULT_SOCKET); + if (fd == -1) { + condlog (0, "ux socket connect error"); + return 1 ; +Index: multipath-tools-130222/libmultipath/uxsock.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/uxsock.c ++++ multipath-tools-130222/libmultipath/uxsock.c +@@ -31,7 +31,7 @@ int ux_socket_connect(const char *name) + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_LOCAL; + addr.sun_path[0] = '\0'; +- len = strlen(name) + 1; ++ len = strlen(name) + 1 + sizeof(sa_family_t); + strncpy(&addr.sun_path[1], name, len); + + fd = socket(AF_LOCAL, SOCK_STREAM, 0); +@@ -62,7 +62,7 @@ int ux_socket_listen(const char *name) + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_LOCAL; + addr.sun_path[0] = '\0'; +- len = strlen(name) + 1; ++ len = strlen(name) + 1 + sizeof(sa_family_t); + strncpy(&addr.sun_path[1], name, len); + + if (bind(fd, (struct sockaddr *)&addr, len) == -1) { diff --git a/SOURCES/0020-RHBZ-907360-static-pthread-init.patch b/SOURCES/0020-RHBZ-907360-static-pthread-init.patch new file mode 100644 index 0000000..bafa5ce --- /dev/null +++ b/SOURCES/0020-RHBZ-907360-static-pthread-init.patch @@ -0,0 +1,41 @@ +--- + libmultipath/uevent.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +Index: multipath-tools-130222/libmultipath/uevent.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/uevent.c ++++ multipath-tools-130222/libmultipath/uevent.c +@@ -53,8 +53,10 @@ typedef int (uev_trigger)(struct uevent + + pthread_t uevq_thr; + LIST_HEAD(uevq); +-pthread_mutex_t uevq_lock, *uevq_lockp = &uevq_lock; +-pthread_cond_t uev_cond, *uev_condp = &uev_cond; ++pthread_mutex_t uevq_lock = PTHREAD_MUTEX_INITIALIZER; ++pthread_mutex_t *uevq_lockp = &uevq_lock; ++pthread_cond_t uev_cond = PTHREAD_COND_INITIALIZER; ++pthread_cond_t *uev_condp = &uev_cond; + uev_trigger *my_uev_trigger; + void * my_trigger_data; + int servicing_uev; +@@ -409,10 +411,6 @@ int uevent_listen(void) + * thereby not getting to empty the socket's receive buffer queue + * often enough. + */ +- INIT_LIST_HEAD(&uevq); +- +- pthread_mutex_init(uevq_lockp, NULL); +- pthread_cond_init(uev_condp, NULL); + pthread_cleanup_push(uevq_stop, NULL); + + monitor = udev_monitor_new_from_netlink(conf->udev, "udev"); +@@ -525,8 +523,6 @@ out: + if (need_failback) + err = failback_listen(); + pthread_cleanup_pop(1); +- pthread_mutex_destroy(uevq_lockp); +- pthread_cond_destroy(uev_condp); + return err; + } + diff --git a/SOURCES/0021-RHBZ-919119-respect-kernel-cmdline.patch b/SOURCES/0021-RHBZ-919119-respect-kernel-cmdline.patch new file mode 100644 index 0000000..cea1e48 --- /dev/null +++ b/SOURCES/0021-RHBZ-919119-respect-kernel-cmdline.patch @@ -0,0 +1,30 @@ +--- + multipath/multipath.rules | 2 ++ + multipathd/multipathd.service | 1 + + 2 files changed, 3 insertions(+) + +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -2,6 +2,8 @@ + # so name them after their devmap name + SUBSYSTEM!="block", GOTO="end_mpath" + ++IMPORT{cmdline}="nompath" ++ENV{nompath}=="?*", GOTO="end_mpath" + ENV{MPATH_SBIN_PATH}="/sbin" + TEST!="$env{MPATH_SBIN_PATH}/multipath", ENV{MPATH_SBIN_PATH}="/usr/sbin" + +Index: multipath-tools-130222/multipathd/multipathd.service +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.service ++++ multipath-tools-130222/multipathd/multipathd.service +@@ -3,6 +3,7 @@ Description=Device-Mapper Multipath Devi + Before=iscsi.service iscsid.service lvm2-activation-early.service + After=syslog.target + ConditionPathExists=/etc/multipath.conf ++ConditionKernelCommandLine=!nompath + DefaultDependencies=no + Conflicts=shutdown.target + diff --git a/SOURCES/0022-RH-multipathd-check-wwids.patch b/SOURCES/0022-RH-multipathd-check-wwids.patch new file mode 100644 index 0000000..b6e8f42 --- /dev/null +++ b/SOURCES/0022-RH-multipathd-check-wwids.patch @@ -0,0 +1,16 @@ +--- + multipathd/main.c | 1 + + 1 file changed, 1 insertion(+) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1363,6 +1363,7 @@ configure (struct vectors * vecs, int st + + sync_maps_state(mpvec); + vector_foreach_slot(mpvec, mpp, i){ ++ remember_wwid(mpp->wwid); + update_map_pr(mpp); + } + diff --git a/SOURCES/0023-RH-multipath-wipe-wwid.patch b/SOURCES/0023-RH-multipath-wipe-wwid.patch new file mode 100644 index 0000000..6de04bf --- /dev/null +++ b/SOURCES/0023-RH-multipath-wipe-wwid.patch @@ -0,0 +1,239 @@ +--- + libmultipath/discovery.c | 3 + + libmultipath/wwids.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++ + libmultipath/wwids.h | 1 + multipath/main.c | 26 ++++++++++++-- + multipath/multipath.8 | 5 ++ + 5 files changed, 115 insertions(+), 6 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -53,7 +53,8 @@ store_pathinfo (vector pathvec, vector h + goto out; + } + pp->udev = udev_device_ref(udevice); +- err = pathinfo(pp, hwtable, flag | DI_BLACKLIST); ++ err = pathinfo(pp, hwtable, ++ (conf->dry_run == 3)? flag : (flag | DI_BLACKLIST)); + if (err) + goto out; + +Index: multipath-tools-130222/libmultipath/wwids.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.c ++++ multipath-tools-130222/libmultipath/wwids.c +@@ -82,6 +82,92 @@ write_out_wwid(int fd, char *wwid) { + } + + int ++do_remove_wwid(int fd, char *str) { ++ char buf[4097]; ++ char *ptr; ++ off_t start = 0; ++ int bytes; ++ ++ while (1) { ++ if (lseek(fd, start, SEEK_SET) < 0) { ++ condlog(0, "wwid file read lseek failed : %s", ++ strerror(errno)); ++ return -1; ++ } ++ bytes = read(fd, buf, 4096); ++ if (bytes < 0) { ++ if (errno == EINTR || errno == EAGAIN) ++ continue; ++ condlog(0, "failed to read from wwids file : %s", ++ strerror(errno)); ++ return -1; ++ } ++ if (!bytes) /* didn't find wwid to remove */ ++ return 1; ++ buf[bytes] = '\0'; ++ ptr = strstr(buf, str); ++ if (ptr != NULL) { ++ condlog(3, "found '%s'", str); ++ if (lseek(fd, start + (ptr - buf), SEEK_SET) < 0) { ++ condlog(0, "write lseek failed : %s", ++ strerror(errno)); ++ return -1; ++ } ++ while (1) { ++ if (write(fd, "#", 1) < 0) { ++ if (errno == EINTR || errno == EAGAIN) ++ continue; ++ condlog(0, "failed to write to wwids file : %s", strerror(errno)); ++ return -1; ++ } ++ return 0; ++ } ++ } ++ ptr = strrchr(buf, '\n'); ++ if (ptr == NULL) { /* shouldn't happen, assume it is EOF */ ++ condlog(4, "couldn't find newline, assuming end of file"); ++ return 1; ++ } ++ start = start + (ptr - buf) + 1; ++ } ++} ++ ++ ++int ++remove_wwid(char *wwid) { ++ int fd, len, can_write; ++ char *str; ++ int ret = -1; ++ ++ len = strlen(wwid) + 4; /* two slashes the newline and a zero byte */ ++ str = malloc(len); ++ if (str == NULL) { ++ condlog(0, "can't allocate memory to remove wwid : %s", ++ strerror(errno)); ++ return -1; ++ } ++ if (snprintf(str, len, "/%s/\n", wwid) >= len) { ++ condlog(0, "string overflow trying to remove wwid"); ++ goto out; ++ } ++ condlog(3, "removing line '%s' from wwids file", str); ++ fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); ++ if (fd < 0) ++ goto out; ++ if (!can_write) { ++ condlog(0, "cannot remove wwid. wwids file is read-only"); ++ goto out_file; ++ } ++ ret = do_remove_wwid(fd, str); ++ ++out_file: ++ close(fd); ++out: ++ free(str); ++ return ret; ++} ++ ++int + check_wwids_file(char *wwid, int write_wwid) + { + int fd, can_write, found, ret; +Index: multipath-tools-130222/libmultipath/wwids.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.h ++++ multipath-tools-130222/libmultipath/wwids.h +@@ -15,5 +15,6 @@ + int should_multipath(struct path *pp, vector pathvec); + int remember_wwid(char *wwid); + int check_wwids_file(char *wwid, int write_wwid); ++int remove_wwid(char *wwid); + + #endif /* _WWIDS_H */ +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -83,7 +83,7 @@ usage (char * progname) + { + fprintf (stderr, VERSION_STRING); + fprintf (stderr, "Usage:\n"); +- fprintf (stderr, " %s [-c] [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); ++ fprintf (stderr, " %s [-c|-w] [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); + fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); + fprintf (stderr, " %s -F [-v lvl]\n", progname); + fprintf (stderr, " %s -t\n", progname); +@@ -104,6 +104,7 @@ usage (char * progname) + " -B treat the bindings file as read only\n" \ + " -p policy failover|multibus|group_by_serial|group_by_prio\n" \ + " -b fil bindings file location\n" \ ++ " -w remove a device from the wwids file\n" \ + " -p pol force all maps to specified path grouping policy :\n" \ + " . failover one path per priority group\n" \ + " . multibus all paths in one priority group\n" \ +@@ -212,7 +213,6 @@ get_dm_mpvec (vector curmp, vector pathv + + if (!conf->dry_run) + reinstate_paths(mpp); +- remember_wwid(mpp->wwid); + } + return 0; + } +@@ -262,7 +262,7 @@ configure (void) + /* + * if we have a blacklisted device parameter, exit early + */ +- if (dev && conf->dev_type == DEV_DEVNODE && ++ if (dev && conf->dev_type == DEV_DEVNODE && conf->dry_run != 3 && + (filter_devnode(conf->blist_devnode, + conf->elist_devnode, dev) > 0)) { + if (conf->dry_run == 2) +@@ -284,6 +284,17 @@ configure (void) + condlog(3, "scope is nul"); + goto out; + } ++ if (conf->dry_run == 3) { ++ r = remove_wwid(refwwid); ++ if (r == 0) ++ printf("wwid '%s' removed\n", refwwid); ++ else if (r == 1) { ++ printf("wwid '%s' not in wwids file\n", ++ refwwid); ++ r = 0; ++ } ++ goto out; ++ } + condlog(3, "scope limited to %s", refwwid); + if (conf->dry_run == 2) { + if (check_wwids_file(refwwid, 0) == 0){ +@@ -439,7 +450,7 @@ main (int argc, char *argv[]) + if (dm_prereq()) + exit(1); + +- while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:Brtq")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:Brtqw")) != EOF ) { + switch(arg) { + case 1: printf("optarg : %s\n",optarg); + break; +@@ -504,6 +515,9 @@ main (int argc, char *argv[]) + case 'h': + usage(argv[0]); + exit(0); ++ case 'w': ++ conf->dry_run = 3; ++ break; + case ':': + fprintf(stderr, "Missing option argument\n"); + usage(argv[0]); +@@ -555,6 +569,10 @@ main (int argc, char *argv[]) + condlog(0, "the -c option requires a path to check"); + goto out; + } ++ if (conf->dry_run == 3 && !conf->dev) { ++ condlog(0, "the -w option requires a device"); ++ goto out; ++ } + if (conf->remove == FLUSH_ONE) { + if (conf->dev_type == DEV_DEVMAP) { + r = dm_suspend_and_flush_map(conf->dev); +Index: multipath-tools-130222/multipath/multipath.8 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.8 ++++ multipath-tools-130222/multipath/multipath.8 +@@ -8,7 +8,7 @@ multipath \- Device mapper target autoco + .RB [\| \-b\ \c + .IR bindings_file \|] + .RB [\| \-d \|] +-.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r \|] ++.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-w \|] + .RB [\| \-p\ \c + .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|] + .RB [\| device \|] +@@ -68,6 +68,9 @@ check if a block device should be a path + .B \-q + allow device tables with queue_if_no_path when multipathd is not running + .TP ++.B \-w ++remove the wwid for the specified device from the wwids file ++.TP + .BI \-p " policy" + force new maps to use the specified policy: + .RS 1.2i diff --git a/SOURCES/0024-RH-multipath-wipe-wwids.patch b/SOURCES/0024-RH-multipath-wipe-wwids.patch new file mode 100644 index 0000000..b91836c --- /dev/null +++ b/SOURCES/0024-RH-multipath-wipe-wwids.patch @@ -0,0 +1,164 @@ +--- + libmultipath/wwids.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + libmultipath/wwids.h | 1 + + multipath/main.c | 29 +++++++++++++++++++++++++++-- + multipath/multipath.8 | 5 ++++- + 4 files changed, 76 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/libmultipath/wwids.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.c ++++ multipath-tools-130222/libmultipath/wwids.c +@@ -82,6 +82,50 @@ write_out_wwid(int fd, char *wwid) { + } + + int ++replace_wwids(vector mp) ++{ ++ int i, fd, can_write; ++ struct multipath * mpp; ++ size_t len; ++ int ret = -1; ++ ++ fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER); ++ if (fd < 0) ++ goto out; ++ if (!can_write) { ++ condlog(0, "cannot replace wwids. wwids file is read-only"); ++ goto out_file; ++ } ++ if (ftruncate(fd, 0) < 0) { ++ condlog(0, "cannot truncate wwids file : %s", strerror(errno)); ++ goto out_file; ++ } ++ len = strlen(WWIDS_FILE_HEADER); ++ if (write_all(fd, WWIDS_FILE_HEADER, len) != len) { ++ condlog(0, "Can't write wwid file header : %s", ++ strerror(errno)); ++ /* cleanup partially written header */ ++ if (ftruncate(fd, 0) < 0) ++ condlog(0, "Cannot truncate header : %s", ++ strerror(errno)); ++ goto out_file; ++ } ++ if (!mp || !mp->allocated) { ++ ret = 0; ++ goto out_file; ++ } ++ vector_foreach_slot(mp, mpp, i) { ++ if (write_out_wwid(fd, mpp->wwid) < 0) ++ goto out_file; ++ } ++ ret = 0; ++out_file: ++ close(fd); ++out: ++ return ret; ++} ++ ++int + do_remove_wwid(int fd, char *str) { + char buf[4097]; + char *ptr; +Index: multipath-tools-130222/libmultipath/wwids.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.h ++++ multipath-tools-130222/libmultipath/wwids.h +@@ -16,5 +16,6 @@ int should_multipath(struct path *pp, ve + int remember_wwid(char *wwid); + int check_wwids_file(char *wwid, int write_wwid); + int remove_wwid(char *wwid); ++int replace_wwids(vector mp); + + #endif /* _WWIDS_H */ +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -83,7 +83,7 @@ usage (char * progname) + { + fprintf (stderr, VERSION_STRING); + fprintf (stderr, "Usage:\n"); +- fprintf (stderr, " %s [-c|-w] [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); ++ fprintf (stderr, " %s [-c|-w|-W] [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); + fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); + fprintf (stderr, " %s -F [-v lvl]\n", progname); + fprintf (stderr, " %s -t\n", progname); +@@ -105,6 +105,7 @@ usage (char * progname) + " -p policy failover|multibus|group_by_serial|group_by_prio\n" \ + " -b fil bindings file location\n" \ + " -w remove a device from the wwids file\n" \ ++ " -W reset the wwids file include only the current devices\n" \ + " -p pol force all maps to specified path grouping policy :\n" \ + " . failover one path per priority group\n" \ + " . multibus all paths in one priority group\n" \ +@@ -450,7 +451,7 @@ main (int argc, char *argv[]) + if (dm_prereq()) + exit(1); + +- while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:Brtqw")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:BrtqwW")) != EOF ) { + switch(arg) { + case 1: printf("optarg : %s\n",optarg); + break; +@@ -518,6 +519,9 @@ main (int argc, char *argv[]) + case 'w': + conf->dry_run = 3; + break; ++ case 'W': ++ conf->dry_run = 4; ++ break; + case ':': + fprintf(stderr, "Missing option argument\n"); + usage(argv[0]); +@@ -573,6 +577,27 @@ main (int argc, char *argv[]) + condlog(0, "the -w option requires a device"); + goto out; + } ++ if (conf->dry_run == 4) { ++ struct multipath * mpp; ++ int i; ++ vector curmp; ++ ++ curmp = vector_alloc(); ++ if (!curmp) { ++ condlog(0, "can't allocate memory for mp list"); ++ goto out; ++ } ++ if (dm_get_maps(curmp) == 0) ++ r = replace_wwids(curmp); ++ if (r == 0) ++ printf("successfully reset wwids\n"); ++ vector_foreach_slot_backwards(curmp, mpp, i) { ++ vector_del_slot(curmp, i); ++ free_multipath(mpp, KEEP_PATHS); ++ } ++ vector_free(curmp); ++ goto out; ++ } + if (conf->remove == FLUSH_ONE) { + if (conf->dev_type == DEV_DEVMAP) { + r = dm_suspend_and_flush_map(conf->dev); +Index: multipath-tools-130222/multipath/multipath.8 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.8 ++++ multipath-tools-130222/multipath/multipath.8 +@@ -8,7 +8,7 @@ multipath \- Device mapper target autoco + .RB [\| \-b\ \c + .IR bindings_file \|] + .RB [\| \-d \|] +-.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-w \|] ++.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-w | \-W \|] + .RB [\| \-p\ \c + .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|] + .RB [\| device \|] +@@ -71,6 +71,9 @@ allow device tables with queue_if_no_pat + .B \-w + remove the wwid for the specified device from the wwids file + .TP ++.B \-W ++reset the wwids file to only include the current multipath devices ++.TP + .BI \-p " policy" + force new maps to use the specified policy: + .RS 1.2i diff --git a/SOURCES/0025-UPBZ-916668_add_maj_min.patch b/SOURCES/0025-UPBZ-916668_add_maj_min.patch new file mode 100644 index 0000000..615533d --- /dev/null +++ b/SOURCES/0025-UPBZ-916668_add_maj_min.patch @@ -0,0 +1,29 @@ +--- + multipathd/main.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -537,7 +537,8 @@ rescan: + goto fail_map; + + if (retries >= 0) { +- condlog(2, "%s path added to devmap %s", pp->dev, mpp->alias); ++ condlog(2, "%s [%s]: path added to devmap %s", ++ pp->dev, pp->dev_t, mpp->alias); + return 0; + } + else +@@ -642,8 +643,8 @@ ev_remove_path (struct path *pp, struct + } + sync_map_state(mpp); + +- condlog(2, "%s: path removed from map %s", +- pp->dev, mpp->alias); ++ condlog(2, "%s [%s]: path removed from map %s", ++ pp->dev, pp->dev_t, mpp->alias); + } + } + diff --git a/SOURCES/0026-fix-checker-time.patch b/SOURCES/0026-fix-checker-time.patch new file mode 100644 index 0000000..e05ef58 --- /dev/null +++ b/SOURCES/0026-fix-checker-time.patch @@ -0,0 +1,23 @@ +--- + multipathd/main.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1226,11 +1226,10 @@ check_path (struct vectors * vecs, struc + pp->checkint = 2 * pp->checkint; + else + pp->checkint = conf->max_checkint; +- +- pp->tick = pp->checkint; +- condlog(4, "%s: delay next check %is", +- pp->dev_t, pp->tick); + } ++ pp->tick = pp->checkint; ++ condlog(4, "%s: delay next check %is", ++ pp->dev_t, pp->tick); + } + } + else if (newstate == PATH_DOWN) { diff --git a/SOURCES/0027-RH-get-wwid.patch b/SOURCES/0027-RH-get-wwid.patch new file mode 100644 index 0000000..04217b4 --- /dev/null +++ b/SOURCES/0027-RH-get-wwid.patch @@ -0,0 +1,17 @@ +--- + libmultipath/structs_vec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -106,7 +106,7 @@ orphan_paths (vector pathvec, struct mul + static void + set_multipath_wwid (struct multipath * mpp) + { +- if (mpp->wwid) ++ if (strlen(mpp->wwid)) + return; + + dm_get_uuid(mpp->alias, mpp->wwid); diff --git a/SOURCES/0028-RHBZ-929078-refresh-udev-dev.patch b/SOURCES/0028-RHBZ-929078-refresh-udev-dev.patch new file mode 100644 index 0000000..c14ddb5 --- /dev/null +++ b/SOURCES/0028-RHBZ-929078-refresh-udev-dev.patch @@ -0,0 +1,55 @@ +--- + libmultipath/discovery.c | 2 +- + multipathd/main.c | 19 ++++++++++++++++++- + 2 files changed, 19 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -1034,7 +1034,7 @@ pathinfo (struct path *pp, vector hwtabl + } + } + +- if (path_state == PATH_UP && (mask & DI_WWID) && !strlen(pp->wwid)) ++ if ((mask & DI_WWID) && !strlen(pp->wwid)) + get_uid(pp); + if (mask & DI_BLACKLIST && mask & DI_WWID) { + if (filter_wwid(conf->blist_wwid, conf->elist_wwid, +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -376,7 +376,7 @@ static int + uev_add_path (struct uevent *uev, struct vectors * vecs) + { + struct path *pp; +- int ret; ++ int ret, i; + + condlog(2, "%s: add path (uevent)", uev->kernel); + if (strstr(uev->kernel, "..") != NULL) { +@@ -393,6 +393,23 @@ uev_add_path (struct uevent *uev, struct + uev->kernel); + if (pp->mpp) + return 0; ++ if (!strlen(pp->wwid)) { ++ udev_device_unref(pp->udev); ++ pp->udev = udev_device_ref(uev->udev); ++ ret = pathinfo(pp, conf->hwtable, ++ DI_ALL | DI_BLACKLIST); ++ if (ret == 2) { ++ i = find_slot(vecs->pathvec, (void *)pp); ++ if (i != -1) ++ vector_del_slot(vecs->pathvec, i); ++ free_path(pp); ++ return 0; ++ } else if (ret == 1) { ++ condlog(0, "%s: failed to reinitialize path", ++ uev->kernel); ++ return 1; ++ } ++ } + } else { + /* + * get path vital state diff --git a/SOURCES/0029-RH-no-prio-put-msg.patch b/SOURCES/0029-RH-no-prio-put-msg.patch new file mode 100644 index 0000000..6ebdae0 --- /dev/null +++ b/SOURCES/0029-RH-no-prio-put-msg.patch @@ -0,0 +1,20 @@ +--- + libmultipath/prio.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/prio.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prio.c ++++ multipath-tools-130222/libmultipath/prio.c +@@ -162,7 +162,10 @@ void prio_put (struct prio * dst) + if (!dst) + return; + +- src = prio_lookup(dst->name); ++ if (!strlen(dst->name)) ++ src = NULL; ++ else ++ src = prio_lookup(dst->name); + memset(dst, 0x0, sizeof(struct prio)); + free_prio(src); + } diff --git a/SOURCES/0030-RHBZ-916528-override-queue-no-daemon.patch b/SOURCES/0030-RHBZ-916528-override-queue-no-daemon.patch new file mode 100644 index 0000000..e663ded --- /dev/null +++ b/SOURCES/0030-RHBZ-916528-override-queue-no-daemon.patch @@ -0,0 +1,200 @@ +--- + libmultipath/dict.c | 10 ++++------ + libmultipath/structs.h | 2 +- + multipathd/cli.c | 3 +++ + multipathd/cli.h | 2 ++ + multipathd/cli_handlers.c | 18 ++++++++++++++++++ + multipathd/cli_handlers.h | 2 ++ + multipathd/main.c | 2 ++ + multipathd/multipathd.init.redhat | 14 ++++++++++---- + 8 files changed, 42 insertions(+), 11 deletions(-) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -438,14 +438,11 @@ def_queue_without_daemon(vector strvec) + if (!buff) + return 1; + +- if (!strncmp(buff, "off", 3) || !strncmp(buff, "no", 2) || +- !strncmp(buff, "0", 1)) +- conf->queue_without_daemon = QUE_NO_DAEMON_OFF; +- else if (!strncmp(buff, "on", 2) || !strncmp(buff, "yes", 3) || ++ if (!strncmp(buff, "on", 2) || !strncmp(buff, "yes", 3) || + !strncmp(buff, "1", 1)) + conf->queue_without_daemon = QUE_NO_DAEMON_ON; + else +- conf->queue_without_daemon = QUE_NO_DAEMON_UNDEF; ++ conf->queue_without_daemon = QUE_NO_DAEMON_OFF; + + free(buff); + return 0; +@@ -2670,8 +2667,9 @@ snprint_def_queue_without_daemon (char * + case QUE_NO_DAEMON_OFF: + return snprintf(buff, len, "\"no\""); + case QUE_NO_DAEMON_ON: +- case QUE_NO_DAEMON_UNDEF: + return snprintf(buff, len, "\"yes\""); ++ case QUE_NO_DAEMON_FORCE: ++ return snprintf(buff, len, "\"forced\""); + } + return 0; + } +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -67,9 +67,9 @@ enum pgstates { + }; + + enum queue_without_daemon_states { +- QUE_NO_DAEMON_UNDEF, + QUE_NO_DAEMON_OFF, + QUE_NO_DAEMON_ON, ++ QUE_NO_DAEMON_FORCE, + }; + + enum pgtimeouts { +Index: multipath-tools-130222/multipathd/cli.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.c ++++ multipath-tools-130222/multipathd/cli.c +@@ -162,6 +162,7 @@ load_keys (void) + r += add_key(keys, "resize", RESIZE, 0); + r += add_key(keys, "reset", RESET, 0); + r += add_key(keys, "reload", RELOAD, 0); ++ r += add_key(keys, "forcequeueing", FORCEQ, 0); + r += add_key(keys, "disablequeueing", DISABLEQ, 0); + r += add_key(keys, "restorequeueing", RESTOREQ, 0); + r += add_key(keys, "paths", PATHS, 0); +@@ -459,6 +460,8 @@ cli_init (void) { + add_handler(GETPRSTATUS+MAP, NULL); + add_handler(SETPRSTATUS+MAP, NULL); + add_handler(UNSETPRSTATUS+MAP, NULL); ++ add_handler(FORCEQ+DAEMON, NULL); ++ add_handler(RESTOREQ+DAEMON, NULL); + + return 0; + } +Index: multipath-tools-130222/multipathd/cli.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli.h ++++ multipath-tools-130222/multipathd/cli.h +@@ -10,6 +10,7 @@ enum { + __RESIZE, + __RESET, + __RELOAD, ++ __FORCEQ, + __DISABLEQ, + __RESTOREQ, + __PATHS, +@@ -45,6 +46,7 @@ enum { + #define RESIZE (1 << __RESIZE) + #define RESET (1 << __RESET) + #define RELOAD (1 << __RELOAD) ++#define FORCEQ (1 << __FORCEQ) + #define DISABLEQ (1 << __DISABLEQ) + #define RESTOREQ (1 << __RESTOREQ) + #define PATHS (1 << __PATHS) +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -628,6 +628,24 @@ cli_resize(void *v, char **reply, int *l + } + + int ++cli_force_no_daemon_q(void * v, char ** reply, int * len, void * data) ++{ ++ condlog(2, "force queue_without_daemon (operator)"); ++ if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF) ++ conf->queue_without_daemon = QUE_NO_DAEMON_FORCE; ++ return 0; ++} ++ ++int ++cli_restore_no_daemon_q(void * v, char ** reply, int * len, void * data) ++{ ++ condlog(2, "restore queue_without_daemon (operator)"); ++ if (conf->queue_without_daemon == QUE_NO_DAEMON_FORCE) ++ conf->queue_without_daemon = QUE_NO_DAEMON_OFF; ++ return 0; ++} ++ ++int + cli_restore_queueing(void *v, char **reply, int *len, void *data) + { + struct vectors * vecs = (struct vectors *)data; +Index: multipath-tools-130222/multipathd/cli_handlers.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.h ++++ multipath-tools-130222/multipathd/cli_handlers.h +@@ -28,6 +28,8 @@ int cli_suspend(void * v, char ** reply, + int cli_resume(void * v, char ** reply, int * len, void * data); + int cli_reinstate(void * v, char ** reply, int * len, void * data); + int cli_fail(void * v, char ** reply, int * len, void * data); ++int cli_force_no_daemon_q(void * v, char ** reply, int * len, void * data); ++int cli_restore_no_daemon_q(void * v, char ** reply, int * len, void * data); + int cli_quit(void * v, char ** reply, int * len, void * data); + int cli_shutdown(void * v, char ** reply, int * len, void * data); + int cli_reassign (void * v, char ** reply, int * len, void * data); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -904,6 +904,8 @@ uxlsnrloop (void * ap) + set_handler_callback(GETPRSTATUS+MAP, cli_getprstatus); + set_handler_callback(SETPRSTATUS+MAP, cli_setprstatus); + set_handler_callback(UNSETPRSTATUS+MAP, cli_unsetprstatus); ++ set_handler_callback(FORCEQ+DAEMON, cli_force_no_daemon_q); ++ set_handler_callback(RESTOREQ+DAEMON, cli_restore_no_daemon_q); + + umask(077); + uxsock_listen(&uxsock_trigger, ap); +Index: multipath-tools-130222/multipathd/multipathd.init.redhat +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.init.redhat ++++ multipath-tools-130222/multipathd/multipathd.init.redhat +@@ -81,23 +81,28 @@ force_stop() { + echo + } + +-stop() { ++check_root() { + root_dev=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $1; }}' /etc/mtab) + dm_num=`dmsetup info -c --noheadings -o minor $root_dev 2> /dev/null` + if [ $? -eq 0 ]; then + root_dm_device="dm-$dm_num" + [ -d $syspath/$root_dm_device ] && teardown_slaves $syspath/$root_dm_device + fi ++} + +- force_stop ++force_queue_without_daemon() { ++ $DAEMON forcequeueing daemon + } + + restart() { +- stop ++ force_queue_without_daemon ++ check_root ++ force_stop + start + } + + force_restart() { ++ force_queue_without_daemon + force_stop + start + } +@@ -115,7 +120,8 @@ start) + start + ;; + stop) +- stop ++ check_root ++ force_stop + ;; + force-stop) + force_stop diff --git a/SOURCES/0031-RHBZ-957188-kpartx-use-dm-name.patch b/SOURCES/0031-RHBZ-957188-kpartx-use-dm-name.patch new file mode 100644 index 0000000..282c517 --- /dev/null +++ b/SOURCES/0031-RHBZ-957188-kpartx-use-dm-name.patch @@ -0,0 +1,17 @@ +--- + kpartx/kpartx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -348,7 +348,7 @@ main(int argc, char **argv){ + if (delim == NULL) { + delim = malloc(DELIM_SIZE); + memset(delim, 0, DELIM_SIZE); +- set_delimiter(device, delim); ++ set_delimiter(mapname, delim); + } + + fd = open(device, O_RDONLY); diff --git a/SOURCES/0032-RHBZ-956464-mpathconf-defaults.patch b/SOURCES/0032-RHBZ-956464-mpathconf-defaults.patch new file mode 100644 index 0000000..d63c32e --- /dev/null +++ b/SOURCES/0032-RHBZ-956464-mpathconf-defaults.patch @@ -0,0 +1,19 @@ +--- + multipath/mpathconf | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/multipath/mpathconf +=================================================================== +--- multipath-tools-130222.orig/multipath/mpathconf ++++ multipath-tools-130222/multipath/mpathconf +@@ -31,8 +31,8 @@ function usage + echo "Commands:" + echo "Enable: --enable " + echo "Disable: --disable" +- echo "Set user_friendly_names (Default n): --user_friendly_names " +- echo "Set find_multipaths (Default n): --find_multipaths " ++ echo "Set user_friendly_names (Default y): --user_friendly_names " ++ echo "Set find_multipaths (Default y): --find_multipaths " + echo "Load the dm-multipath modules on enable (Default y): --with_module " + echo "start/stop/reload multipathd (Default n): --with_multipathd " + echo "" diff --git a/SOURCES/0033-RHBZ-829963-e-series-conf.patch b/SOURCES/0033-RHBZ-829963-e-series-conf.patch new file mode 100644 index 0000000..d8fc119 --- /dev/null +++ b/SOURCES/0033-RHBZ-829963-e-series-conf.patch @@ -0,0 +1,44 @@ +This patch provides hwtable updates for NETAPP/LSI/ENGENIO E-Series arrays, +utilizing new features to detect TPGS support, automatically. + +Signed-off-by: Sean Stewart + +--- +--- + libmultipath/hwtable.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1046,9 +1046,13 @@ static struct hwentry default_hw[] = { + .checker_name = RDAC, + .prio_name = PRIO_RDAC, + }, +- /* LSI/Engenio/NetApp E-Series RDAC storage */ ++ /* LSI/Engenio/NetApp E-Series RDAC storage ++ * ++ * Maintainer : Sean Stewart ++ * Mail : sean.stewart@netapp.com ++ */ + { +- .vendor = "(LSI|ENGENIO)", ++ .vendor = "(NETAPP|LSI|ENGENIO)", + .product = "INF-01-00", + .bl_product = "Universal Xport", + .features = "2 pg_init_retries 50", +@@ -1056,10 +1060,12 @@ static struct hwentry default_hw[] = { + .pgpolicy = GROUP_BY_PRIO, + .pgfailback = -FAILBACK_IMMEDIATE, + .rr_weight = RR_WEIGHT_NONE, +- .no_path_retry = 15, ++ .no_path_retry = 30, + .checker_name = RDAC, + .prio_name = PRIO_RDAC, + .prio_args = NULL, ++ .detect_prio = DETECT_PRIO_ON, ++ .retain_hwhandler = RETAIN_HWHANDLER_ON, + }, + { + .vendor = "STK", diff --git a/SOURCES/0034-RHBZ-851416-mpathconf-display.patch b/SOURCES/0034-RHBZ-851416-mpathconf-display.patch new file mode 100644 index 0000000..e9e00ce --- /dev/null +++ b/SOURCES/0034-RHBZ-851416-mpathconf-display.patch @@ -0,0 +1,53 @@ +--- + multipath/mpathconf | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +Index: multipath-tools-130222/multipath/mpathconf +=================================================================== +--- multipath-tools-130222.orig/multipath/mpathconf ++++ multipath-tools-130222/multipath/mpathconf +@@ -159,7 +159,7 @@ if [ -z "$MODULE" -o "$MODULE" = "y" ]; + fi + + if [ "$MULTIPATHD" = "y" ]; then +- if service multipathd status > /dev/null ; then ++ if /bin/systemctl status multipathd.service > /dev/null 2>&1 ; then + HAVE_MULTIPATHD=1 + else + HAVE_MULTIPATHD=0 +@@ -210,8 +210,17 @@ if [ -n "$SHOW_STATUS" ]; then + echo "dm_multipath module is not loaded" + fi + fi +- if [ -n "$HAVE_MULTIPATHD" ]; then +- service multipathd status ++ 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 +@@ -301,12 +310,12 @@ if [ "$ENABLE" = 1 ]; then + modprobe dm_multipath + fi + if [ "$HAVE_MULTIPATHD" = 0 ]; then +- service multipathd start ++ systemctl start multipathd.service + fi + elif [ "$ENABLE" = 0 ]; then + if [ "$HAVE_MULTIPATHD" = 1 ]; then +- service multipathd stop ++ systemctl stop multipathd.service + fi + elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then +- service multipathd reload ++ systemctl reload multipathd.service + fi diff --git a/SOURCES/0035-RHBZ-891921-list-mpp.patch b/SOURCES/0035-RHBZ-891921-list-mpp.patch new file mode 100644 index 0000000..b0bb7a2 --- /dev/null +++ b/SOURCES/0035-RHBZ-891921-list-mpp.patch @@ -0,0 +1,33 @@ +--- + libmultipath/print.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -422,6 +422,16 @@ snprint_path_serial (char * buff, size_t + } + + static int ++snprint_path_mpp (char * buff, size_t len, struct path * pp) ++{ ++ if (!pp->mpp) ++ return snprintf(buff, len, "[orphan]"); ++ if (!pp->mpp->alias) ++ return snprintf(buff, len, "[unknown]"); ++ return snprint_str(buff, len, pp->mpp->alias); ++} ++ ++static int + snprint_path_checker (char * buff, size_t len, struct path * pp) + { + struct checker * c = &pp->checker; +@@ -464,6 +474,7 @@ struct path_data pd[] = { + {'p', "pri", 0, snprint_pri}, + {'S', "size", 0, snprint_path_size}, + {'z', "serial", 0, snprint_path_serial}, ++ {'m', "multipath", 0, snprint_path_mpp}, + {0, NULL, 0 , NULL} + }; + diff --git a/SOURCES/0036-RHBZ-949239-load-multipath-module.patch b/SOURCES/0036-RHBZ-949239-load-multipath-module.patch new file mode 100644 index 0000000..04a6f68 --- /dev/null +++ b/SOURCES/0036-RHBZ-949239-load-multipath-module.patch @@ -0,0 +1,16 @@ +--- + multipathd/multipathd.service | 1 + + 1 file changed, 1 insertion(+) + +Index: multipath-tools-130222/multipathd/multipathd.service +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.service ++++ multipath-tools-130222/multipathd/multipathd.service +@@ -10,6 +10,7 @@ Conflicts=shutdown.target + [Service] + Type=forking + PIDFile=/var/run/multipathd.pid ++ExecStartPre=/sbin/modprobe dm-multipath + ExecStart=/sbin/multipathd + ExecReload=/sbin/multipathd reconfigure + #ExecStop=/path/to/scrip delete-me if not necessary diff --git a/SOURCES/0037-RHBZ-768873-fix-rename.patch b/SOURCES/0037-RHBZ-768873-fix-rename.patch new file mode 100644 index 0000000..7e05bd0 --- /dev/null +++ b/SOURCES/0037-RHBZ-768873-fix-rename.patch @@ -0,0 +1,87 @@ +--- + libmultipath/devmapper.c | 45 --------------------------------------------- + libmultipath/devmapper.h | 1 - + libmultipath/propsel.c | 2 -- + 3 files changed, 48 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -917,51 +917,6 @@ out: + return r; + } + +-extern char * +-dm_get_name(char *uuid) +-{ +- struct dm_task *dmt; +- struct dm_info info; +- char *prefixed_uuid, *name = NULL; +- const char *nametmp; +- +- dmt = dm_task_create(DM_DEVICE_INFO); +- if (!dmt) +- return NULL; +- +- prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(uuid) + 1); +- if (!prefixed_uuid) { +- condlog(0, "cannot create prefixed uuid : %s", +- strerror(errno)); +- goto freeout; +- } +- sprintf(prefixed_uuid, UUID_PREFIX "%s", uuid); +- if (!dm_task_set_uuid(dmt, prefixed_uuid)) +- goto freeout; +- +- if (!dm_task_run(dmt)) +- goto freeout; +- +- if (!dm_task_get_info(dmt, &info) || !info.exists) +- goto freeout; +- +- nametmp = dm_task_get_name(dmt); +- if (nametmp && strlen(nametmp)) { +- name = MALLOC(strlen(nametmp) + 1); +- if (name) +- strcpy(name, nametmp); +- } else { +- condlog(2, "%s: no device-mapper name found", uuid); +- } +- +-freeout: +- if (prefixed_uuid) +- FREE(prefixed_uuid); +- dm_task_destroy(dmt); +- +- return name; +-} +- + int + dm_geteventnr (char *name) + { +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -40,7 +40,6 @@ int dm_remove_partmaps (const char * map + int dm_get_uuid(char *name, char *uuid); + int dm_get_info (char * mapname, struct dm_info ** dmi); + int dm_rename (char * old, char * new); +-char * dm_get_name(char * uuid); + int dm_reassign(const char * mapname); + int dm_reassign_table(const char *name, char *old, char *new); + int dm_setgeometry(struct multipath *mpp); +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -263,8 +263,6 @@ select_alias (struct multipath * mp) + conf->bindings_file, mp->alias_prefix, conf->bindings_read_only); + } + if (mp->alias == NULL) +- mp->alias = dm_get_name(mp->wwid); +- if (mp->alias == NULL) + mp->alias = STRDUP(mp->wwid); + } + diff --git a/SOURCES/0038-RHBZ-799860-netapp-config.patch b/SOURCES/0038-RHBZ-799860-netapp-config.patch new file mode 100644 index 0000000..3b91f9b --- /dev/null +++ b/SOURCES/0038-RHBZ-799860-netapp-config.patch @@ -0,0 +1,16 @@ +--- + libmultipath/hwtable.c | 1 + + 1 file changed, 1 insertion(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -794,6 +794,7 @@ static struct hwentry default_hw[] = { + .prio_name = PRIO_ONTAP, + .prio_args = NULL, + .retain_hwhandler = RETAIN_HWHANDLER_ON, ++ .user_friendly_names = USER_FRIENDLY_NAMES_OFF, + .detect_prio = DETECT_PRIO_ON, + }, + /* diff --git a/SOURCES/0039-RH-detect-prio-fix.patch b/SOURCES/0039-RH-detect-prio-fix.patch new file mode 100644 index 0000000..941a570 --- /dev/null +++ b/SOURCES/0039-RH-detect-prio-fix.patch @@ -0,0 +1,28 @@ +--- + libmultipath/propsel.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -384,10 +384,17 @@ select_getuid (struct path * pp) + void + detect_prio(struct path * pp) + { ++ int ret; + struct prio *p = &pp->prio; + +- if (get_target_port_group_support(pp->fd) > 0) +- prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS); ++ if (get_target_port_group_support(pp->fd) <= 0) ++ return; ++ ret = get_target_port_group(pp->fd); ++ if (ret < 0) ++ return; ++ if (get_asymmetric_access_state(pp->fd, ret) < 0) ++ return; ++ prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS); + } + + extern int diff --git a/SOURCES/0040-RH-bindings-fix.patch b/SOURCES/0040-RH-bindings-fix.patch new file mode 100644 index 0000000..c56f352 --- /dev/null +++ b/SOURCES/0040-RH-bindings-fix.patch @@ -0,0 +1,101 @@ +--- + libmultipath/alias.c | 39 ++++++++++++++++++++++++++++++--------- + 1 file changed, 30 insertions(+), 9 deletions(-) + +Index: multipath-tools-130222/libmultipath/alias.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.c ++++ multipath-tools-130222/libmultipath/alias.c +@@ -46,11 +46,11 @@ format_devname(char *name, int id, int l + memset(name,0, len); + strcpy(name, prefix); + for (pos = len - 1; pos >= prefix_len; pos--) { ++ id--; + name[pos] = 'a' + id % 26; + if (id < 26) + break; + id /= 26; +- id--; + } + memmove(name + prefix_len, name + pos, len - pos); + name[prefix_len + len - pos] = '\0'; +@@ -66,13 +66,22 @@ scan_devname(char *alias, char *prefix) + if (!prefix || strncmp(alias, prefix, strlen(prefix))) + return -1; + ++ if (strlen(alias) == strlen(prefix)) ++ return -1; ++ ++ if (strlen(alias) > strlen(prefix) + 7) ++ /* id of 'aaaaaaaa' overflows int */ ++ return -1; ++ + c = alias + strlen(prefix); + while (*c != '\0' && *c != ' ' && *c != '\t') { ++ if (*c < 'a' || *c > 'z') ++ return -1; + i = *c - 'a'; + n = ( n * 26 ) + i; ++ if (n < 0) ++ return -1; + c++; +- if (*c < 'a' || *c > 'z') +- break; + n++; + } + +@@ -84,7 +93,9 @@ lookup_binding(FILE *f, char *map_wwid, + { + char buf[LINE_MAX]; + unsigned int line_nr = 0; +- int id = 0; ++ int id = 1; ++ int biggest_id = 1; ++ int smallest_bigger_id = INT_MAX; + + *map_alias = NULL; + +@@ -100,8 +111,12 @@ lookup_binding(FILE *f, char *map_wwid, + if (!alias) /* blank line */ + continue; + curr_id = scan_devname(alias, prefix); +- if (curr_id >= id) +- id = curr_id + 1; ++ if (curr_id == id) ++ id++; ++ if (curr_id > biggest_id) ++ biggest_id = curr_id; ++ if (curr_id > id && curr_id < smallest_bigger_id) ++ smallest_bigger_id = curr_id; + wwid = strtok(NULL, " \t"); + if (!wwid){ + condlog(3, +@@ -116,11 +131,17 @@ lookup_binding(FILE *f, char *map_wwid, + if (*map_alias == NULL) + condlog(0, "Cannot copy alias from bindings " + "file : %s", strerror(errno)); +- return id; ++ return 0; + } + } + condlog(3, "No matching wwid [%s] in bindings file.", map_wwid); +- return id; ++ if (id < 0) { ++ condlog(0, "no more available user_friendly_names"); ++ return 0; ++ } ++ if (id < smallest_bigger_id) ++ return id; ++ return biggest_id + 1; + } + + static int +@@ -254,7 +275,7 @@ get_user_friendly_alias(char *wwid, char + return NULL; + } + +- if (!alias && can_write && !bindings_read_only) ++ if (!alias && can_write && !bindings_read_only && id) + alias = allocate_binding(fd, wwid, id, prefix); + + fclose(f); diff --git a/SOURCES/0041-RH-check-for-erofs.patch b/SOURCES/0041-RH-check-for-erofs.patch new file mode 100644 index 0000000..d29d78d --- /dev/null +++ b/SOURCES/0041-RH-check-for-erofs.patch @@ -0,0 +1,121 @@ +--- + libmultipath/configure.c | 7 ------ + libmultipath/devmapper.c | 53 ++++++++++++++++++++++------------------------- + libmultipath/devmapper.h | 2 - + 3 files changed, 25 insertions(+), 37 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -384,24 +384,17 @@ domap (struct multipath * mpp, char * pa + + r = dm_addmap_create(mpp, params); + +- if (!r) +- r = dm_addmap_create_ro(mpp, params); +- + lock_multipath(mpp, 0); + break; + + case ACT_RELOAD: + r = dm_addmap_reload(mpp, params); +- if (!r) +- r = dm_addmap_reload_ro(mpp, params); + if (r) + r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias); + break; + + case ACT_RESIZE: + r = dm_addmap_reload(mpp, params); +- if (!r) +- r = dm_addmap_reload_ro(mpp, params); + if (r) + r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1); + break; +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -298,42 +298,39 @@ dm_addmap (int task, const char *target, + return r; + } + +-static int +-_dm_addmap_create (struct multipath *mpp, char * params, int ro) { +- int r; +- r = dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, 1, ro); +- /* +- * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD. +- * Failing the second part leaves an empty map. Clean it up. +- */ +- if (!r && dm_map_present(mpp->alias)) { +- condlog(3, "%s: failed to load map (a path might be in use)", +- mpp->alias); +- dm_flush_map_nosync(mpp->alias); ++extern int ++dm_addmap_create (struct multipath *mpp, char * params) { ++ int ro; ++ ++ for (ro = 0; ro <= 1; ro++) { ++ int err; ++ ++ if (dm_addmap(DM_DEVICE_CREATE, TGT_MPATH, mpp, params, 1, ro)) ++ return 1; ++ /* ++ * DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD. ++ * Failing the second part leaves an empty map. Clean it up. ++ */ ++ err = errno; ++ if (dm_map_present(mpp->alias)) { ++ condlog(3, "%s: failed to load map (a path might be in use)", mpp->alias); ++ dm_flush_map_nosync(mpp->alias); ++ } ++ if (err != EROFS) ++ break; + } +- return r; ++ return 0; + } + + #define ADDMAP_RW 0 + #define ADDMAP_RO 1 + + extern int +-dm_addmap_create (struct multipath *mpp, char *params) { +- return _dm_addmap_create(mpp, params, ADDMAP_RW); +-} +- +-extern int +-dm_addmap_create_ro (struct multipath *mpp, char *params) { +- return _dm_addmap_create(mpp, params, ADDMAP_RO); +-} +- +-extern int + dm_addmap_reload (struct multipath *mpp, char *params) { +- return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW); +-} +- +-extern int +-dm_addmap_reload_ro (struct multipath *mpp, char *params) { ++ if (dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RW)) ++ return 1; ++ if (errno != EROFS) ++ return 0; + return dm_addmap(DM_DEVICE_RELOAD, TGT_MPATH, mpp, params, 0, ADDMAP_RO); + } + +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -12,9 +12,7 @@ int dm_drv_version (unsigned int * versi + int dm_simplecmd_flush (int, const char *, int); + int dm_simplecmd_noflush (int, const char *); + int dm_addmap_create (struct multipath *mpp, char *params); +-int dm_addmap_create_ro (struct multipath *mpp, char *params); + int dm_addmap_reload (struct multipath *mpp, char *params); +-int dm_addmap_reload_ro (struct multipath *mpp, char *params); + int dm_map_present (const char *); + int dm_get_map(char *, unsigned long long *, char *); + int dm_get_status(char *, char *); diff --git a/SOURCES/0042-UP-fix-signal-handling.patch b/SOURCES/0042-UP-fix-signal-handling.patch new file mode 100644 index 0000000..4b4b40b --- /dev/null +++ b/SOURCES/0042-UP-fix-signal-handling.patch @@ -0,0 +1,493 @@ +--- + libmultipath/file.c | 4 +- + libmultipath/lock.c | 9 ---- + libmultipath/lock.h | 1 + libmultipath/log_pthread.c | 22 ----------- + libmultipath/waiter.c | 2 - + multipathd/cli_handlers.c | 4 +- + multipathd/main.c | 90 ++++++++++++++++++++------------------------- + multipathd/main.h | 3 + + multipathd/uxlsnr.c | 21 +++++++--- + multipathd/uxlsnr.h | 3 + + 10 files changed, 65 insertions(+), 94 deletions(-) + +Index: multipath-tools-130222/libmultipath/file.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/file.c ++++ multipath-tools-130222/libmultipath/file.c +@@ -98,7 +98,7 @@ lock_file(int fd, char *file_name) + sigaddset(&set, SIGALRM); + + sigaction(SIGALRM, &act, &oldact); +- sigprocmask(SIG_UNBLOCK, &set, &oldset); ++ pthread_sigmask(SIG_UNBLOCK, &set, &oldset); + + alarm(FILE_TIMEOUT); + err = fcntl(fd, F_SETLKW, &lock); +@@ -112,7 +112,7 @@ lock_file(int fd, char *file_name) + condlog(0, "%s is locked. Giving up.", file_name); + } + +- sigprocmask(SIG_SETMASK, &oldset, NULL); ++ pthread_sigmask(SIG_SETMASK, &oldset, NULL); + sigaction(SIGALRM, &oldact, NULL); + return err; + } +Index: multipath-tools-130222/libmultipath/lock.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/lock.c ++++ multipath-tools-130222/libmultipath/lock.c +@@ -1,16 +1,7 @@ + #include +-#include + #include "lock.h" + #include + +-void block_signal (int signum, sigset_t *old) +-{ +- sigset_t set; +- sigemptyset(&set); +- sigaddset(&set, signum); +- pthread_sigmask(SIG_BLOCK, &set, old); +-} +- + void cleanup_lock (void * data) + { + unlock ((*(struct mutex_lock *)data)); +Index: multipath-tools-130222/libmultipath/lock.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/lock.h ++++ multipath-tools-130222/libmultipath/lock.h +@@ -29,6 +29,5 @@ struct mutex_lock { + #endif + + void cleanup_lock (void * data); +-void block_signal(int signum, sigset_t *old); + + #endif /* _LOCK_H */ +Index: multipath-tools-130222/libmultipath/log_pthread.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/log_pthread.c ++++ multipath-tools-130222/libmultipath/log_pthread.c +@@ -22,26 +22,13 @@ pthread_cond_t logev_cond; + + int logq_running; + +-static void +-sigusr1 (int sig) +-{ +- pthread_mutex_lock(&logq_lock); +- log_reset("multipathd"); +- pthread_mutex_unlock(&logq_lock); +-} +- + void log_safe (int prio, const char * fmt, va_list ap) + { +- sigset_t old; +- + if (log_thr == (pthread_t)0) { + syslog(prio, fmt, ap); + return; + } + +- block_signal(SIGUSR1, &old); +- block_signal(SIGHUP, NULL); +- + pthread_mutex_lock(&logq_lock); + log_enqueue(prio, fmt, ap); + pthread_mutex_unlock(&logq_lock); +@@ -49,8 +36,6 @@ void log_safe (int prio, const char * fm + pthread_mutex_lock(&logev_lock); + pthread_cond_signal(&logev_cond); + pthread_mutex_unlock(&logev_lock); +- +- pthread_sigmask(SIG_SETMASK, &old, NULL); + } + + void log_thread_flush (void) +@@ -81,15 +66,8 @@ static void flush_logqueue (void) + + static void * log_thread (void * et) + { +- struct sigaction sig; + int running; + +- sig.sa_handler = sigusr1; +- sigemptyset(&sig.sa_mask); +- sig.sa_flags = 0; +- if (sigaction(SIGUSR1, &sig, NULL) < 0) +- logdbg(stderr, "Cannot set signal handler"); +- + pthread_mutex_lock(&logev_lock); + logq_running = 1; + pthread_mutex_unlock(&logev_lock); +Index: multipath-tools-130222/libmultipath/waiter.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/waiter.c ++++ multipath-tools-130222/libmultipath/waiter.c +@@ -157,8 +157,6 @@ void *waitevent (void *et) + waiter = (struct event_thread *)et; + pthread_cleanup_push(free_waiter, et); + +- block_signal(SIGUSR1, NULL); +- block_signal(SIGHUP, NULL); + while (1) { + r = waiteventloop(waiter); + +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -939,8 +939,8 @@ int + cli_shutdown (void * v, char ** reply, int * len, void * data) + { + condlog(3, "shutdown (operator)"); +- +- return exit_daemon(0); ++ exit_daemon(); ++ return 0; + } + + int +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + + /* +@@ -52,6 +53,7 @@ + #include + #include + #include ++#include + + #include "main.h" + #include "pidfile.h" +@@ -81,13 +83,11 @@ struct mpath_event_param + + unsigned int mpath_mx_alloc_len; + +-pthread_cond_t exit_cond = PTHREAD_COND_INITIALIZER; +-pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER; +- + int logsink; + enum daemon_status running_state; + pid_t daemon_pid; + ++static sem_t exit_sem; + /* + * global copy of vecs for use in sig handlers + */ +@@ -838,9 +838,6 @@ out: + static void * + ueventloop (void * ap) + { +- block_signal(SIGUSR1, NULL); +- block_signal(SIGHUP, NULL); +- + if (uevent_listen()) + condlog(0, "error starting uevent listener"); + +@@ -850,9 +847,6 @@ ueventloop (void * ap) + static void * + uevqloop (void * ap) + { +- block_signal(SIGUSR1, NULL); +- block_signal(SIGHUP, NULL); +- + if (uevent_dispatch(&uev_trigger, ap)) + condlog(0, "error starting uevent dispatcher"); + +@@ -861,9 +855,6 @@ uevqloop (void * ap) + static void * + uxlsnrloop (void * ap) + { +- block_signal(SIGUSR1, NULL); +- block_signal(SIGHUP, NULL); +- + if (cli_init()) + return NULL; + +@@ -913,18 +904,10 @@ uxlsnrloop (void * ap) + return NULL; + } + +-int +-exit_daemon (int status) ++void ++exit_daemon (void) + { +- if (status != 0) +- fprintf(stderr, "bad exit status. see daemon.log\n"); +- +- if (running_state != DAEMON_SHUTDOWN) { +- pthread_mutex_lock(&exit_mutex); +- pthread_cond_signal(&exit_cond); +- pthread_mutex_unlock(&exit_mutex); +- } +- return status; ++ sem_post(&exit_sem); + } + + const char * +@@ -1287,7 +1270,6 @@ checkerloop (void *ap) + struct path *pp; + int count = 0; + unsigned int i; +- sigset_t old; + + mlockall(MCL_CURRENT | MCL_FUTURE); + vecs = (struct vectors *)ap; +@@ -1301,7 +1283,6 @@ checkerloop (void *ap) + } + + while (1) { +- block_signal(SIGHUP, &old); + pthread_cleanup_push(cleanup_lock, &vecs->lock); + lock(vecs->lock); + pthread_testcancel(); +@@ -1325,7 +1306,6 @@ checkerloop (void *ap) + } + + lock_cleanup_pop(vecs->lock); +- pthread_sigmask(SIG_SETMASK, &old, NULL); + sleep(1); + } + return NULL; +@@ -1485,36 +1465,56 @@ signal_set(int signo, void (*func) (int) + return (osig.sa_handler); + } + ++void ++handle_signals(void) ++{ ++ if (reconfig_sig && running_state == DAEMON_RUNNING) { ++ condlog(2, "reconfigure (signal)"); ++ pthread_cleanup_push(cleanup_lock, ++ &gvecs->lock); ++ lock(gvecs->lock); ++ pthread_testcancel(); ++ reconfigure(gvecs); ++ lock_cleanup_pop(gvecs->lock); ++ } ++ if (log_reset_sig) { ++ condlog(2, "reset log (signal)"); ++ pthread_mutex_lock(&logq_lock); ++ log_reset("multipathd"); ++ pthread_mutex_unlock(&logq_lock); ++ } ++ reconfig_sig = 0; ++ log_reset_sig = 0; ++} ++ + static void + sighup (int sig) + { +- condlog(2, "reconfigure (SIGHUP)"); +- +- if (running_state != DAEMON_RUNNING) +- return; +- +- reconfigure(gvecs); +- +-#ifdef _DEBUG_ +- dbg_free_final(NULL); +-#endif ++ reconfig_sig = 1; + } + + static void + sigend (int sig) + { +- exit_daemon(0); ++ exit_daemon(); + } + + static void + sigusr1 (int sig) + { +- condlog(3, "SIGUSR1 received"); ++ log_reset_sig = 1; + } + + static void + signal_init(void) + { ++ sigset_t set; ++ ++ sigemptyset(&set); ++ sigaddset(&set, SIGHUP); ++ sigaddset(&set, SIGUSR1); ++ pthread_sigmask(SIG_BLOCK, &set, NULL); ++ + signal_set(SIGHUP, sighup); + signal_set(SIGUSR1, sigusr1); + signal_set(SIGINT, sigend); +@@ -1587,10 +1587,11 @@ child (void * param) + struct vectors * vecs; + struct multipath * mpp; + int i; +- sigset_t set; + int rc, pid_rc; + + mlockall(MCL_CURRENT | MCL_FUTURE); ++ sem_init(&exit_sem, 0, 0); ++ signal_init(); + + setup_thread_attr(&misc_attr, 64 * 1024, 1); + setup_thread_attr(&waiter_attr, 32 * 1024, 1); +@@ -1650,7 +1651,6 @@ child (void * param) + if (!vecs) + exit(1); + +- signal_init(); + setscheduler(); + set_oom_adj(); + +@@ -1693,25 +1693,17 @@ child (void * param) + } + pthread_attr_destroy(&misc_attr); + +- pthread_mutex_lock(&exit_mutex); + /* Startup complete, create logfile */ + pid_rc = pidfile_create(DEFAULT_PIDFILE, daemon_pid); + /* Ignore errors, we can live without */ + + running_state = DAEMON_RUNNING; +- pthread_cond_wait(&exit_cond, &exit_mutex); +- /* Need to block these to avoid deadlocking */ +- sigemptyset(&set); +- sigaddset(&set, SIGTERM); +- sigaddset(&set, SIGINT); +- pthread_sigmask(SIG_BLOCK, &set, NULL); + + /* + * exit path + */ ++ while(sem_wait(&exit_sem) != 0); /* Do nothing */ + running_state = DAEMON_SHUTDOWN; +- pthread_sigmask(SIG_UNBLOCK, &set, NULL); +- block_signal(SIGHUP, NULL); + lock(vecs->lock); + if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF) + vector_foreach_slot(vecs->mpvec, mpp, i) +Index: multipath-tools-130222/multipathd/main.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.h ++++ multipath-tools-130222/multipathd/main.h +@@ -16,7 +16,7 @@ struct prin_resp; + + extern pid_t daemon_pid; + +-int exit_daemon(int); ++void exit_daemon(void); + const char * daemon_status(void); + int reconfigure (struct vectors *); + int ev_add_path (struct path *, struct vectors *); +@@ -35,5 +35,6 @@ int mpath_pr_event_handle(struct path *p + void * mpath_pr_event_handler_fn (void * ); + int update_map_pr(struct multipath *mpp); + void * mpath_pr_event_handler_fn (void * pathp ); ++void handle_signals(void); + + #endif /* MAIN_H */ +Index: multipath-tools-130222/multipathd/uxlsnr.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/uxlsnr.c ++++ multipath-tools-130222/multipathd/uxlsnr.c +@@ -8,6 +8,7 @@ + /* + * A simple domain socket listener + */ ++#define _GNU_SOURCE + #include + #include + #include +@@ -19,20 +20,21 @@ + #include + #include + #include +- ++#include + #include +- + #include + #include + #include + #include ++#include + #include + #include + ++#include "main.h" + #include "cli.h" + #include "uxlsnr.h" + +-#define SLEEP_TIME 5000 ++struct timespec sleep_time = {5, 0}; + + struct client { + int fd; +@@ -42,6 +44,8 @@ struct client { + static struct client *clients; + static unsigned num_clients; + struct pollfd *polls; ++volatile sig_atomic_t reconfig_sig = 0; ++volatile sig_atomic_t log_reset_sig = 0; + + /* + * handle a new client joining +@@ -104,6 +108,7 @@ void * uxsock_listen(int (*uxsock_trigge + int rlen; + char *inbuf; + char *reply; ++ sigset_t mask; + + ux_sock = ux_socket_listen(DEFAULT_SOCKET); + +@@ -115,7 +120,9 @@ void * uxsock_listen(int (*uxsock_trigge + pthread_cleanup_push(uxsock_cleanup, NULL); + + polls = (struct pollfd *)MALLOC(0); +- ++ pthread_sigmask(SIG_SETMASK, NULL, &mask); ++ sigdelset(&mask, SIGHUP); ++ sigdelset(&mask, SIGUSR1); + while (1) { + struct client *c; + int i, poll_count; +@@ -132,11 +139,13 @@ void * uxsock_listen(int (*uxsock_trigge + } + + /* most of our life is spent in this call */ +- poll_count = poll(polls, i, SLEEP_TIME); ++ poll_count = ppoll(polls, i, &sleep_time, &mask); + + if (poll_count == -1) { +- if (errno == EINTR) ++ if (errno == EINTR) { ++ handle_signals(); + continue; ++ } + + /* something went badly wrong! */ + condlog(0, "poll"); +Index: multipath-tools-130222/multipathd/uxlsnr.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/uxlsnr.h ++++ multipath-tools-130222/multipathd/uxlsnr.h +@@ -4,5 +4,8 @@ + void * uxsock_listen(int (*uxsock_trigger) + (char *, char **, int *, void *), + void * trigger_data); ++ ++extern volatile sig_atomic_t reconfig_sig; ++extern volatile sig_atomic_t log_reset_sig; + #endif + diff --git a/SOURCES/0043-RH-signal-waiter.patch b/SOURCES/0043-RH-signal-waiter.patch new file mode 100644 index 0000000..a1a63ea --- /dev/null +++ b/SOURCES/0043-RH-signal-waiter.patch @@ -0,0 +1,71 @@ +--- + libmultipath/waiter.c | 9 +++++++++ + multipathd/main.c | 8 ++++++++ + 2 files changed, 17 insertions(+) + +Index: multipath-tools-130222/libmultipath/waiter.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/waiter.c ++++ multipath-tools-130222/libmultipath/waiter.c +@@ -57,6 +57,7 @@ void stop_waiter_thread (struct multipat + thread = mpp->waiter; + mpp->waiter = (pthread_t)0; + pthread_cancel(thread); ++ pthread_kill(thread, SIGUSR2); + } + + /* +@@ -65,6 +66,7 @@ void stop_waiter_thread (struct multipat + */ + int waiteventloop (struct event_thread *waiter) + { ++ sigset_t set, oldset; + int event_nr; + int r; + +@@ -97,8 +99,15 @@ int waiteventloop (struct event_thread * + dm_task_no_open_count(waiter->dmt); + + /* wait */ ++ sigemptyset(&set); ++ sigaddset(&set, SIGUSR2); ++ pthread_sigmask(SIG_UNBLOCK, &set, &oldset); ++ ++ pthread_testcancel(); + r = dm_task_run(waiter->dmt); ++ pthread_testcancel(); + ++ pthread_sigmask(SIG_SETMASK, &oldset, NULL); + dm_task_destroy(waiter->dmt); + waiter->dmt = NULL; + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1506,6 +1506,12 @@ sigusr1 (int sig) + } + + static void ++sigusr2 (int sig) ++{ ++ condlog(3, "SIGUSR2 received"); ++} ++ ++static void + signal_init(void) + { + sigset_t set; +@@ -1513,10 +1519,12 @@ signal_init(void) + sigemptyset(&set); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGUSR1); ++ sigaddset(&set, SIGUSR2); + pthread_sigmask(SIG_BLOCK, &set, NULL); + + signal_set(SIGHUP, sighup); + signal_set(SIGUSR1, sigusr1); ++ signal_set(SIGUSR2, sigusr2); + signal_set(SIGINT, sigend); + signal_set(SIGTERM, sigend); + signal(SIGPIPE, SIG_IGN); diff --git a/SOURCES/0044-RHBZ-976688-fix-wipe-wwids.patch b/SOURCES/0044-RHBZ-976688-fix-wipe-wwids.patch new file mode 100644 index 0000000..6f70574 --- /dev/null +++ b/SOURCES/0044-RHBZ-976688-fix-wipe-wwids.patch @@ -0,0 +1,28 @@ +--- + libmultipath/wwids.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +Index: multipath-tools-130222/libmultipath/wwids.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.c ++++ multipath-tools-130222/libmultipath/wwids.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + + #include "checkers.h" + #include "vector.h" +@@ -100,6 +101,11 @@ replace_wwids(vector mp) + condlog(0, "cannot truncate wwids file : %s", strerror(errno)); + goto out_file; + } ++ if (lseek(fd, 0, SEEK_SET) < 0) { ++ condlog(0, "cannot seek to the start of the file : %s", ++ strerror(errno)); ++ goto out_file; ++ } + len = strlen(WWIDS_FILE_HEADER); + if (write_all(fd, WWIDS_FILE_HEADER, len) != len) { + condlog(0, "Can't write wwid file header : %s", diff --git a/SOURCES/0045-RHBZ-977297-man-page-fix.patch b/SOURCES/0045-RHBZ-977297-man-page-fix.patch new file mode 100644 index 0000000..3ede0ce --- /dev/null +++ b/SOURCES/0045-RHBZ-977297-man-page-fix.patch @@ -0,0 +1,35 @@ +--- + multipath/multipath.conf.5 | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -136,7 +136,7 @@ per-multipath option in the configuratio + 1 priority group per target node name. Target node names are fetched + in /sys/class/fc_transport/target*/node_name. + .TP +-Default value is \fImultibus\fR. ++Default value is \fIfailover\fR. + .RE + .TP + .B uid_attribute +@@ -182,7 +182,7 @@ Generate a random priority between 1 and + Generate the path priority based on the regular expression and the + priority provided as argument. requires prio_args keyword. + .TP +-Default value is \fBnone\fR. ++Default value is \fBconst\fR. + .RE + .TP + .B prio_args +@@ -270,7 +270,7 @@ The number of IO to route to a path befo + the same path group. This is only for BIO based multipath. Default is + .I 1000 + .TP +-.B rr_min_io_q ++.B rr_min_io_rq + The number of IO requests to route to a path before switching to the + next in the same path group. This is only for request based multipath. + Default is diff --git a/SOURCES/0046-RHBZ-883981-move-udev-rules.patch b/SOURCES/0046-RHBZ-883981-move-udev-rules.patch new file mode 100644 index 0000000..4e5bc85 --- /dev/null +++ b/SOURCES/0046-RHBZ-883981-move-udev-rules.patch @@ -0,0 +1,28 @@ +--- + multipath/Makefile | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -23,8 +23,8 @@ install: + $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/ +- $(INSTALL_PROGRAM) -d $(DESTDIR)/lib/udev/rules.d +- $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/lib/udev/rules.d/62-multipath.rules ++ $(INSTALL_PROGRAM) -d $(DESTDIR)/usr/lib/udev/rules.d ++ $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/usr/lib/udev/rules.d/62-multipath.rules + $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) +@@ -32,7 +32,7 @@ install: + $(INSTALL_PROGRAM) -m 644 mpathconf.8.gz $(DESTDIR)$(mandir) + + uninstall: +- rm $(DESTDIR)/lib/udev/rules.d/62-multipath.rules ++ rm $(DESTDIR)/usr/lib/udev/rules.d/62-multipath.rules + rm $(DESTDIR)$(bindir)/$(EXEC) + rm $(DESTDIR)$(bindir)/mpathconf + rm $(DESTDIR)$(mandir)/$(EXEC).8.gz diff --git a/SOURCES/0047-RHBZ-kpartx-read-only-loop-devs.patch b/SOURCES/0047-RHBZ-kpartx-read-only-loop-devs.patch new file mode 100644 index 0000000..ed79e22 --- /dev/null +++ b/SOURCES/0047-RHBZ-kpartx-read-only-loop-devs.patch @@ -0,0 +1,39 @@ +--- + kpartx/kpartx.c | 3 +-- + kpartx/lopart.c | 2 +- + 2 files changed, 2 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -204,7 +204,6 @@ main(int argc, char **argv){ + char * delim = NULL; + char *uuid = NULL; + char *mapname = NULL; +- int loopro = 0; + int hotplug = 0; + int loopcreated = 0; + struct stat buf; +@@ -315,7 +314,7 @@ main(int argc, char **argv){ + if (!loopdev) { + loopdev = find_unused_loop_device(); + +- if (set_loop(loopdev, device, 0, &loopro)) { ++ if (set_loop(loopdev, device, 0, &ro)) { + fprintf(stderr, "can't set up loop\n"); + exit (1); + } +Index: multipath-tools-130222/kpartx/lopart.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/lopart.c ++++ multipath-tools-130222/kpartx/lopart.c +@@ -230,7 +230,7 @@ set_loop (const char *device, const char + + if ((ffd = open (file, mode)) < 0) { + +- if (!*loopro && errno == EROFS) ++ if (!*loopro && (errno == EROFS || errno == EACCES)) + ffd = open (file, mode = O_RDONLY); + + if (ffd < 0) { diff --git a/SOURCES/0048-RH-print-defaults.patch b/SOURCES/0048-RH-print-defaults.patch new file mode 100644 index 0000000..be1ce57 --- /dev/null +++ b/SOURCES/0048-RH-print-defaults.patch @@ -0,0 +1,25 @@ +--- + libmultipath/dict.c | 4 ---- + 1 file changed, 4 deletions(-) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -2468,16 +2468,12 @@ snprint_def_verbosity (char * buff, int + static int + snprint_def_max_polling_interval (char * buff, int len, void * data) + { +- if (conf->max_checkint == MAX_CHECKINT(conf->checkint)) +- return 0; + return snprintf(buff, len, "%i", conf->max_checkint); + } + + static int + snprint_reassign_maps (char * buff, int len, void * data) + { +- if (conf->reassign_maps == DEFAULT_REASSIGN_MAPS) +- return 0; + return snprintf(buff, len, "\"%s\"", + conf->reassign_maps?"yes":"no"); + } diff --git a/SOURCES/0049-RH-remove-ID_FS_TYPE.patch b/SOURCES/0049-RH-remove-ID_FS_TYPE.patch new file mode 100644 index 0000000..732f50f --- /dev/null +++ b/SOURCES/0049-RH-remove-ID_FS_TYPE.patch @@ -0,0 +1,17 @@ +--- + multipath/multipath.rules | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -11,7 +11,7 @@ ACTION=="add", ENV{DEVTYPE}!="partition" + ENV{DM_MULTIPATH_DEVICE_PATH}!="1", \ + TEST=="/etc/multipath.conf", \ + PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -c $tempnode", \ +- ENV{DM_MULTIPATH_DEVICE_PATH}="1" ++ ENV{DM_MULTIPATH_DEVICE_PATH}="1" ENV{ID_FS_TYPE}="mpath_member" + + ENV{DM_MULTIPATH_DEVICE_PATH}=="1", ENV{DEVTYPE}!="partition", \ + RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}" diff --git a/SOURCES/0050-RH-listing-speedup.patch b/SOURCES/0050-RH-listing-speedup.patch new file mode 100644 index 0000000..4742634 --- /dev/null +++ b/SOURCES/0050-RH-listing-speedup.patch @@ -0,0 +1,17 @@ +--- + multipath/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -311,7 +311,7 @@ configure (void) + /* + * get a path list + */ +- if (conf->dev) ++ if (conf->dev && !conf->list) + di_flag = DI_WWID; + + if (conf->list > 1) diff --git a/SOURCES/0051-UP-fix-cli-resize.patch b/SOURCES/0051-UP-fix-cli-resize.patch new file mode 100644 index 0000000..f278607 --- /dev/null +++ b/SOURCES/0051-UP-fix-cli-resize.patch @@ -0,0 +1,23 @@ +diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c +index 7b1cb62..4b860bb 100644 +--- a/multipathd/cli_handlers.c ++++ b/multipathd/cli_handlers.c +@@ -603,7 +603,18 @@ cli_resize(void *v, char **reply, int *len, void *data) + } + + pgp = VECTOR_SLOT(mpp->pg, 0); ++ ++ if (!pgp){ ++ condlog(0, "%s: couldn't get path group. cannot resize", ++ mapname); ++ return 1; ++ } + pp = VECTOR_SLOT(pgp->paths, 0); ++ ++ if (!pp){ ++ condlog(0, "%s: couldn't get path. cannot resize", mapname); ++ return 1; ++ } + if (!pp->udev || sysfs_get_size(pp, &size)) { + condlog(0, "%s: couldn't get size for sysfs. cannot resize", + mapname); diff --git a/SOURCES/0052-RH-fix-bad-derefs.patch b/SOURCES/0052-RH-fix-bad-derefs.patch new file mode 100644 index 0000000..db5f1db --- /dev/null +++ b/SOURCES/0052-RH-fix-bad-derefs.patch @@ -0,0 +1,54 @@ +--- + multipathd/cli_handlers.c | 3 ++- + multipathd/main.c | 12 ++++++------ + 2 files changed, 8 insertions(+), 7 deletions(-) + +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -632,7 +632,8 @@ cli_resize(void *v, char **reply, int *l + return 1; + + dm_lib_release(); +- setup_multipath(vecs, mpp); ++ if (setup_multipath(vecs, mpp) != 0) ++ return 1; + sync_map_state(mpp); + + return 0; +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -134,7 +134,6 @@ coalesce_maps(struct vectors *vecs, vect + struct multipath * ompp; + vector ompv = vecs->mpvec; + unsigned int i; +- int j; + + vector_foreach_slot (ompv, ompp, i) { + if (!find_mp_by_wwid(nmpv, ompp->wwid)) { +@@ -148,16 +147,17 @@ coalesce_maps(struct vectors *vecs, vect + /* + * may be just because the device is open + */ ++ if (setup_multipath(vecs, ompp) != 0) { ++ i--; ++ continue; ++ } + if (!vector_alloc_slot(nmpv)) + return 1; + + vector_set_slot(nmpv, ompp); +- setup_multipath(vecs, ompp); + +- if ((j = find_slot(ompv, (void *)ompp)) != -1) +- vector_del_slot(ompv, j); +- +- continue; ++ vector_del_slot(ompv, i); ++ i--; + } + else { + dm_lib_release(); diff --git a/SOURCES/0053-UP-fix-failback.patch b/SOURCES/0053-UP-fix-failback.patch new file mode 100644 index 0000000..936655d --- /dev/null +++ b/SOURCES/0053-UP-fix-failback.patch @@ -0,0 +1,23 @@ +--- + libmultipath/dict.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -1126,11 +1126,11 @@ hw_failback_handler(vector strvec) + + buff = set_value(strvec); + +- if (strlen(buff) == 6 && !strcmp(buff, "\"manual\"")) ++ if (strlen(buff) == 6 && !strcmp(buff, "manual")) + hwe->pgfailback = -FAILBACK_MANUAL; +- else if (strlen(buff) == 9 && !strcmp(buff, "\"immediate\"")) ++ else if (strlen(buff) == 9 && !strcmp(buff, "immediate")) + hwe->pgfailback = -FAILBACK_IMMEDIATE; +- else if (strlen(buff) == 10 && !strcmp(buff, "\"followover\"")) ++ else if (strlen(buff) == 10 && !strcmp(buff, "followover")) + hwe->pgfailback = -FAILBACK_FOLLOWOVER; + else + hwe->pgfailback = atoi(buff); diff --git a/SOURCES/0054-UP-keep-udev-ref.patch b/SOURCES/0054-UP-keep-udev-ref.patch new file mode 100644 index 0000000..e42d716 --- /dev/null +++ b/SOURCES/0054-UP-keep-udev-ref.patch @@ -0,0 +1,308 @@ +--- + libmpathpersist/mpath_persist.c | 7 ++++--- + libmpathpersist/mpath_persist.h | 2 +- + libmpathpersist/mpath_pr_ioctl.c | 5 +++-- + libmultipath/config.c | 9 +++------ + libmultipath/config.h | 2 +- + mpathpersist/Makefile | 2 +- + mpathpersist/main.c | 11 +++++++---- + multipath/Makefile | 2 +- + multipath/main.c | 12 ++++++++---- + multipathd/main.c | 11 ++++++++--- + 10 files changed, 37 insertions(+), 26 deletions(-) + +Index: multipath-tools-130222/libmpathpersist/mpath_persist.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.c ++++ multipath-tools-130222/libmpathpersist/mpath_persist.c +@@ -1,4 +1,3 @@ +-#include "mpath_persist.h" + #include + #include + #include +@@ -8,6 +7,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -20,6 +20,7 @@ + #include + #include + ++#include "mpath_persist.h" + #include "mpathpr.h" + #include "mpath_pr_ioctl.h" + +@@ -32,9 +33,9 @@ + + + int +-mpath_lib_init (void) ++mpath_lib_init (struct udev *udev) + { +- if (load_config(DEFAULT_CONFIGFILE)){ ++ if (load_config(DEFAULT_CONFIGFILE, udev)){ + condlog(0, "Failed to initialize multipath config."); + return 1; + } +Index: multipath-tools-130222/libmpathpersist/mpath_persist.h +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_persist.h ++++ multipath-tools-130222/libmpathpersist/mpath_persist.h +@@ -174,7 +174,7 @@ struct prout_param_descriptor { /* PROU + * + * RETURNS: 0->Success, 1->Failed. + */ +-extern int mpath_lib_init (void ); ++extern int mpath_lib_init (struct udev *udev); + + + /* +Index: multipath-tools-130222/libmpathpersist/mpath_pr_ioctl.c +=================================================================== +--- multipath-tools-130222.orig/libmpathpersist/mpath_pr_ioctl.c ++++ multipath-tools-130222/libmpathpersist/mpath_pr_ioctl.c +@@ -10,8 +10,9 @@ + #include + #include + #include +-#include "mpath_pr_ioctl.h" +-#include ++#include ++#include "mpath_pr_ioctl.h" ++#include + + #include + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -467,9 +467,6 @@ free_config (struct config * conf) + if (conf->dev) + FREE(conf->dev); + +- if (conf->udev) +- udev_unref(conf->udev); +- + if (conf->multipath_dir) + FREE(conf->multipath_dir); + +@@ -519,12 +516,12 @@ free_config (struct config * conf) + } + + int +-load_config (char * file) ++load_config (char * file, struct udev *udev) + { + if (!conf) + conf = alloc_config(); + +- if (!conf) ++ if (!conf || !udev) + return 1; + + /* +@@ -533,7 +530,7 @@ load_config (char * file) + if (!conf->verbosity) + conf->verbosity = DEFAULT_VERBOSITY; + +- conf->udev = udev_new(); ++ conf->udev = udev; + dm_drv_version(conf->version, TGT_MPATH); + conf->dev_type = DEV_NONE; + conf->minio = DEFAULT_MINIO; +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -159,7 +159,7 @@ void free_mptable (vector mptable); + + int store_hwe (vector hwtable, struct hwentry *); + +-int load_config (char * file); ++int load_config (char * file, struct udev * udev); + struct config * alloc_config (void); + void free_config (struct config * conf); + +Index: multipath-tools-130222/mpathpersist/main.c +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/main.c ++++ multipath-tools-130222/mpathpersist/main.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include "main.h" + #include +@@ -68,7 +69,8 @@ int main (int argc, char * argv[]) + int noisy = 0; + int num_transport =0; + void *resp = NULL; +- struct transportid * tmp; ++ struct transportid * tmp; ++ struct udev *udev = NULL; + + if (optind == argc) + { +@@ -84,8 +86,8 @@ int main (int argc, char * argv[]) + exit (1); + } + +- +- mpath_lib_init(); ++ udev = udev_new(); ++ mpath_lib_init(udev); + memset(transportids,0,MPATH_MX_TIDS); + + while (1) +@@ -461,12 +463,13 @@ int main (int argc, char * argv[]) + if (res < 0) + { + mpath_lib_exit(); ++ udev_unref(udev); + return MPATH_PR_FILE_ERROR; + } + + out : + mpath_lib_exit(); +- ++ udev_unref(udev); + return (ret >= 0) ? ret : MPATH_PR_OTHER; + } + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -435,6 +436,7 @@ convert_dev(char *dev) + int + main (int argc, char *argv[]) + { ++ struct udev *udev; + int arg; + extern char *optarg; + extern int optind; +@@ -445,7 +447,9 @@ main (int argc, char *argv[]) + exit(1); + } + +- if (load_config(DEFAULT_CONFIGFILE)) ++ udev = udev_new(); ++ ++ if (load_config(DEFAULT_CONFIGFILE, udev)) + exit(1); + + if (dm_prereq()) +@@ -560,11 +564,11 @@ main (int argc, char *argv[]) + + if (init_checkers()) { + condlog(0, "failed to initialize checkers"); +- exit(1); ++ goto out; + } + if (init_prio()) { + condlog(0, "failed to initialize prioritizers"); +- exit(1); ++ goto out; + } + dm_init(); + +@@ -628,7 +632,7 @@ out: + */ + free_config(conf); + conf = NULL; +- ++ udev_unref(udev); + #ifdef _DEBUG_ + dbg_free_final(NULL); + #endif +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -93,6 +93,8 @@ static sem_t exit_sem; + */ + struct vectors * gvecs; + ++struct udev * udev; ++ + static int + need_switch_pathgroup (struct multipath * mpp, int refresh) + { +@@ -1408,7 +1410,7 @@ reconfigure (struct vectors * vecs) + vecs->pathvec = NULL; + conf = NULL; + +- if (!load_config(DEFAULT_CONFIGFILE)) { ++ if (!load_config(DEFAULT_CONFIGFILE, udev)) { + conf->verbosity = old->verbosity; + conf->daemon = 1; + configure(vecs, 1); +@@ -1601,6 +1603,8 @@ child (void * param) + sem_init(&exit_sem, 0, 0); + signal_init(); + ++ udev = udev_new(); ++ + setup_thread_attr(&misc_attr, 64 * 1024, 1); + setup_thread_attr(&waiter_attr, 32 * 1024, 1); + +@@ -1615,7 +1619,7 @@ child (void * param) + condlog(2, "--------start up--------"); + condlog(2, "read " DEFAULT_CONFIGFILE); + +- if (load_config(DEFAULT_CONFIGFILE)) ++ if (load_config(DEFAULT_CONFIGFILE, udev)) + exit(1); + + if (init_checkers()) { +@@ -1765,7 +1769,8 @@ child (void * param) + */ + free_config(conf); + conf = NULL; +- ++ udev_unref(udev); ++ udev = NULL; + #ifdef _DEBUG_ + dbg_free_final(NULL); + #endif +Index: multipath-tools-130222/mpathpersist/Makefile +=================================================================== +--- multipath-tools-130222.orig/mpathpersist/Makefile ++++ multipath-tools-130222/mpathpersist/Makefile +@@ -5,7 +5,7 @@ include ../Makefile.inc + OBJS = main.o + + CFLAGS += -I$(multipathdir) -I$(mpathpersistdir) +-LDFLAGS += -lpthread -ldevmapper -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -lmultipath ++LDFLAGS += -lpthread -ldevmapper -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -lmultipath -ludev + + EXEC = mpathpersist + +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -7,7 +7,7 @@ include ../Makefile.inc + OBJS = main.o + + CFLAGS += -fPIC -I$(multipathdir) +-LDFLAGS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath ++LDFLAGS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath -ludev + + EXEC = multipath + diff --git a/SOURCES/0055-UP-handle-quiesced-paths.patch b/SOURCES/0055-UP-handle-quiesced-paths.patch new file mode 100644 index 0000000..0556a61 --- /dev/null +++ b/SOURCES/0055-UP-handle-quiesced-paths.patch @@ -0,0 +1,16 @@ +--- + libmultipath/discovery.c | 1 + + 1 file changed, 1 insertion(+) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -799,6 +799,7 @@ path_offline (struct path * pp) + condlog(3, "%s: path state = %s", pp->dev, buff); + + if (!strncmp(buff, "offline", 7) || ++ !strncmp(buff, "quiesce", 7) || + !strncmp(buff, "transport-offline", 17)) { + pp->offline = 1; + return PATH_DOWN; diff --git a/SOURCES/0056-UP-alua-prio-fix.patch b/SOURCES/0056-UP-alua-prio-fix.patch new file mode 100644 index 0000000..0ac41ab --- /dev/null +++ b/SOURCES/0056-UP-alua-prio-fix.patch @@ -0,0 +1,17 @@ +--- + libmultipath/prioritizers/alua.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/prioritizers/alua.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua.c ++++ multipath-tools-130222/libmultipath/prioritizers/alua.c +@@ -108,7 +108,7 @@ int getprio (struct path * pp, char * ar + default: + rc = 0; + } +- if (priopath) ++ if (priopath && aas != AAS_OPTIMIZED) + rc += 80; + } else { + switch(-rc) { diff --git a/SOURCES/0057-UP-fix-tmo.patch b/SOURCES/0057-UP-fix-tmo.patch new file mode 100644 index 0000000..0bfc46b --- /dev/null +++ b/SOURCES/0057-UP-fix-tmo.patch @@ -0,0 +1,329 @@ +--- + libmultipath/discovery.c | 109 +++++++++++++++++++++++++++++++++++++---------- + libmultipath/sysfs.c | 86 +++++++++++++++++++++++++++++++------ + libmultipath/sysfs.h | 2 + 3 files changed, 161 insertions(+), 36 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -162,7 +162,6 @@ declare_sysfs_get_str(cutype); + declare_sysfs_get_str(vendor); + declare_sysfs_get_str(model); + declare_sysfs_get_str(rev); +-declare_sysfs_get_str(state); + declare_sysfs_get_str(dev); + + int +@@ -315,9 +314,14 @@ static void + sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp) + { + struct udev_device *rport_dev = NULL; +- char value[11]; ++ char value[16]; + char rport_id[32]; ++ int delay_fast_io_fail = 0; ++ int current_dev_loss = 0; ++ int ret; + ++ if (!mpp->dev_loss && mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET) ++ return; + sprintf(rport_id, "rport-%d:%d-%d", + pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); + rport_dev = udev_device_new_from_subsystem_sysname(conf->udev, +@@ -330,33 +334,85 @@ sysfs_set_rport_tmo(struct multipath *mp + condlog(4, "target%d:%d:%d -> %s", pp->sg_id.host_no, + pp->sg_id.channel, pp->sg_id.scsi_id, rport_id); + +- snprintf(value, 11, "%u", mpp->dev_loss); +- if (mpp->dev_loss && +- sysfs_attr_set_value(rport_dev, "dev_loss_tmo", value, 11) <= 0) { +- if ((mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET || +- mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) +- && mpp->dev_loss > 600) { +- condlog(3, "%s: limiting dev_loss_tmo to 600, since " +- "fast_io_fail is not set", mpp->alias); +- snprintf(value, 11, "%u", 600); +- if (sysfs_attr_set_value(rport_dev, "dev_loss_tmo", +- value, 11) <= 0) +- condlog(0, "%s failed to set dev_loss_tmo", +- mpp->alias); ++ memset(value, 0, 16); ++ if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) { ++ ret = sysfs_attr_get_value(rport_dev, "dev_loss_tmo", ++ value, 16); ++ if (ret <= 0) { ++ condlog(0, "%s: failed to read dev_loss_tmo value, " ++ "error %d", rport_id, -ret); + goto out; + } ++ if (sscanf(value, "%u\n", ¤t_dev_loss) != 1) { ++ condlog(0, "%s: Cannot parse dev_loss_tmo " ++ "attribute '%s'", rport_id, value); ++ goto out; ++ } ++ if ((mpp->dev_loss && ++ mpp->fast_io_fail >= (int)mpp->dev_loss) || ++ (!mpp->dev_loss && ++ mpp->fast_io_fail >= (int)current_dev_loss)) { ++ condlog(3, "%s: limiting fast_io_fail_tmo to %d, since " ++ "it must be less than dev_loss_tmo", ++ rport_id, mpp->dev_loss - 1); ++ if (mpp->dev_loss) ++ mpp->fast_io_fail = mpp->dev_loss - 1; ++ else ++ mpp->fast_io_fail = current_dev_loss - 1; ++ } ++ if (mpp->fast_io_fail >= (int)current_dev_loss) ++ delay_fast_io_fail = 1; ++ } ++ if (mpp->dev_loss > 600 && ++ (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF || ++ mpp->fast_io_fail == MP_FAST_IO_FAIL_UNSET)) { ++ condlog(3, "%s: limiting dev_loss_tmo to 600, since " ++ "fast_io_fail is unset or off", rport_id); ++ mpp->dev_loss = 600; + } +- if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET){ ++ if (mpp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) { + if (mpp->fast_io_fail == MP_FAST_IO_FAIL_OFF) + sprintf(value, "off"); + else if (mpp->fast_io_fail == MP_FAST_IO_FAIL_ZERO) + sprintf(value, "0"); ++ else if (delay_fast_io_fail) ++ snprintf(value, 16, "%u", current_dev_loss - 1); + else +- snprintf(value, 11, "%u", mpp->fast_io_fail); +- if (sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo", +- value, 11) <= 0) { +- condlog(0, "%s failed to set fast_io_fail_tmo", +- mpp->alias); ++ snprintf(value, 16, "%u", mpp->fast_io_fail); ++ ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo", ++ value, strlen(value)); ++ if (ret <= 0) { ++ if (ret == -EBUSY) ++ condlog(3, "%s: rport blocked", rport_id); ++ else ++ condlog(0, "%s: failed to set fast_io_fail_tmo to %s, error %d", ++ rport_id, value, -ret); ++ goto out; ++ } ++ } ++ if (mpp->dev_loss) { ++ snprintf(value, 16, "%u", mpp->dev_loss); ++ ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo", ++ value, strlen(value)); ++ if (ret <= 0) { ++ if (ret == -EBUSY) ++ condlog(3, "%s: rport blocked", rport_id); ++ else ++ condlog(0, "%s: failed to set dev_loss_tmo to %s, error %d", ++ rport_id, value, -ret); ++ goto out; ++ } ++ } ++ if (delay_fast_io_fail) { ++ snprintf(value, 16, "%u", mpp->fast_io_fail); ++ ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo", ++ value, strlen(value)); ++ if (ret <= 0) { ++ if (ret == -EBUSY) ++ condlog(3, "%s: rport blocked", rport_id); ++ else ++ condlog(0, "%s: failed to set fast_io_fail_tmo to %s, error %d", ++ rport_id, value, -ret); + } + } + out: +@@ -394,7 +450,7 @@ sysfs_set_session_tmo(struct multipath * + } else { + snprintf(value, 11, "%u", mpp->fast_io_fail); + if (sysfs_attr_set_value(session_dev, "recovery_tmo", +- value, 11)) { ++ value, 11) <= 0) { + condlog(3, "%s: Failed to set recovery_tmo, " + " error %d", pp->dev, errno); + } +@@ -752,6 +808,9 @@ cciss_sysfs_pathinfo (struct path * pp) + static int + common_sysfs_pathinfo (struct path * pp) + { ++ if (!pp) ++ return 1; ++ + if (!pp->udev) { + condlog(4, "%s: udev not initialised", pp->dev); + return 1; +@@ -793,7 +852,8 @@ path_offline (struct path * pp) + return PATH_DOWN; + } + +- if (sysfs_get_state(parent, buff, SCSI_STATE_SIZE)) ++ memset(buff, 0x0, SCSI_STATE_SIZE); ++ if (sysfs_attr_get_value(parent, "state", buff, SCSI_STATE_SIZE) <= 0) + return PATH_DOWN; + + condlog(3, "%s: path state = %s", pp->dev, buff); +@@ -983,6 +1043,9 @@ pathinfo (struct path *pp, vector hwtabl + { + int path_state; + ++ if (!pp) ++ return 1; ++ + condlog(3, "%s: mask = 0x%x", pp->dev, mask); + + /* +Index: multipath-tools-130222/libmultipath/sysfs.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/sysfs.c ++++ multipath-tools-130222/libmultipath/sysfs.c +@@ -38,7 +38,12 @@ + #include "debug.h" + #include "devmapper.h" + +-ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name, ++/* ++ * When we modify an attribute value we cannot rely on libudev for now, ++ * as libudev lacks the capability to update an attribute value. ++ * So for modified attributes we need to implement our own function. ++ */ ++ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name, + char * value, size_t value_len) + { + char devpath[PATH_SIZE]; +@@ -54,28 +59,83 @@ ssize_t sysfs_attr_set_value(struct udev + condlog(4, "open '%s'", devpath); + if (stat(devpath, &statbuf) != 0) { + condlog(4, "stat '%s' failed: %s", devpath, strerror(errno)); +- return 0; ++ return -errno; + } + + /* skip directories */ +- if (S_ISDIR(statbuf.st_mode)) +- return 0; ++ if (S_ISDIR(statbuf.st_mode)) { ++ condlog(4, "%s is a directory", devpath); ++ return -EISDIR; ++ } + + /* skip non-writeable files */ +- if ((statbuf.st_mode & S_IWUSR) == 0) ++ if ((statbuf.st_mode & S_IRUSR) == 0) { ++ condlog(4, "%s is not readable", devpath); ++ return -EPERM; ++ } ++ ++ /* read attribute value */ ++ fd = open(devpath, O_RDONLY); ++ if (fd < 0) { ++ condlog(4, "attribute '%s' can not be opened: %s", ++ devpath, strerror(errno)); ++ return -errno; ++ } ++ size = read(fd, value, value_len); ++ if (size < 0) { ++ condlog(4, "read from %s failed: %s", devpath, strerror(errno)); ++ size = -errno; ++ } else if (size == value_len) { ++ condlog(4, "overflow while reading from %s", devpath); ++ size = 0; ++ } ++ ++ close(fd); ++ return size; ++} ++ ++ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name, ++ char * value, size_t value_len) ++{ ++ char devpath[PATH_SIZE]; ++ struct stat statbuf; ++ int fd; ++ ssize_t size = -1; ++ ++ if (!dev || !attr_name || !value || !value_len) + return 0; + ++ snprintf(devpath, PATH_SIZE, "%s/%s", udev_device_get_syspath(dev), ++ attr_name); ++ condlog(4, "open '%s'", devpath); ++ if (stat(devpath, &statbuf) != 0) { ++ condlog(4, "stat '%s' failed: %s", devpath, strerror(errno)); ++ return -errno; ++ } ++ ++ /* skip directories */ ++ if (S_ISDIR(statbuf.st_mode)) { ++ condlog(4, "%s is a directory", devpath); ++ return -EISDIR; ++ } ++ ++ /* skip non-writeable files */ ++ if ((statbuf.st_mode & S_IWUSR) == 0) { ++ condlog(4, "%s is not writeable", devpath); ++ return -EPERM; ++ } ++ + /* write attribute value */ + fd = open(devpath, O_WRONLY); + if (fd < 0) { + condlog(4, "attribute '%s' can not be opened: %s", + devpath, strerror(errno)); +- return 0; ++ return -errno; + } + size = write(fd, value, value_len); + if (size < 0) { + condlog(4, "write to %s failed: %s", devpath, strerror(errno)); +- size = 0; ++ size = -errno; + } else if (size < value_len) { + condlog(4, "tried to write %ld to %s. Wrote %ld", + (long)value_len, devpath, (long)size); +@@ -89,14 +149,14 @@ ssize_t sysfs_attr_set_value(struct udev + int + sysfs_get_size (struct path *pp, unsigned long long * size) + { +- const char * attr; ++ char attr[255]; + int r; + +- if (!pp->udev) ++ if (!pp->udev || !size) + return 1; + +- attr = udev_device_get_sysattr_value(pp->udev, "size"); +- if (!attr) { ++ attr[0] = '\0'; ++ if (sysfs_attr_get_value(pp->udev, "size", attr, 255) == 0) { + condlog(3, "%s: No size attribute in sysfs", pp->dev); + return 1; + } +@@ -104,8 +164,8 @@ sysfs_get_size (struct path *pp, unsigne + r = sscanf(attr, "%llu\n", size); + + if (r != 1) { +- condlog(3, "%s: Cannot parse size attribute '%s'", +- pp->dev, attr); ++ condlog(3, "%s: Cannot parse size attribute", pp->dev); ++ *size = 0; + return 1; + } + +Index: multipath-tools-130222/libmultipath/sysfs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/sysfs.h ++++ multipath-tools-130222/libmultipath/sysfs.h +@@ -7,6 +7,8 @@ + + ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name, + char * value, size_t value_len); ++ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name, ++ 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); + #endif diff --git a/SOURCES/0058-UP-fix-failback.patch b/SOURCES/0058-UP-fix-failback.patch new file mode 100644 index 0000000..d1fbaeb --- /dev/null +++ b/SOURCES/0058-UP-fix-failback.patch @@ -0,0 +1,17 @@ +--- + libmultipath/dict.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -2562,7 +2562,7 @@ snprint_def_failback (char * buff, int l + if (!pgfailback) + pgfailback = DEFAULT_FAILBACK; + +- switch(conf->pgfailback) { ++ switch(pgfailback) { + case FAILBACK_UNDEF: + break; + case -FAILBACK_MANUAL: diff --git a/SOURCES/0059-UP-flush-failure-queueing.patch b/SOURCES/0059-UP-flush-failure-queueing.patch new file mode 100644 index 0000000..f72f314 --- /dev/null +++ b/SOURCES/0059-UP-flush-failure-queueing.patch @@ -0,0 +1,71 @@ +--- + libmultipath/devmapper.c | 21 +++++++++++++++++---- + libmultipath/devmapper.h | 2 +- + 2 files changed, 18 insertions(+), 5 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -363,7 +363,7 @@ out: + } + + extern int +-dm_get_map(char * name, unsigned long long * size, char * outparams) ++dm_get_map(const char * name, unsigned long long * size, char * outparams) + { + int r = 1; + struct dm_task *dmt; +@@ -682,7 +682,9 @@ _dm_flush_map (const char * mapname, int + extern int + dm_suspend_and_flush_map (const char * mapname) + { +- int s; ++ int s = 0, queue_if_no_path = 0; ++ unsigned long long mapsize; ++ char params[PARAMS_SIZE] = {0}; + + if (!dm_map_present(mapname)) + return 0; +@@ -690,8 +692,17 @@ dm_suspend_and_flush_map (const char * m + if (dm_type(mapname, TGT_MPATH) <= 0) + return 0; /* nothing to do */ + +- s = dm_queue_if_no_path((char *)mapname, 0); +- if (!s) ++ if (!dm_get_map(mapname, &mapsize, params)) { ++ if (strstr(params, "queue_if_no_path")) ++ queue_if_no_path = 1; ++ } ++ ++ if (queue_if_no_path) ++ s = dm_queue_if_no_path((char *)mapname, 0); ++ /* Leave queue_if_no_path alone if unset failed */ ++ if (s) ++ queue_if_no_path = 0; ++ else + s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0); + + if (!dm_flush_map(mapname)) { +@@ -700,6 +711,8 @@ dm_suspend_and_flush_map (const char * m + } + condlog(2, "failed to remove multipath map %s", mapname); + dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname); ++ if (queue_if_no_path) ++ s = dm_queue_if_no_path((char *)mapname, 1); + return 1; + } + +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -14,7 +14,7 @@ int dm_simplecmd_noflush (int, const cha + int dm_addmap_create (struct multipath *mpp, char *params); + int dm_addmap_reload (struct multipath *mpp, char *params); + int dm_map_present (const char *); +-int dm_get_map(char *, unsigned long long *, char *); ++int dm_get_map(const char *, unsigned long long *, char *); + int dm_get_status(char *, char *); + int dm_type(const char *, char *); + int _dm_flush_map (const char *, int); diff --git a/SOURCES/0060-UP-uevent-loop-udev.patch b/SOURCES/0060-UP-uevent-loop-udev.patch new file mode 100644 index 0000000..88fc005 --- /dev/null +++ b/SOURCES/0060-UP-uevent-loop-udev.patch @@ -0,0 +1,127 @@ +--- + libmultipath/uevent.c | 17 ++++++++++++----- + libmultipath/uevent.h | 4 +++- + multipathd/main.c | 8 +++++--- + 3 files changed, 20 insertions(+), 9 deletions(-) + +Index: multipath-tools-130222/libmultipath/uevent.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/uevent.c ++++ multipath-tools-130222/libmultipath/uevent.c +@@ -47,7 +47,6 @@ + #include "list.h" + #include "uevent.h" + #include "vector.h" +-#include "config.h" + + typedef int (uev_trigger)(struct uevent *, void * trigger_data); + +@@ -127,11 +126,14 @@ service_uevq(struct list_head *tmpq) + + static void uevq_stop(void *arg) + { ++ struct udev *udev = arg; ++ + condlog(3, "Stopping uev queue"); + pthread_mutex_lock(uevq_lockp); + my_uev_trigger = NULL; + pthread_cond_signal(uev_condp); + pthread_mutex_unlock(uevq_lockp); ++ udev_unref(udev); + } + + void +@@ -399,9 +401,9 @@ exit: + return 1; + } + +-int uevent_listen(void) ++int uevent_listen(struct udev *udev) + { +- int err; ++ int err = 2; + struct udev_monitor *monitor = NULL; + int fd, socket_flags; + int need_failback = 1; +@@ -411,9 +413,14 @@ int uevent_listen(void) + * thereby not getting to empty the socket's receive buffer queue + * often enough. + */ +- pthread_cleanup_push(uevq_stop, NULL); ++ if (!udev) { ++ condlog(1, "no udev context"); ++ return 1; ++ } ++ udev_ref(udev); ++ pthread_cleanup_push(uevq_stop, udev); + +- monitor = udev_monitor_new_from_netlink(conf->udev, "udev"); ++ monitor = udev_monitor_new_from_netlink(udev, "udev"); + if (!monitor) { + condlog(2, "failed to create udev monitor"); + goto out; +Index: multipath-tools-130222/libmultipath/uevent.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/uevent.h ++++ multipath-tools-130222/libmultipath/uevent.h +@@ -13,6 +13,8 @@ + #define NETLINK_KOBJECT_UEVENT 15 + #endif + ++struct udev; ++ + struct uevent { + struct list_head node; + struct udev_device *udev; +@@ -27,7 +29,7 @@ struct uevent { + int is_uevent_busy(void); + void setup_thread_attr(pthread_attr_t *attr, size_t stacksize, int detached); + +-int uevent_listen(void); ++int uevent_listen(struct udev *udev); + int uevent_dispatch(int (*store_uev)(struct uevent *, void * trigger_data), + void * trigger_data); + int uevent_get_major(struct uevent *uev); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -840,7 +840,7 @@ out: + static void * + ueventloop (void * ap) + { +- if (uevent_listen()) ++ if (uevent_listen(udev)) + condlog(0, "error starting uevent listener"); + + return NULL; +@@ -1593,7 +1593,7 @@ static int + child (void * param) + { + pthread_t check_thr, uevent_thr, uxlsnr_thr, uevq_thr; +- pthread_attr_t log_attr, misc_attr; ++ pthread_attr_t log_attr, misc_attr, uevent_attr; + struct vectors * vecs; + struct multipath * mpp; + int i; +@@ -1606,6 +1606,7 @@ child (void * param) + udev = udev_new(); + + setup_thread_attr(&misc_attr, 64 * 1024, 1); ++ setup_thread_attr(&uevent_attr, 128 * 1024, 1); + setup_thread_attr(&waiter_attr, 32 * 1024, 1); + + if (logsink) { +@@ -1671,10 +1672,11 @@ child (void * param) + /* + * Start uevent listener early to catch events + */ +- if ((rc = pthread_create(&uevent_thr, &misc_attr, ueventloop, vecs))) { ++ if ((rc = pthread_create(&uevent_thr, &uevent_attr, ueventloop, udev))) { + condlog(0, "failed to create uevent thread: %d", rc); + exit(1); + } ++ pthread_attr_destroy(&uevent_attr); + if ((rc = pthread_create(&uxlsnr_thr, &misc_attr, uxlsnrloop, vecs))) { + condlog(0, "failed to create cli listener: %d", rc); + exit(1); diff --git a/SOURCES/0061-RH-display-find-mpaths.patch b/SOURCES/0061-RH-display-find-mpaths.patch new file mode 100644 index 0000000..05c63f0 --- /dev/null +++ b/SOURCES/0061-RH-display-find-mpaths.patch @@ -0,0 +1,17 @@ +--- + libmultipath/dict.c | 2 -- + 1 file changed, 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -2717,8 +2717,6 @@ snprint_def_log_checker_err (char * buff + static int + snprint_def_find_multipaths (char * buff, int len, void * data) + { +- if (conf->find_multipaths == DEFAULT_FIND_MULTIPATHS) +- return 0; + if (!conf->find_multipaths) + return snprintf(buff, len, "no"); + diff --git a/SOURCES/0062-RH-dont-free-vecs.patch b/SOURCES/0062-RH-dont-free-vecs.patch new file mode 100644 index 0000000..f1c3217 --- /dev/null +++ b/SOURCES/0062-RH-dont-free-vecs.patch @@ -0,0 +1,28 @@ +--- + multipathd/main.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1735,8 +1735,9 @@ child (void * param) + vecs->pathvec = NULL; + unlock(vecs->lock); + /* Now all the waitevent threads will start rushing in. */ ++ /* freeing vecs isn't worth the races + while (vecs->lock.depth > 0) { +- sleep (1); /* This is weak. */ ++ sleep (1); + condlog(3, "Have %d wait event checkers threads to de-alloc," + " waiting...", vecs->lock.depth); + } +@@ -1746,7 +1747,7 @@ child (void * param) + vecs->lock.mutex = NULL; + FREE(vecs); + vecs = NULL; +- ++ */ + cleanup_checkers(); + cleanup_prio(); + diff --git a/SOURCES/0063-RH-fix-warning.patch b/SOURCES/0063-RH-fix-warning.patch new file mode 100644 index 0000000..7db8056 --- /dev/null +++ b/SOURCES/0063-RH-fix-warning.patch @@ -0,0 +1,26 @@ +--- + kpartx/dasd.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/kpartx/dasd.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/dasd.c ++++ multipath-tools-130222/kpartx/dasd.c +@@ -46,6 +46,8 @@ unsigned long long sectors512(unsigned l + return sectors * (blocksize >> 9); + } + ++typedef unsigned int __attribute__((__may_alias__)) label_ints_t; ++ + /* + */ + int +@@ -169,7 +171,7 @@ read_dasd_pt(int fd, struct slice all, s + /* + * VM style CMS1 labeled disk + */ +- unsigned int *label = (unsigned int *) &vlabel; ++ label_ints_t *label = (label_ints_t *) &vlabel; + + blocksize = label[4]; + if (label[14] != 0) { diff --git a/SOURCES/0064-RHBZ-1010040-fix-ID_FS-attrs.patch b/SOURCES/0064-RHBZ-1010040-fix-ID_FS-attrs.patch new file mode 100644 index 0000000..cb59a85 --- /dev/null +++ b/SOURCES/0064-RHBZ-1010040-fix-ID_FS-attrs.patch @@ -0,0 +1,383 @@ +--- + libmultipath/defaults.h | 3 - + libmultipath/file.c | 89 +++++++++++++++++++++++++++++++++++++++++- + libmultipath/file.h | 3 + + libmultipath/wwids.c | 7 ++- + multipath/main.c | 36 +++++++++++++++- + multipath/multipath.rules | 26 +++++++++--- + multipathd/main.c | 4 + + multipathd/multipathd.service | 2 + multipathd/pidfile.c | 3 + + 9 files changed, 160 insertions(+), 13 deletions(-) + +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -24,7 +24,8 @@ + #define MAX_CHECKINT(a) (a << 2) + + #define MAX_DEV_LOSS_TMO 0x7FFFFFFF +-#define DEFAULT_PIDFILE "/var/run/multipathd.pid" ++#define DEFAULT_PIDFILE "/var/run/multipathd/multipathd.pid" ++#define DEFAULT_TIMESTAMP_FILE "/var/run/multipathd/timestamp" + #define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd" + #define DEFAULT_CONFIGFILE "/etc/multipath.conf" + #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings" +Index: multipath-tools-130222/libmultipath/file.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/file.c ++++ multipath-tools-130222/libmultipath/file.c +@@ -12,10 +12,12 @@ + #include + #include + #include ++#include + + #include "file.h" + #include "debug.h" + #include "uxsock.h" ++#include "defaults.h" + + + /* +@@ -36,8 +38,8 @@ + * See the file COPYING included with this distribution for more details. + */ + +-static int +-ensure_directories_exist(char *str, mode_t dir_mode) ++int ++ensure_directories_exist(const char *str, mode_t dir_mode) + { + char *pathname; + char *end; +@@ -178,3 +180,86 @@ fail: + close(fd); + return -1; + } ++ ++/* If you can't get the timestamp, return equal to just keep using the ++ * existing value. ++ */ ++int timestamp_equal(long int chk_timestamp) ++{ ++ char buf[4096]; ++ FILE *file; ++ long int file_timestamp; ++ int ret = 1; ++ ++ if ((file = fopen(DEFAULT_TIMESTAMP_FILE, "r")) == NULL) { ++ if (errno != ENOENT) ++ condlog(2, "Cannot open timestamp file [%s]: %s", ++ DEFAULT_TIMESTAMP_FILE, strerror(errno)); ++ goto out; ++ } ++ errno = 0; ++ if (fgets(buf, sizeof(buf), file) == NULL) { ++ if (errno) ++ condlog(2, "Cannot read from timestamp file: %s", ++ strerror(errno)); ++ goto out; ++ } ++ if (sscanf(buf, "DM_MULTIPATH_TIMESTAMP=%ld", &file_timestamp) != 1) { ++ if (errno) ++ condlog(0, "Cannot get timestamp: %s", strerror(errno)); ++ else ++ condlog(0, "invalid timestamp file [%s]: %s", ++ DEFAULT_TIMESTAMP_FILE, strerror(errno)); ++ goto out; ++ } ++ if (file_timestamp != chk_timestamp) { ++ condlog(3, "timestamp has changed"); ++ ret = 0; ++ } ++ else ++ condlog(3, "timestamp has not changed"); ++out: ++ if (file) ++ fclose(file); ++ return ret; ++} ++ ++int update_timestamp(int create) ++{ ++ char buf[44]; ++ time_t timestamp; ++ int fd; ++ int flags = O_WRONLY; ++ if (create) ++ flags |= O_CREAT; ++ if((fd = open(DEFAULT_TIMESTAMP_FILE, flags, ++ (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) { ++ if (errno == ENOENT) ++ return 0; ++ condlog(0, "Cannot open timestamp file [%s]: %s", ++ DEFAULT_TIMESTAMP_FILE, strerror(errno)); ++ return 1; ++ } ++ if (ftruncate(fd, 0) < 0) { ++ condlog(0, "Cannot truncate timestamp file [%s]: %s", ++ DEFAULT_TIMESTAMP_FILE, strerror(errno)); ++ goto fail; ++ } ++ if (time(×tamp) == -1) { ++ condlog(0, "Cannot get current time: %s", strerror(errno)); ++ goto fail; ++ } ++ memset(buf, 0, sizeof(buf)); ++ snprintf(buf, sizeof(buf)-1, "DM_MULTIPATH_TIMESTAMP=%ld\n", ++ timestamp); ++ if (write(fd, buf, strlen(buf)) != strlen(buf)) { ++ condlog(0, "Cannot write out timestamp to %s: %s", ++ DEFAULT_TIMESTAMP_FILE, strerror(errno)); ++ goto fail; ++ } ++ close(fd); ++ return 0; ++fail: ++ close(fd); ++ return 1; ++} +Index: multipath-tools-130222/libmultipath/file.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/file.h ++++ multipath-tools-130222/libmultipath/file.h +@@ -7,5 +7,8 @@ + + #define FILE_TIMEOUT 30 + int open_file(char *file, int *can_write, char *header); ++int ensure_directories_exist(const char *str, mode_t dir_mode); ++int update_timestamp(int create); ++int timestamp_equal(long int chk_timestamp); + + #endif /* _FILE_H */ +Index: multipath-tools-130222/multipathd/pidfile.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/pidfile.c ++++ multipath-tools-130222/multipathd/pidfile.c +@@ -9,6 +9,7 @@ + #include /* for fcntl() */ + + #include ++#include + + #include "pidfile.h" + +@@ -18,6 +19,8 @@ int pidfile_create(const char *pidFile, + struct flock lock; + int fd, value; + ++ if (ensure_directories_exist(pidFile, 0700)) ++ return 1; + if((fd = open(pidFile, O_WRONLY | O_CREAT, + (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) { + condlog(0, "Cannot open pidfile [%s], error was [%s]", +Index: multipath-tools-130222/libmultipath/wwids.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.c ++++ multipath-tools-130222/libmultipath/wwids.c +@@ -125,6 +125,7 @@ replace_wwids(vector mp) + goto out_file; + } + ret = 0; ++ update_timestamp(0); + out_file: + close(fd); + out: +@@ -209,6 +210,8 @@ remove_wwid(char *wwid) { + goto out_file; + } + ret = do_remove_wwid(fd, str); ++ if (!ret) ++ update_timestamp(0); + + out_file: + close(fd); +@@ -294,8 +297,10 @@ remember_wwid(char *wwid) + condlog(3, "failed writing wwid %s to wwids file", wwid); + return -1; + } +- if (ret == 1) ++ if (ret == 1) { + condlog(3, "wrote wwid %s to wwids file", wwid); ++ update_timestamp(0); ++ } + else + condlog(4, "wwid %s already in wwids file", wwid); + return 0; +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -4,18 +4,34 @@ SUBSYSTEM!="block", GOTO="end_mpath" + + IMPORT{cmdline}="nompath" + ENV{nompath}=="?*", GOTO="end_mpath" ++ENV{DEVTYPE}=="partition", GOTO="end_mpath" + ENV{MPATH_SBIN_PATH}="/sbin" + TEST!="$env{MPATH_SBIN_PATH}/multipath", ENV{MPATH_SBIN_PATH}="/usr/sbin" ++TEST!="/etc/multipath.conf", GOTO="check_kpartx" + +-ACTION=="add", ENV{DEVTYPE}!="partition", \ +- ENV{DM_MULTIPATH_DEVICE_PATH}!="1", \ +- TEST=="/etc/multipath.conf", \ ++ACTION=="add", ENV{DM_MULTIPATH_DEVICE_PATH}!="1", \ + PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -c $tempnode", \ +- ENV{DM_MULTIPATH_DEVICE_PATH}="1" ENV{ID_FS_TYPE}="mpath_member" ++ ENV{DM_MULTIPATH_DEVICE_PATH}="1", ENV{ID_FS_TYPE}="mpath_member" + +-ENV{DM_MULTIPATH_DEVICE_PATH}=="1", ENV{DEVTYPE}!="partition", \ ++ENV{DM_MULTIPATH_DEVICE_PATH}=="1", \ + RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}" + ++ACTION!="change", GOTO="update_timestamp" ++IMPORT{db}="DM_MULTIPATH_TIMESTAMP" ++IMPORT{db}="DM_MULTIPATH_DEVICE_PATH" ++# Check if the device is part of a multipath device. the -T option just keeps ++# the old result if the timestamp hasn't changed. ++PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -T $env{DM_MULTIPATH_TIMESTAMP}:$env{DM_MULTIPATH_DEVICE_PATH} -c $env{DEVNAME}", \ ++ ENV{DM_MULTIPATH_DEVICE_PATH}="1", ENV{ID_FS_TYPE}="mpath_member", \ ++ GOTO="update_timestamp" ++ ++# If the device isn't part of a multipath device, clear this ++ENV{DM_MULTIPATH_DEVICE_PATH}="" ++ ++LABEL="update_timestamp" ++IMPORT{file}="/run/multipathd/timestamp" ++ ++LABEL="check_kpartx" + KERNEL!="dm-*", GOTO="end_mpath" + ENV{DM_UUID}=="mpath-?*|part[0-9]*-mpath-?*", OPTIONS+="link_priority=10" + ACTION!="change", GOTO="end_mpath" +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -54,6 +54,7 @@ + #include + #include + #include ++#include + + #include "main.h" + #include "pidfile.h" +@@ -1417,6 +1418,7 @@ reconfigure (struct vectors * vecs) + free_config(old); + retval = 0; + } ++ update_timestamp(0); + + return retval; + } +@@ -1709,6 +1711,7 @@ child (void * param) + + /* Startup complete, create logfile */ + pid_rc = pidfile_create(DEFAULT_PIDFILE, daemon_pid); ++ update_timestamp(1); + /* Ignore errors, we can live without */ + + running_state = DAEMON_RUNNING; +@@ -1758,6 +1761,7 @@ child (void * param) + if (!pid_rc) { + condlog(3, "unlink pidfile"); + unlink(DEFAULT_PIDFILE); ++ unlink(DEFAULT_TIMESTAMP_FILE); + } + + condlog(2, "--------shut down-------"); +Index: multipath-tools-130222/multipathd/multipathd.service +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.service ++++ multipath-tools-130222/multipathd/multipathd.service +@@ -9,7 +9,7 @@ Conflicts=shutdown.target + + [Service] + Type=forking +-PIDFile=/var/run/multipathd.pid ++PIDFile=/var/run/multipathd/multipathd.pid + ExecStartPre=/sbin/modprobe dm-multipath + ExecStart=/sbin/multipathd + ExecReload=/sbin/multipathd reconfigure +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -55,6 +55,7 @@ + #include + #include + #include ++#include + #include "dev_t.h" + + int logsink; +@@ -84,7 +85,7 @@ usage (char * progname) + { + fprintf (stderr, VERSION_STRING); + fprintf (stderr, "Usage:\n"); +- fprintf (stderr, " %s [-c|-w|-W] [-d] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); ++ fprintf (stderr, " %s [-c|-w|-W] [-d] [-T tm:val] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); + fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); + fprintf (stderr, " %s -F [-v lvl]\n", progname); + fprintf (stderr, " %s -t\n", progname); +@@ -98,6 +99,9 @@ usage (char * progname) + " -f flush a multipath device map\n" \ + " -F flush all multipath device maps\n" \ + " -c check if a device should be a path in a multipath device\n" \ ++ " -T tm:val\n" \ ++ " check if tm matches the multipathd timestamp. If so val is\n" \ ++ " whether or not the device is a path in a multipath device\n" \ + " -q allow queue_if_no_path when multipathd is not running\n"\ + " -d dry run, do not create or update devmaps\n" \ + " -t dump internal hardware table\n" \ +@@ -441,7 +445,31 @@ main (int argc, char *argv[]) + extern char *optarg; + extern int optind; + int r = 1; +- ++ long int timestamp = -1; ++ int valid = -1; ++ while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { ++ switch(arg) { ++ case 'T': ++ if (optarg[0] == ':') ++ sscanf(optarg, ":%d", &valid); ++ else ++ sscanf(optarg, "%ld:%d", ×tamp, &valid); ++ if (timestamp_equal(timestamp)) ++ return (valid != 1); ++ break; ++ case ':': ++ fprintf(stderr, "Missing option argument\n"); ++ usage(argv[0]); ++ exit(1); ++ case '?': ++ fprintf(stderr, "Unknown switch: %s\n", optarg); ++ usage(argv[0]); ++ exit(1); ++ default: ++ break; ++ } ++ } ++ optind = 1; + if (getuid() != 0) { + fprintf(stderr, "need to be root\n"); + exit(1); +@@ -455,7 +483,7 @@ main (int argc, char *argv[]) + if (dm_prereq()) + exit(1); + +- while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:BrtqwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { + switch(arg) { + case 1: printf("optarg : %s\n",optarg); + break; +@@ -517,6 +545,8 @@ main (int argc, char *argv[]) + case 't': + r = dump_config(); + goto out; ++ case 'T': ++ break; + case 'h': + usage(argv[0]); + exit(0); diff --git a/SOURCES/0065-UPBZ-995538-fail-rdac-on-unavailable.patch b/SOURCES/0065-UPBZ-995538-fail-rdac-on-unavailable.patch new file mode 100644 index 0000000..ca72b61 --- /dev/null +++ b/SOURCES/0065-UPBZ-995538-fail-rdac-on-unavailable.patch @@ -0,0 +1,21 @@ +--- + libmultipath/checkers/rdac.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/libmultipath/checkers/rdac.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/rdac.c ++++ multipath-tools-130222/libmultipath/checkers/rdac.c +@@ -222,10 +222,9 @@ libcheck_check (struct checker * c) + goto done; + } + +- /* check if controller is in service mode */ ++ /* check if controller is reporting asymmetric access state of unavailable */ + if ((inq.avtcvp & 0x10) && +- ((inq.asym_access_state_cur & 0x0F) == 0x3) && +- (inq.vendor_specific_cur == 0x7)) { ++ ((inq.asym_access_state_cur & 0x0F) == 0x3)) { + ret = PATH_DOWN; + goto done; + } diff --git a/SOURCES/0066-UP-dos-4k-partition-fix.patch b/SOURCES/0066-UP-dos-4k-partition-fix.patch new file mode 100644 index 0000000..a2d1b44 --- /dev/null +++ b/SOURCES/0066-UP-dos-4k-partition-fix.patch @@ -0,0 +1,159 @@ +--- + kpartx/dos.c | 17 ++++++++++------- + kpartx/gpt.c | 20 +------------------- + kpartx/kpartx.c | 12 ++++++++++++ + kpartx/kpartx.h | 8 ++++++++ + 4 files changed, 31 insertions(+), 26 deletions(-) + +Index: multipath-tools-130222/kpartx/dos.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/dos.c ++++ multipath-tools-130222/kpartx/dos.c +@@ -26,7 +26,9 @@ read_extended_partition(int fd, struct p + int moretodo = 1; + int i, n=0; + +- next = start = le32_to_cpu(ep->start_sect); ++ int sector_size_mul = get_sector_size(fd)/512; ++ ++ next = start = sector_size_mul * le32_to_cpu(ep->start_sect); + + while (moretodo) { + here = next; +@@ -45,14 +47,14 @@ read_extended_partition(int fd, struct p + memcpy(&p, bp + 0x1be + i * sizeof (p), sizeof (p)); + if (is_extended(p.sys_type)) { + if (p.nr_sects && !moretodo) { +- next = start + le32_to_cpu(p.start_sect); ++ next = start + sector_size_mul * le32_to_cpu(p.start_sect); + moretodo = 1; + } + continue; + } + if (n < ns) { +- sp[n].start = here + le32_to_cpu(p.start_sect); +- sp[n].size = le32_to_cpu(p.nr_sects); ++ sp[n].start = here + sector_size_mul * le32_to_cpu(p.start_sect); ++ sp[n].size = sector_size_mul * le32_to_cpu(p.nr_sects); + n++; + } else { + fprintf(stderr, +@@ -76,6 +78,7 @@ read_dos_pt(int fd, struct slice all, st + unsigned long offset = all.start; + int i, n=4; + unsigned char *bp; ++ int sector_size_mul = get_sector_size(fd)/512; + + bp = (unsigned char *)getblock(fd, offset); + if (bp == NULL) +@@ -89,8 +92,8 @@ read_dos_pt(int fd, struct slice all, st + if (is_gpt(p.sys_type)) + return 0; + if (i < ns) { +- sp[i].start = le32_to_cpu(p.start_sect); +- sp[i].size = le32_to_cpu(p.nr_sects); ++ sp[i].start = sector_size_mul * le32_to_cpu(p.start_sect); ++ sp[i].size = sector_size_mul * le32_to_cpu(p.nr_sects); + } else { + fprintf(stderr, + "dos_partition: too many slices\n"); +@@ -99,7 +102,7 @@ read_dos_pt(int fd, struct slice all, st + if (is_extended(p.sys_type)) { + n += read_extended_partition(fd, &p, sp+n, ns-n); + /* hide the extended partition itself */ +- sp[i].size = 2; ++ sp[i].size = sector_size_mul * 2; + } + } + return n; +Index: multipath-tools-130222/kpartx/gpt.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/gpt.c ++++ multipath-tools-130222/kpartx/gpt.c +@@ -38,6 +38,7 @@ + #include + #include + #include "crc32.h" ++#include "kpartx.h" + + #if BYTE_ORDER == LITTLE_ENDIAN + # define __le16_to_cpu(x) (x) +@@ -116,25 +117,6 @@ is_pmbr_valid(legacy_mbr *mbr) + + + /************************************************************ +- * get_sector_size +- * Requires: +- * - filedes is an open file descriptor, suitable for reading +- * Modifies: nothing +- * Returns: +- * sector size, or 512. +- ************************************************************/ +-static int +-get_sector_size(int filedes) +-{ +- int rc, sector_size = 512; +- +- rc = ioctl(filedes, BLKSSZGET, §or_size); +- if (rc) +- sector_size = 512; +- return sector_size; +-} +- +-/************************************************************ + * _get_num_sectors + * Requires: + * - filedes is an open file descriptor, suitable for reading +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -606,3 +607,14 @@ getblock (int fd, unsigned int secnr) { + + return bp->block; + } ++ ++int ++get_sector_size(int filedes) ++{ ++ int rc, sector_size = 512; ++ ++ rc = ioctl(filedes, BLKSSZGET, §or_size); ++ if (rc) ++ sector_size = 512; ++ return sector_size; ++} +Index: multipath-tools-130222/kpartx/kpartx.h +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.h ++++ multipath-tools-130222/kpartx/kpartx.h +@@ -2,6 +2,7 @@ + #define _KPARTX_H + + #include ++#include + + /* + * For each partition type there is a routine that takes +@@ -18,6 +19,13 @@ + #define safe_sprintf(var, format, args...) \ + snprintf(var, sizeof(var), format, ##args) >= sizeof(var) + ++#ifndef BLKSSZGET ++#define BLKSSZGET _IO(0x12,104) /* get block device sector size */ ++#endif ++ ++int ++get_sector_size(int filedes); ++ + /* + * units: 512 byte sectors + */ diff --git a/SOURCES/0067-RHBZ-1022899-fix-udev-partition-handling.patch b/SOURCES/0067-RHBZ-1022899-fix-udev-partition-handling.patch new file mode 100644 index 0000000..6f0a3d8 --- /dev/null +++ b/SOURCES/0067-RHBZ-1022899-fix-udev-partition-handling.patch @@ -0,0 +1,37 @@ +--- + multipath/multipath.rules | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -13,12 +13,13 @@ ACTION=="add", ENV{DM_MULTIPATH_DEVICE_P + PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -c $tempnode", \ + ENV{DM_MULTIPATH_DEVICE_PATH}="1", ENV{ID_FS_TYPE}="mpath_member" + +-ENV{DM_MULTIPATH_DEVICE_PATH}=="1", \ ++ENV{DM_MULTIPATH_DEVICE_PATH}=="1", ENV{DM_MULTIPATH_WIPE_PARTS}="1", \ + RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}" + + ACTION!="change", GOTO="update_timestamp" + IMPORT{db}="DM_MULTIPATH_TIMESTAMP" + IMPORT{db}="DM_MULTIPATH_DEVICE_PATH" ++IMPORT{db}="DM_MULTIPATH_WIPE_PARTS" + # Check if the device is part of a multipath device. the -T option just keeps + # the old result if the timestamp hasn't changed. + PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -T $env{DM_MULTIPATH_TIMESTAMP}:$env{DM_MULTIPATH_DEVICE_PATH} -c $env{DEVNAME}", \ +@@ -27,8 +28,13 @@ PROGRAM=="$env{MPATH_SBIN_PATH}/multipat + + # If the device isn't part of a multipath device, clear this + ENV{DM_MULTIPATH_DEVICE_PATH}="" ++ENV{DM_MULTIPATH_WIPE_PARTS}="" + + LABEL="update_timestamp" ++ENV{DM_MULTIPATH_DEVICE_PATH}=="1", ENV{DM_MULTIPATH_WIPE_PARTS}!="1", \ ++ ENV{DM_MULTIPATH_WIPE_PARTS}="1", \ ++ RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}" ++ + IMPORT{file}="/run/multipathd/timestamp" + + LABEL="check_kpartx" diff --git a/SOURCES/0068-RHBZ-1034578-label-partition-devices.patch b/SOURCES/0068-RHBZ-1034578-label-partition-devices.patch new file mode 100644 index 0000000..e8008f7 --- /dev/null +++ b/SOURCES/0068-RHBZ-1034578-label-partition-devices.patch @@ -0,0 +1,18 @@ +--- + multipath/multipath.rules | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -4,7 +4,8 @@ SUBSYSTEM!="block", GOTO="end_mpath" + + IMPORT{cmdline}="nompath" + ENV{nompath}=="?*", GOTO="end_mpath" +-ENV{DEVTYPE}=="partition", GOTO="end_mpath" ++ENV{DEVTYPE}=="partition", IMPORT{parent}="DM_MULTIPATH_DEVICE_PATH", \ ++ GOTO="end_mpath" + ENV{MPATH_SBIN_PATH}="/sbin" + TEST!="$env{MPATH_SBIN_PATH}/multipath", ENV{MPATH_SBIN_PATH}="/usr/sbin" + TEST!="/etc/multipath.conf", GOTO="check_kpartx" diff --git a/SOURCES/0069-UPBZ-1033791-improve-rdac-checker.patch b/SOURCES/0069-UPBZ-1033791-improve-rdac-checker.patch new file mode 100644 index 0000000..c838f29 --- /dev/null +++ b/SOURCES/0069-UPBZ-1033791-improve-rdac-checker.patch @@ -0,0 +1,153 @@ +--- + libmultipath/checkers/rdac.c | 91 ++++++++++++++++++++++++++++++++++++++----- + libmultipath/discovery.c | 2 + 2 files changed, 81 insertions(+), 12 deletions(-) + +Index: multipath-tools-130222/libmultipath/checkers/rdac.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/rdac.c ++++ multipath-tools-130222/libmultipath/checkers/rdac.c +@@ -34,6 +34,18 @@ + #define MSG_RDAC_UP "rdac checker reports path is up" + #define MSG_RDAC_DOWN "rdac checker reports path is down" + #define MSG_RDAC_GHOST "rdac checker reports path is ghost" ++#define MSG_RDAC_DOWN_TYPE(STR) MSG_RDAC_DOWN": "STR ++ ++#define RTPG_UNAVAILABLE 0x3 ++#define RTPG_OFFLINE 0xE ++#define RTPG_TRANSITIONING 0xF ++ ++#define RTPG_UNAVAIL_NON_RESPONSIVE 0x2 ++#define RTPG_UNAVAIL_IN_RESET 0x3 ++#define RTPG_UNAVAIL_CFW_DL1 0x4 ++#define RTPG_UNAVAIL_CFW_DL2 0x5 ++#define RTPG_UNAVAIL_QUIESCED 0x6 ++#define RTPG_UNAVAIL_SERVICE_MODE 0x7 + + struct control_mode_page { + unsigned char header[8]; +@@ -199,22 +211,64 @@ struct volume_access_inq + char PQ_PDT; + char dontcare0[7]; + char avtcvp; +- char dontcare1; +- char asym_access_state_cur; ++ char vol_ppp; ++ char aas_cur; + char vendor_specific_cur; +- char dontcare2[36]; ++ char aas_alt; ++ char vendor_specific_alt; ++ char dontcare1[34]; + }; + ++const char ++*checker_msg_string(struct volume_access_inq *inq) ++{ ++ /* lun not connected */ ++ if (((inq->PQ_PDT & 0xE0) == 0x20) || (inq->PQ_PDT & 0x7f)) ++ return MSG_RDAC_DOWN_TYPE("lun not connected"); ++ ++ /* if no tpg data is available, give the generic path down message */ ++ if (!(inq->avtcvp & 0x10)) ++ return MSG_RDAC_DOWN; ++ ++ /* controller is booting up */ ++ if (((inq->aas_cur & 0x0F) == RTPG_TRANSITIONING) && ++ (inq->aas_alt & 0x0F) != RTPG_TRANSITIONING) ++ return MSG_RDAC_DOWN_TYPE("ctlr is in startup sequence"); ++ ++ /* if not unavailable, give generic message */ ++ if ((inq->aas_cur & 0x0F) != RTPG_UNAVAILABLE) ++ return MSG_RDAC_DOWN; ++ ++ /* target port group unavailable */ ++ switch (inq->vendor_specific_cur) { ++ case RTPG_UNAVAIL_NON_RESPONSIVE: ++ return MSG_RDAC_DOWN_TYPE("non-responsive to queries"); ++ case RTPG_UNAVAIL_IN_RESET: ++ return MSG_RDAC_DOWN_TYPE("ctlr held in reset"); ++ case RTPG_UNAVAIL_CFW_DL1: ++ case RTPG_UNAVAIL_CFW_DL2: ++ return MSG_RDAC_DOWN_TYPE("ctlr firmware downloading"); ++ case RTPG_UNAVAIL_QUIESCED: ++ return MSG_RDAC_DOWN_TYPE("ctlr quiesced by admin request"); ++ case RTPG_UNAVAIL_SERVICE_MODE: ++ return MSG_RDAC_DOWN_TYPE("ctlr is in service mode"); ++ default: ++ return MSG_RDAC_DOWN_TYPE("ctlr is unavailable"); ++ } ++} ++ + extern int + libcheck_check (struct checker * c) + { + struct volume_access_inq inq; +- int ret; ++ int ret, inqfail; + ++ inqfail = 0; + memset(&inq, 0, sizeof(struct volume_access_inq)); + if (0 != do_inq(c->fd, 0xC9, &inq, sizeof(struct volume_access_inq), + c->timeout)) { + ret = PATH_DOWN; ++ inqfail = 1; + goto done; + } else if (((inq.PQ_PDT & 0xE0) == 0x20) || (inq.PQ_PDT & 0x7f)) { + /* LUN not connected*/ +@@ -222,11 +276,27 @@ libcheck_check (struct checker * c) + goto done; + } + +- /* check if controller is reporting asymmetric access state of unavailable */ +- if ((inq.avtcvp & 0x10) && +- ((inq.asym_access_state_cur & 0x0F) == 0x3)) { +- ret = PATH_DOWN; +- goto done; ++ /* If TPGDE bit set, evaluate TPG information */ ++ if ((inq.avtcvp & 0x10)) { ++ switch (inq.aas_cur & 0x0F) { ++ /* Never use the path if it reports unavailable */ ++ case RTPG_UNAVAILABLE: ++ ret = PATH_DOWN; ++ goto done; ++ /* ++ * If both controllers report transitioning, it ++ * means mode select or STPG is being processed. ++ * ++ * If this controller alone is transitioning, it's ++ * booting and we shouldn't use it yet. ++ */ ++ case RTPG_TRANSITIONING: ++ if ((inq.aas_alt & 0xF) != RTPG_TRANSITIONING) { ++ ret = PATH_DOWN; ++ goto done; ++ } ++ break; ++ } + } + + /* If owner set or ioship mode is enabled return PATH_UP always */ +@@ -238,7 +308,8 @@ libcheck_check (struct checker * c) + done: + switch (ret) { + case PATH_DOWN: +- MSG(c, MSG_RDAC_DOWN); ++ MSG(c, (inqfail) ? MSG_RDAC_DOWN_TYPE("inquiry failed") : ++ checker_msg_string(&inq)); + break; + case PATH_UP: + MSG(c, MSG_RDAC_UP); +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -1116,8 +1116,6 @@ pathinfo (struct path *pp, vector hwtabl + if (!strlen(pp->wwid)) + get_uid(pp); + get_prio(pp); +- } else { +- pp->priority = PRIO_UNDEF; + } + } + diff --git a/SOURCES/0070-RHBZ-1036503-blacklist-td-devs.patch b/SOURCES/0070-RHBZ-1036503-blacklist-td-devs.patch new file mode 100644 index 0000000..ffcae46 --- /dev/null +++ b/SOURCES/0070-RHBZ-1036503-blacklist-td-devs.patch @@ -0,0 +1,17 @@ +--- + libmultipath/blacklist.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/blacklist.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/blacklist.c ++++ multipath-tools-130222/libmultipath/blacklist.c +@@ -163,7 +163,7 @@ setup_default_blist (struct config * con + if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT)) + return 1; + +- str = STRDUP("^hd[a-z]"); ++ str = STRDUP("^(td|hd)[a-z]"); + if (!str) + return 1; + if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT)) diff --git a/SOURCES/0071-RHBZ-1031546-strip-dev.patch b/SOURCES/0071-RHBZ-1031546-strip-dev.patch new file mode 100644 index 0000000..64118c2 --- /dev/null +++ b/SOURCES/0071-RHBZ-1031546-strip-dev.patch @@ -0,0 +1,248 @@ +--- + libmultipath/util.c | 22 ++++++++++++++++++++++ + libmultipath/util.h | 1 + + multipath/main.c | 23 +---------------------- + multipathd/cli_handlers.c | 18 ++++++++++++++++++ + 4 files changed, 42 insertions(+), 22 deletions(-) + +Index: multipath-tools-130222/libmultipath/util.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/util.c ++++ multipath-tools-130222/libmultipath/util.c +@@ -236,6 +236,28 @@ skip_proc: + return 0; + } + ++/* This function returns a pointer inside of the supplied pathname string. ++ * If is_path_device is true, it may also modify the supplied string */ ++char *convert_dev(char *name, int is_path_device) ++{ ++ char *ptr; ++ ++ if (!name) ++ return NULL; ++ if (is_path_device) { ++ ptr = strstr(name, "cciss/"); ++ if (ptr) { ++ ptr += 5; ++ *ptr = '!'; ++ } ++ } ++ if (!strncmp(name, "/dev/", 5) && strlen(name) > 5) ++ ptr = name + 5; ++ else ++ ptr = name; ++ return ptr; ++} ++ + dev_t parse_devt(const char *dev_t) + { + int maj, min; +Index: multipath-tools-130222/libmultipath/util.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/util.h ++++ multipath-tools-130222/libmultipath/util.h +@@ -10,6 +10,7 @@ size_t strlcat(char *dst, const char *sr + void remove_trailing_chars(char *path, char c); + int devt2devname (char *, int, char *); + dev_t parse_devt(const char *dev_t); ++char *convert_dev(char *dev, int is_path_device); + + #define safe_sprintf(var, format, args...) \ + snprintf(var, sizeof(var), format, ##args) >= sizeof(var) +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -254,16 +254,7 @@ configure (void) + vecs.pathvec = pathvec; + vecs.mpvec = curmp; + +- /* +- * dev is "/dev/" . "sysfs block dev" +- */ +- if (conf->dev) { +- if (!strncmp(conf->dev, "/dev/", 5) && +- strlen(conf->dev) > 5) +- dev = conf->dev + 5; +- else +- dev = conf->dev; +- } ++ dev = convert_dev(conf->dev, (conf->dev_type == DEV_DEVNODE)); + + /* + * if we have a blacklisted device parameter, exit early +@@ -427,16 +418,6 @@ get_dev_type(char *dev) { + return DEV_DEVMAP; + } + +-static void +-convert_dev(char *dev) +-{ +- char *ptr = strstr(dev, "cciss/"); +- if (ptr) { +- ptr += 5; +- *ptr = '!'; +- } +-} +- + int + main (int argc, char *argv[]) + { +@@ -577,8 +558,6 @@ main (int argc, char *argv[]) + + strncpy(conf->dev, argv[optind], FILE_NAME_SIZE); + conf->dev_type = get_dev_type(conf->dev); +- if (conf->dev_type == DEV_DEVNODE) +- convert_dev(conf->dev); + } + conf->daemon = 0; + +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -235,6 +235,7 @@ cli_list_map_topology (void * v, char ** + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); + ++ param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); + mpp = find_mp_by_str(vecs->mpvec, param); + +@@ -416,6 +417,7 @@ cli_add_path (void * v, char ** reply, i + struct path *pp; + int r; + ++ param = convert_dev(param, 1); + condlog(2, "%s: add path (operator)", param); + + if (filter_devnode(conf->blist_devnode, conf->elist_devnode, +@@ -459,6 +461,7 @@ cli_del_path (void * v, char ** reply, i + char * param = get_keyparam(v, PATH); + struct path *pp; + ++ param = convert_dev(param, 1); + condlog(2, "%s: remove path (operator)", param); + pp = find_path_by_dev(vecs->pathvec, param); + if (!pp) { +@@ -478,6 +481,7 @@ cli_add_map (void * v, char ** reply, in + char *alias; + int rc; + ++ param = convert_dev(param, 0); + condlog(2, "%s: add map (operator)", param); + + if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param) > 0) { +@@ -518,6 +522,7 @@ cli_del_map (void * v, char ** reply, in + char *alias; + int rc; + ++ param = convert_dev(param, 0); + condlog(2, "%s: remove map (operator)", param); + minor = dm_get_minor(param); + if (minor < 0) { +@@ -549,6 +554,7 @@ cli_reload(void *v, char **reply, int *l + struct multipath *mpp; + int minor; + ++ mapname = convert_dev(mapname, 0); + condlog(2, "%s: reload map (operator)", mapname); + if (sscanf(mapname, "dm-%d", &minor) == 1) + mpp = find_mp_by_minor(vecs->mpvec, minor); +@@ -591,6 +597,7 @@ cli_resize(void *v, char **reply, int *l + struct pathgroup *pgp; + struct path *pp; + ++ mapname = convert_dev(mapname, 0); + condlog(2, "%s: resize map (operator)", mapname); + if (sscanf(mapname, "dm-%d", &minor) == 1) + mpp = find_mp_by_minor(vecs->mpvec, minor); +@@ -665,6 +672,7 @@ cli_restore_queueing(void *v, char **rep + struct multipath *mpp; + int minor; + ++ mapname = convert_dev(mapname, 0); + condlog(2, "%s: restore map queueing (operator)", mapname); + if (sscanf(mapname, "dm-%d", &minor) == 1) + mpp = find_mp_by_minor(vecs->mpvec, minor); +@@ -716,6 +724,7 @@ cli_disable_queueing(void *v, char **rep + struct multipath *mpp; + int minor; + ++ mapname = convert_dev(mapname, 0); + condlog(2, "%s: disable map queueing (operator)", mapname); + if (sscanf(mapname, "dm-%d", &minor) == 1) + mpp = find_mp_by_minor(vecs->mpvec, minor); +@@ -753,6 +762,7 @@ cli_switch_group(void * v, char ** reply + char * mapname = get_keyparam(v, MAP); + int groupnum = atoi(get_keyparam(v, GROUP)); + ++ mapname = convert_dev(mapname, 0); + condlog(2, "%s: switch to path group #%i (operator)", mapname, groupnum); + + return dm_switchgroup(mapname, groupnum); +@@ -775,6 +785,7 @@ cli_suspend(void * v, char ** reply, int + char * param = get_keyparam(v, MAP); + int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param); + ++ param = convert_dev(param, 0); + condlog(2, "%s: suspend (operator)", param); + + if (!r) /* error */ +@@ -796,6 +807,7 @@ cli_resume(void * v, char ** reply, int + char * param = get_keyparam(v, MAP); + int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param); + ++ param = convert_dev(param, 0); + condlog(2, "%s: resume (operator)", param); + + if (!r) /* error */ +@@ -817,6 +829,7 @@ cli_reinstate(void * v, char ** reply, i + char * param = get_keyparam(v, PATH); + struct path * pp; + ++ param = convert_dev(param, 1); + pp = find_path_by_dev(vecs->pathvec, param); + + if (!pp) +@@ -837,6 +850,7 @@ cli_reassign (void * v, char ** reply, i + { + char * param = get_keyparam(v, MAP); + ++ param = convert_dev(param, 0); + condlog(3, "%s: reset devices (operator)", param); + + dm_reassign(param); +@@ -851,6 +865,7 @@ cli_fail(void * v, char ** reply, int * + struct path * pp; + int r; + ++ param = convert_dev(param, 1); + pp = find_path_by_dev(vecs->pathvec, param); + + if (!pp) +@@ -962,6 +977,7 @@ cli_getprstatus (void * v, char ** reply + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); + ++ param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); + mpp = find_mp_by_str(vecs->mpvec, param); + +@@ -991,6 +1007,7 @@ cli_setprstatus(void * v, char ** reply, + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); + ++ param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); + mpp = find_mp_by_str(vecs->mpvec, param); + +@@ -1013,6 +1030,7 @@ cli_unsetprstatus(void * v, char ** repl + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); + ++ param = convert_dev(param, 0); + get_path_layout(vecs->pathvec, 0); + mpp = find_mp_by_str(vecs->mpvec, param); + diff --git a/SOURCES/0072-RHBZ-1039199-check-loop-control.patch b/SOURCES/0072-RHBZ-1039199-check-loop-control.patch new file mode 100644 index 0000000..21bd0c3 --- /dev/null +++ b/SOURCES/0072-RHBZ-1039199-check-loop-control.patch @@ -0,0 +1,46 @@ +--- + kpartx/lopart.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/kpartx/lopart.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/lopart.c ++++ multipath-tools-130222/kpartx/lopart.c +@@ -32,6 +32,10 @@ + #include "lopart.h" + #include "xstrncpy.h" + ++#ifndef LOOP_CTL_GET_FREE ++#define LOOP_CTL_GET_FREE 0x4C82 ++#endif ++ + #if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) \ + && !defined (__s390x__) + #define int2ptr(x) ((void *) ((int) x)) +@@ -140,14 +144,24 @@ find_unused_loop_device (void) + + char dev[20]; + char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" }; +- int i, j, fd, somedev = 0, someloop = 0, loop_known = 0; ++ int i, j, fd, first = 0, somedev = 0, someloop = 0, loop_known = 0; + struct stat statbuf; + struct loop_info loopinfo; + FILE *procdev; + ++ if (stat("/dev/loop-control", &statbuf) == 0 && ++ S_ISCHR(statbuf.st_mode)) { ++ fd = open("/dev/loop-control", O_RDWR); ++ if (fd >= 0) { ++ first = ioctl(fd, LOOP_CTL_GET_FREE); ++ close(fd); ++ } ++ if (first < 0) ++ first = 0; ++ } + for (j = 0; j < SIZE(loop_formats); j++) { + +- for(i = 0; i < 256; i++) { ++ for(i = first; i < 256; i++) { + sprintf(dev, loop_formats[j], i); + + if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) { diff --git a/SOURCES/0073-RH-update-build-flags.patch b/SOURCES/0073-RH-update-build-flags.patch new file mode 100644 index 0000000..3ab72d0 --- /dev/null +++ b/SOURCES/0073-RH-update-build-flags.patch @@ -0,0 +1,33 @@ +--- + Makefile.inc | 2 +- + libmultipath/checkers/rdac.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/Makefile.inc +=================================================================== +--- multipath-tools-130222.orig/Makefile.inc ++++ multipath-tools-130222/Makefile.inc +@@ -39,7 +39,7 @@ GZIP = /bin/gzip -9 -c + INSTALL_PROGRAM = install + + ifndef RPM_OPT_FLAGS +- RPM_OPT_FLAGS = -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 ++ RPM_OPT_FLAGS = -O2 -g -pipe -Wformat-security -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 + endif + + LDFLAGS += -Wl,-z,relro +Index: multipath-tools-130222/libmultipath/checkers/rdac.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/rdac.c ++++ multipath-tools-130222/libmultipath/checkers/rdac.c +@@ -308,8 +308,8 @@ libcheck_check (struct checker * c) + done: + switch (ret) { + case PATH_DOWN: +- MSG(c, (inqfail) ? MSG_RDAC_DOWN_TYPE("inquiry failed") : +- checker_msg_string(&inq)); ++ MSG(c, "%s", (inqfail) ? MSG_RDAC_DOWN_TYPE("inquiry failed") : ++ checker_msg_string(&inq)); + break; + case PATH_UP: + MSG(c, MSG_RDAC_UP); diff --git a/SOURCES/0074-RHBZ-1056976-dm-mpath-rules.patch b/SOURCES/0074-RHBZ-1056976-dm-mpath-rules.patch new file mode 100644 index 0000000..9f6c880 --- /dev/null +++ b/SOURCES/0074-RHBZ-1056976-dm-mpath-rules.patch @@ -0,0 +1,64 @@ +--- + multipath/11-dm-mpath.rules | 34 ++++++++++++++++++++++++++++++++++ + multipath/Makefile | 2 ++ + 2 files changed, 36 insertions(+) + +Index: multipath-tools-130222/multipath/11-dm-mpath.rules +=================================================================== +--- /dev/null ++++ multipath-tools-130222/multipath/11-dm-mpath.rules +@@ -0,0 +1,34 @@ ++ACTION!="add|change", GOTO="mpath_end" ++ENV{DM_UDEV_RULES_VSN}!="?*", GOTO="mpath_end" ++ENV{DM_UUID}!="mpath-?*", GOTO="mpath_end" ++ ++# Do not initiate scanning if no path is available, ++# otherwise there would be a hang or IO error on access. ++# We'd like to avoid this, especially within udev processing. ++ENV{DM_NR_VALID_PATHS}!="?*", IMPORT{db}="DM_NR_VALID_PATHS" ++ENV{DM_NR_VALID_PATHS}=="0", ENV{DM_NOSCAN}="1" ++ ++# Also skip all foreign rules if no path is available. ++# Remember the original value of DM_DISABLE_OTHER_RULES_FLAG ++# and restore it back once we have at least one path available. ++IMPORT{db}="DM_DISABLE_OTHER_RULES_FLAG_OLD" ++ENV{DM_ACTION}=="PATH_FAILED",\ ++ ENV{DM_NR_VALID_PATHS}=="0",\ ++ ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}=="",\ ++ ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="$env{DM_UDEV_DISABLE_OTHER_RULES_FLAG}",\ ++ ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1" ++ENV{DM_ACTION}=="PATH_REINSTATED",\ ++ ENV{DM_NR_VALID_PATHS}=="1",\ ++ ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="$env{DM_DISABLE_OTHER_RULES_FLAG_OLD}",\ ++ ENV{DM_DISABLE_OTHER_RULES_FLAG_OLD}="",\ ++ ENV{DM_ACTIVATION}="1" ++ ++# DM_SUBSYSTEM_UDEV_FLAG0 is the "RELOAD" flag for multipath subsystem. ++# Drop the DM_ACTIVATION flag here as mpath reloads tables if any of its ++# paths are lost/recovered. For any stack above the mpath device, this is not ++# something that should be reacted upon since it would be useless extra work. ++# It's exactly mpath's job to provide *seamless* device access to any of the ++# paths that are available underneath. ++ENV{DM_SUBSYSTEM_UDEV_FLAG0}=="1", ENV{DM_ACTIVATION}="0" ++ ++LABEL="mpath_end" +Index: multipath-tools-130222/multipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/multipath/Makefile ++++ multipath-tools-130222/multipath/Makefile +@@ -25,6 +25,7 @@ install: + $(INSTALL_PROGRAM) -m 755 mpathconf $(DESTDIR)$(bindir)/ + $(INSTALL_PROGRAM) -d $(DESTDIR)/usr/lib/udev/rules.d + $(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/usr/lib/udev/rules.d/62-multipath.rules ++ $(INSTALL_PROGRAM) -m 644 11-dm-mpath.rules $(DESTDIR)/usr/lib/udev/rules.d/11-dm-mpath.rules + $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir) + $(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir) +@@ -33,6 +34,7 @@ install: + + uninstall: + rm $(DESTDIR)/usr/lib/udev/rules.d/62-multipath.rules ++ rm $(DESTDIR)/usr/lib/udev/rules.d/11-dm-mpath.rules + rm $(DESTDIR)$(bindir)/$(EXEC) + rm $(DESTDIR)$(bindir)/mpathconf + rm $(DESTDIR)$(mandir)/$(EXEC).8.gz diff --git a/SOURCES/0075-RHBZ-1056976-reload-flag.patch b/SOURCES/0075-RHBZ-1056976-reload-flag.patch new file mode 100644 index 0000000..ee2cdee --- /dev/null +++ b/SOURCES/0075-RHBZ-1056976-reload-flag.patch @@ -0,0 +1,246 @@ +--- + kpartx/devmapper.c | 4 ++-- + kpartx/devmapper.h | 8 +++++++- + kpartx/kpartx.c | 6 +++--- + libmultipath/configure.c | 4 ++-- + libmultipath/devmapper.c | 26 ++++++++++++++------------ + libmultipath/devmapper.h | 10 ++++++++-- + multipathd/cli_handlers.c | 4 ++-- + 7 files changed, 38 insertions(+), 24 deletions(-) + +Index: multipath-tools-130222/kpartx/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.c ++++ multipath-tools-130222/kpartx/devmapper.c +@@ -60,7 +60,7 @@ dm_prereq (char * str, int x, int y, int + } + + extern int +-dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie) { ++dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie, uint16_t udev_flags) { + int r = 0; + int udev_wait_flag = (task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE); +@@ -78,7 +78,7 @@ dm_simplecmd (int task, const char *name + if (no_flush) + dm_task_no_flush(dmt); + +- if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, (udev_sync)? 0 : DM_UDEV_DISABLE_LIBRARY_FALLBACK)) ++ if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, ((udev_sync)? 0 : DM_UDEV_DISABLE_LIBRARY_FALLBACK) | udev_flags)) + goto out; + r = dm_task_run(dmt); + +Index: multipath-tools-130222/kpartx/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.h ++++ multipath-tools-130222/kpartx/devmapper.h +@@ -2,10 +2,16 @@ + #define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00)) + #define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12)) + ++#ifdef DM_SUBSYSTEM_UDEV_FLAG0 ++#define MPATH_UDEV_RELOAD_FLAG DM_SUBSYSTEM_UDEV_FLAG0 ++#else ++#define MPATH_UDEV_RELOAD_FLAG 0 ++#endif ++ + extern int udev_sync; + + int dm_prereq (char *, int, int, int); +-int dm_simplecmd (int, const char *, int, uint32_t *); ++int dm_simplecmd (int, const char *, int, uint32_t *, uint16_t); + int dm_addmap (int, const char *, const char *, const char *, uint64_t, + int, const char *, int, mode_t, uid_t, gid_t, uint32_t *); + int dm_map_present (char *); +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -421,7 +421,7 @@ main(int argc, char **argv){ + continue; + + if (!dm_simplecmd(DM_DEVICE_REMOVE, partname, +- 0, &cookie)) { ++ 0, &cookie, 0)) { + r++; + continue; + } +@@ -473,7 +473,7 @@ main(int argc, char **argv){ + } + if (op == DM_DEVICE_RELOAD && + !dm_simplecmd(DM_DEVICE_RESUME, partname, +- 1, &cookie)) { ++ 1, &cookie, MPATH_UDEV_RELOAD_FLAG)) { + fprintf(stderr, "resume failed on %s\n", + partname); + r++; +@@ -505,7 +505,7 @@ main(int argc, char **argv){ + continue; + + if (!dm_simplecmd(DM_DEVICE_REMOVE, +- partname, 1, &cookie)) { ++ partname, 1, &cookie, 0)) { + r++; + continue; + } +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -390,13 +390,13 @@ domap (struct multipath * mpp, char * pa + case ACT_RELOAD: + r = dm_addmap_reload(mpp, params); + if (r) +- r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias); ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, MPATH_UDEV_RELOAD_FLAG); + break; + + case ACT_RESIZE: + r = dm_addmap_reload(mpp, params); + if (r) +- r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1); ++ r = dm_simplecmd_flush(DM_DEVICE_RESUME, mpp->alias, 1, 0); + break; + + case ACT_RENAME: +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -103,7 +103,9 @@ dm_lib_prereq (void) + { + char version[64]; + int v[3]; +-#ifdef LIBDM_API_COOKIE ++#if defined(DM_SUBSYSTEM_UDEV_FLAG0) ++ int minv[3] = {1, 2, 82}; ++#elif defined(LIBDM_API_COOKIE) + int minv[3] = {1, 2, 38}; + #else + int minv[3] = {1, 2, 8}; +@@ -200,7 +202,7 @@ dm_prereq (void) + } + + static int +-dm_simplecmd (int task, const char *name, int no_flush, int need_sync) { ++dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags) { + int r = 0; + int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE)); +@@ -219,7 +221,7 @@ dm_simplecmd (int task, const char *name + dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ + #endif + +- if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0)) ++ if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags)) + goto out; + r = dm_task_run (dmt); + +@@ -229,13 +231,13 @@ dm_simplecmd (int task, const char *name + } + + extern int +-dm_simplecmd_flush (int task, const char *name, int needsync) { +- return dm_simplecmd(task, name, 0, needsync); ++dm_simplecmd_flush (int task, const char *name, int needsync, uint16_t udev_flags) { ++ return dm_simplecmd(task, name, 0, needsync, udev_flags); + } + + extern int +-dm_simplecmd_noflush (int task, const char *name) { +- return dm_simplecmd(task, name, 1, 1); ++dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) { ++ return dm_simplecmd(task, name, 1, 1, udev_flags); + } + + extern int +@@ -670,7 +672,7 @@ _dm_flush_map (const char * mapname, int + return 1; + } + +- r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync); ++ r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync, 0); + + if (r) { + condlog(4, "multipath map %s removed", mapname); +@@ -703,14 +705,14 @@ dm_suspend_and_flush_map (const char * m + if (s) + queue_if_no_path = 0; + else +- s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0); ++ s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0, 0); + + if (!dm_flush_map(mapname)) { + condlog(4, "multipath map %s removed", mapname); + return 0; + } + condlog(2, "failed to remove multipath map %s", mapname); +- dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname); ++ dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname, 0); + if (queue_if_no_path) + s = dm_queue_if_no_path((char *)mapname, 1); + return 1; +@@ -1077,7 +1079,7 @@ dm_remove_partmaps (const char * mapname + condlog(4, "partition map %s removed", + names->name); + dm_simplecmd_flush(DM_DEVICE_REMOVE, names->name, +- need_sync); ++ need_sync, 0); + } + + next = names->next; +@@ -1305,7 +1307,7 @@ int dm_reassign_table(const char *name, + condlog(3, "%s: failed to reassign targets", name); + goto out_reload; + } +- dm_simplecmd_noflush(DM_DEVICE_RESUME, name); ++ dm_simplecmd_noflush(DM_DEVICE_RESUME, name, MPATH_UDEV_RELOAD_FLAG); + } + r = 1; + +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -6,11 +6,17 @@ + #define TGT_MPATH "multipath" + #define TGT_PART "linear" + ++#ifdef DM_SUBSYSTEM_UDEV_FLAG0 ++#define MPATH_UDEV_RELOAD_FLAG DM_SUBSYSTEM_UDEV_FLAG0 ++#else ++#define MPATH_UDEV_RELOAD_FLAG 0 ++#endif ++ + void dm_init(void); + int dm_prereq (void); + int dm_drv_version (unsigned int * version, char * str); +-int dm_simplecmd_flush (int, const char *, int); +-int dm_simplecmd_noflush (int, const char *); ++int dm_simplecmd_flush (int, const char *, int, uint16_t); ++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 dm_map_present (const char *); +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -783,7 +783,7 @@ cli_suspend(void * v, char ** reply, int + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); +- int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param); ++ int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0); + + param = convert_dev(param, 0); + condlog(2, "%s: suspend (operator)", param); +@@ -805,7 +805,7 @@ cli_resume(void * v, char ** reply, int + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); +- int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param); ++ int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); + + param = convert_dev(param, 0); + condlog(2, "%s: resume (operator)", param); diff --git a/SOURCES/0076-RHBZ-1056686-add-hw_str_match.patch b/SOURCES/0076-RHBZ-1056686-add-hw_str_match.patch new file mode 100644 index 0000000..dc9aca6 --- /dev/null +++ b/SOURCES/0076-RHBZ-1056686-add-hw_str_match.patch @@ -0,0 +1,125 @@ +--- + libmultipath/config.c | 10 ++++++++-- + libmultipath/config.h | 1 + + libmultipath/dict.c | 28 ++++++++++++++++++++++++++++ + multipath/multipath.conf.5 | 11 +++++++++++ + 4 files changed, 48 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -431,11 +431,16 @@ restart: + break; + j = n; + vector_foreach_slot_after(hw, hwe2, j) { +- if (hwe_regmatch(hwe1, hwe2)) ++ if (conf->hw_strmatch) { ++ if (hwe_strmatch(hwe2, hwe1)) ++ continue; ++ } ++ else if (hwe_regmatch(hwe1, hwe2)) + continue; + /* dup */ + merge_hwe(hwe2, hwe1); +- if (hwe_strmatch(hwe2, hwe1) == 0) { ++ if (conf->hw_strmatch || ++ hwe_strmatch(hwe2, hwe1) == 0) { + vector_del_slot(hw, i); + free_hwe(hwe1); + n -= 1; +@@ -550,6 +555,7 @@ load_config (char * file, struct udev *u + conf->fast_io_fail = DEFAULT_FAST_IO_FAIL; + conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER; + conf->detect_prio = DEFAULT_DETECT_PRIO; ++ conf->hw_strmatch = 0; + + /* + * preload default hwtable +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -107,6 +107,7 @@ struct config { + int log_checker_err; + int allow_queueing; + int find_multipaths; ++ int hw_strmatch; + uid_t uid; + gid_t gid; + mode_t mode; +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -693,6 +693,25 @@ def_detect_prio_handler(vector strvec) + return 0; + } + ++static int ++def_hw_strmatch_handler(vector strvec) ++{ ++ char *buff; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if (!strncmp(buff, "on", 2) || !strncmp(buff, "yes", 3) || ++ !strncmp(buff, "1", 1)) ++ conf->hw_strmatch = 1; ++ else ++ conf->hw_strmatch = 0; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -2795,6 +2814,14 @@ snprint_def_detect_prio(char * buff, int + } + + static int ++snprint_def_hw_strmatch(char * buff, int len, void * data) ++{ ++ if (conf->hw_strmatch) ++ return snprintf(buff, len, "yes"); ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -2861,6 +2888,7 @@ init_keywords(void) + install_keyword("find_multipaths", &def_find_multipaths_handler, &snprint_def_find_multipaths); + install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler_handler); + install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio); ++ install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -400,6 +400,17 @@ will automatically use the + .I alua + prioritizer. If not, the prioritizer will be selected as usual. Default is + .I no ++.TP ++.B hw_str_match ++If set to ++.I yes ++, the vendor, product, and revision parameters of user device configs will be ++string matched against the built-in device configs to determine if they should ++modify an existing config, or create a new one. If set to ++.I no ++, the user device configs will be regular expression matched against the ++built-in configs instead. Default is ++.I no + . + .SH "blacklist section" + The diff --git a/SOURCES/0077-RHBZ-1054806-mpathconf-always-reload.patch b/SOURCES/0077-RHBZ-1054806-mpathconf-always-reload.patch new file mode 100644 index 0000000..467da8a --- /dev/null +++ b/SOURCES/0077-RHBZ-1054806-mpathconf-always-reload.patch @@ -0,0 +1,16 @@ +--- + multipath/mpathconf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/mpathconf +=================================================================== +--- multipath-tools-130222.orig/multipath/mpathconf ++++ multipath-tools-130222/multipath/mpathconf +@@ -316,6 +316,6 @@ elif [ "$ENABLE" = 0 ]; then + if [ "$HAVE_MULTIPATHD" = 1 ]; then + systemctl stop multipathd.service + fi +-elif [ -n "$CHANGED_CONFIG" -a "$HAVE_MULTIPATHD" = 1 ]; then ++elif [ "$HAVE_MULTIPATHD" = 1 ]; then + systemctl reload multipathd.service + fi diff --git a/SOURCES/0078-RHBZ-1054044-fix-mpathconf-manpage.patch b/SOURCES/0078-RHBZ-1054044-fix-mpathconf-manpage.patch new file mode 100644 index 0000000..b06b410 --- /dev/null +++ b/SOURCES/0078-RHBZ-1054044-fix-mpathconf-manpage.patch @@ -0,0 +1,17 @@ +--- + multipath/mpathconf.8 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/mpathconf.8 +=================================================================== +--- multipath-tools-130222.orig/multipath/mpathconf.8 ++++ multipath-tools-130222/multipath/mpathconf.8 +@@ -86,7 +86,7 @@ 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 start the multipathd daemon on \fB--disable\fP, and ++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. diff --git a/SOURCES/0079-RHBZ-1070581-add-wwid-option.patch b/SOURCES/0079-RHBZ-1070581-add-wwid-option.patch new file mode 100644 index 0000000..e967a51 --- /dev/null +++ b/SOURCES/0079-RHBZ-1070581-add-wwid-option.patch @@ -0,0 +1,93 @@ +--- + multipath/main.c | 19 ++++++++++++++++--- + multipath/multipath.8 | 5 ++++- + 2 files changed, 20 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -85,7 +85,7 @@ usage (char * progname) + { + fprintf (stderr, VERSION_STRING); + fprintf (stderr, "Usage:\n"); +- fprintf (stderr, " %s [-c|-w|-W] [-d] [-T tm:val] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); ++ fprintf (stderr, " %s [-a|-c|-w|-W] [-d] [-T tm:val] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); + fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); + fprintf (stderr, " %s -F [-v lvl]\n", progname); + fprintf (stderr, " %s -t\n", progname); +@@ -98,6 +98,7 @@ usage (char * progname) + " -ll show multipath topology (maximum info)\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" \ + " -c check if a device should be a path in a multipath device\n" \ + " -T tm:val\n" \ + " check if tm matches the multipathd timestamp. If so val is\n" \ +@@ -292,6 +293,15 @@ configure (void) + } + goto out; + } ++ if (conf->dry_run == 5) { ++ r = remember_wwid(refwwid); ++ if (r == 0) ++ printf("wwid '%s' added\n", refwwid); ++ else ++ printf("failed adding '%s' to wwids file\n", ++ refwwid); ++ goto out; ++ } + condlog(3, "scope limited to %s", refwwid); + if (conf->dry_run == 2) { + if (check_wwids_file(refwwid, 0) == 0){ +@@ -428,7 +438,7 @@ main (int argc, char *argv[]) + int r = 1; + long int timestamp = -1; + int valid = -1; +- while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":adchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { + switch(arg) { + case 'T': + if (optarg[0] == ':') +@@ -464,7 +474,7 @@ main (int argc, char *argv[]) + if (dm_prereq()) + exit(1); + +- while ((arg = getopt(argc, argv, ":dchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":adchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { + switch(arg) { + case 1: printf("optarg : %s\n",optarg); + break; +@@ -537,6 +547,9 @@ main (int argc, char *argv[]) + case 'W': + conf->dry_run = 4; + break; ++ case 'a': ++ conf->dry_run = 5; ++ break; + case ':': + fprintf(stderr, "Missing option argument\n"); + usage(argv[0]); +Index: multipath-tools-130222/multipath/multipath.8 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.8 ++++ multipath-tools-130222/multipath/multipath.8 +@@ -8,7 +8,7 @@ multipath \- Device mapper target autoco + .RB [\| \-b\ \c + .IR bindings_file \|] + .RB [\| \-d \|] +-.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-w | \-W \|] ++.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-a | \-w | \-W \|] + .RB [\| \-p\ \c + .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|] + .RB [\| device \|] +@@ -68,6 +68,9 @@ check if a block device should be a path + .B \-q + allow device tables with queue_if_no_path when multipathd is not running + .TP ++.B \-a ++add the wwid for the specified device to the wwids file ++.TP + .B \-w + remove the wwid for the specified device from the wwids file + .TP diff --git a/SOURCES/0080-RHBZ-1075796-cmdline-wwid.patch b/SOURCES/0080-RHBZ-1075796-cmdline-wwid.patch new file mode 100644 index 0000000..f943aa3 --- /dev/null +++ b/SOURCES/0080-RHBZ-1075796-cmdline-wwid.patch @@ -0,0 +1,157 @@ +--- + libmultipath/wwids.c | 44 ++++++++++++++++++++++++++++++++++++++++++ + libmultipath/wwids.h | 1 + multipath/main.c | 12 ++++++++--- + multipath/multipath.8 | 5 +++- + multipathd/multipathd.service | 1 + 5 files changed, 59 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/libmultipath/wwids.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.c ++++ multipath-tools-130222/libmultipath/wwids.c +@@ -305,3 +305,47 @@ remember_wwid(char *wwid) + condlog(4, "wwid %s already in wwids file", wwid); + return 0; + } ++ ++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; ++} +Index: multipath-tools-130222/libmultipath/wwids.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.h ++++ multipath-tools-130222/libmultipath/wwids.h +@@ -17,5 +17,6 @@ int remember_wwid(char *wwid); + int check_wwids_file(char *wwid, int write_wwid); + int remove_wwid(char *wwid); + int replace_wwids(vector mp); ++int remember_cmdline_wwid(void); + + #endif /* _WWIDS_H */ +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -85,7 +85,7 @@ usage (char * progname) + { + fprintf (stderr, VERSION_STRING); + fprintf (stderr, "Usage:\n"); +- fprintf (stderr, " %s [-a|-c|-w|-W] [-d] [-T tm:val] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); ++ fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-T tm:val] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); + fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); + fprintf (stderr, " %s -F [-v lvl]\n", progname); + fprintf (stderr, " %s -t\n", progname); +@@ -99,6 +99,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" \ + " -T tm:val\n" \ + " check if tm matches the multipathd timestamp. If so val is\n" \ +@@ -438,7 +440,7 @@ main (int argc, char *argv[]) + int r = 1; + long int timestamp = -1; + int valid = -1; +- while ((arg = getopt(argc, argv, ":adchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { + switch(arg) { + case 'T': + if (optarg[0] == ':') +@@ -474,7 +476,7 @@ main (int argc, char *argv[]) + if (dm_prereq()) + exit(1); + +- while ((arg = getopt(argc, argv, ":adchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { + switch(arg) { + case 1: printf("optarg : %s\n",optarg); + break; +@@ -538,6 +540,10 @@ main (int argc, char *argv[]) + goto out; + case 'T': + break; ++ case 'A': ++ if (remember_cmdline_wwid() != 0) ++ exit(1); ++ exit(0); + case 'h': + usage(argv[0]); + exit(0); +Index: multipath-tools-130222/multipathd/multipathd.service +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.service ++++ multipath-tools-130222/multipathd/multipathd.service +@@ -11,6 +11,7 @@ Conflicts=shutdown.target + Type=forking + PIDFile=/var/run/multipathd/multipathd.pid + ExecStartPre=/sbin/modprobe dm-multipath ++ExecStartPre=-/sbin/multipath -A + ExecStart=/sbin/multipathd + ExecReload=/sbin/multipathd reconfigure + #ExecStop=/path/to/scrip delete-me if not necessary +Index: multipath-tools-130222/multipath/multipath.8 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.8 ++++ multipath-tools-130222/multipath/multipath.8 +@@ -8,7 +8,7 @@ multipath \- Device mapper target autoco + .RB [\| \-b\ \c + .IR bindings_file \|] + .RB [\| \-d \|] +-.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-a | \-w | \-W \|] ++.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-a | \-A | \-w | \-W \|] + .RB [\| \-p\ \c + .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|] + .RB [\| device \|] +@@ -71,6 +71,9 @@ allow device tables with queue_if_no_pat + .B \-a + add the wwid for the specified device to the wwids file + .TP ++.B \-A ++add wwids from any kernel command line mpath.wwid parameters to the wwids file ++.TP + .B \-w + remove the wwid for the specified device from the wwids file + .TP diff --git a/SOURCES/0081-RHBZ-1066264-check-prefix-on-rename.patch b/SOURCES/0081-RHBZ-1066264-check-prefix-on-rename.patch new file mode 100644 index 0000000..791f32e --- /dev/null +++ b/SOURCES/0081-RHBZ-1066264-check-prefix-on-rename.patch @@ -0,0 +1,41 @@ +--- + libmultipath/devmapper.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -1151,6 +1151,8 @@ dm_rename_partmaps (char * old, char * n + unsigned long long size; + char dev_t[32]; + int r = 1; ++ int offset; ++ char *delim; + + if (!(dmt = dm_task_create(DM_DEVICE_LIST))) + return 1; +@@ -1171,6 +1173,11 @@ dm_rename_partmaps (char * old, char * n + if (dm_dev_t(old, &dev_t[0], 32)) + goto out; + ++ if (isdigit(new[strlen(new)-1])) ++ delim = "p"; ++ else ++ delim = ""; ++ + do { + if ( + /* +@@ -1198,8 +1205,9 @@ dm_rename_partmaps (char * old, char * n + * then it's a kpartx generated partition. + * Rename it. + */ +- snprintf(buff, PARAMS_SIZE, "%s%s", +- new, names->name + strlen(old)); ++ for (offset = strlen(old); names->name[offset] && !(isdigit(names->name[offset])); offset++); /* do nothing */ ++ snprintf(buff, PARAMS_SIZE, "%s%s%s", ++ new, delim, names->name + offset); + dm_rename(names->name, buff); + condlog(4, "partition map %s renamed", + names->name); diff --git a/SOURCES/0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch b/SOURCES/0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch new file mode 100644 index 0000000..9a1bd34 --- /dev/null +++ b/SOURCES/0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch @@ -0,0 +1,32 @@ +--- + libmultipath/checkers/tur.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +Index: multipath-tools-130222/libmultipath/checkers/tur.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers/tur.c ++++ multipath-tools-130222/libmultipath/checkers/tur.c +@@ -409,7 +409,6 @@ libcheck_check (struct checker * c) + ct->running = 0; + MSG(c, MSG_TUR_TIMEOUT); + tur_status = PATH_DOWN; +- ct->state = PATH_UNCHECKED; + } else { + condlog(3, "%d:%d: tur checker not finished", + TUR_DEVT(ct)); +@@ -426,12 +425,10 @@ libcheck_check (struct checker * c) + pthread_mutex_unlock(&ct->lock); + } else { + if (ct->thread) { +- /* pthread cancel failed. continue in sync mode */ + pthread_mutex_unlock(&ct->lock); +- condlog(3, "%d:%d: tur thread not responding, " +- "using sync mode", TUR_DEVT(ct)); +- return tur_check(c->fd, c->timeout, c->message, +- ct->wwid); ++ condlog(3, "%d:%d: tur thread not responding, ", ++ TUR_DEVT(ct)); ++ return PATH_DOWN; + } + /* Start new TUR checker */ + ct->state = PATH_UNCHECKED; diff --git a/SOURCES/0083-RHBZ-1080055-orphan-paths-on-reload.patch b/SOURCES/0083-RHBZ-1080055-orphan-paths-on-reload.patch new file mode 100644 index 0000000..8eaee74 --- /dev/null +++ b/SOURCES/0083-RHBZ-1080055-orphan-paths-on-reload.patch @@ -0,0 +1,85 @@ +--- + libmultipath/structs_vec.c | 31 +++++++++++++++++++++++++++---- + multipathd/main.c | 4 ++++ + 2 files changed, 31 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -280,12 +280,38 @@ update_multipath_status (struct multipat + return 0; + } + ++void sync_paths(struct multipath *mpp, vector pathvec) ++{ ++ struct path *pp; ++ struct pathgroup *pgp; ++ int found, i, j; ++ ++ vector_foreach_slot (mpp->paths, pp, i) { ++ found = 0; ++ vector_foreach_slot(mpp->pg, pgp, j) { ++ if (find_slot(pgp->paths, (void *)pp) != -1) { ++ found = 1; ++ break; ++ } ++ } ++ if (!found) { ++ condlog(3, "%s dropped path %s", mpp->alias, pp->dev); ++ vector_del_slot(mpp->paths, i--); ++ orphan_path(pp); ++ } ++ } ++ update_mpp_paths(mpp, pathvec); ++ vector_foreach_slot (mpp->paths, pp, i) ++ pp->mpp = mpp; ++} ++ + extern int + update_multipath_strings (struct multipath *mpp, vector pathvec) + { + if (!mpp) + return 1; + ++ update_mpp_paths(mpp, pathvec); + condlog(4, "%s: %s", mpp->alias, __FUNCTION__); + + free_multipath_attributes(mpp); +@@ -294,6 +320,7 @@ update_multipath_strings (struct multipa + + if (update_multipath_table(mpp, pathvec)) + return 1; ++ sync_paths(mpp, pathvec); + + if (update_multipath_status(mpp)) + return 1; +@@ -494,13 +521,9 @@ int update_multipath (struct vectors *ve + return 2; + } + +- free_pgvec(mpp->pg, KEEP_PATHS); +- mpp->pg = NULL; +- + if (__setup_multipath(vecs, mpp, reset)) + return 1; /* mpp freed in setup_multipath */ + +- adopt_paths(vecs->pathvec, mpp, 0); + /* + * compare checkers states with DM states + */ +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1152,6 +1152,10 @@ check_path (struct vectors * vecs, struc + pp->dev); + pp->dmstate = PSTATE_UNDEF; + } ++ /* if update_multipath_strings orphaned the path, quit early */ ++ if (!pp->mpp) ++ return; ++ + pp->chkrstate = newstate; + if (newstate != pp->state) { + int oldstate = pp->state; diff --git a/SOURCES/0084-RHBZ-1110000-multipath-man.patch b/SOURCES/0084-RHBZ-1110000-multipath-man.patch new file mode 100644 index 0000000..4ea422a --- /dev/null +++ b/SOURCES/0084-RHBZ-1110000-multipath-man.patch @@ -0,0 +1,101 @@ +--- + libmultipath/prioritizers/alua.c | 4 ++-- + multipathd/multipathd.8 | 37 +++++++++++++++++++++++++++++++++---- + 2 files changed, 35 insertions(+), 6 deletions(-) + +Index: multipath-tools-130222/multipathd/multipathd.8 +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.8 ++++ multipath-tools-130222/multipathd/multipathd.8 +@@ -42,6 +42,9 @@ format wildcards. + .B list|show maps|multipaths + Show the multipath devices that the multipathd is monitoring. + .TP ++.B list|show daemon ++Show the current state of the multipathd daemon ++.TP + .B list|show maps|multipaths format $format + Show the status of all multipath devices that the multipathd is monitoring, + using a format string with multipath format wildcards. +@@ -83,16 +86,16 @@ Add a path to the list of monitored path + .B remove|del path $path + Stop monitoring a path. $path is as listed in /sys/block (e.g. sda). + .TP +-.B add map $map ++.B add map|multipath $map + Add a multipath device to the list of monitored devices. $map can either be a device-mapper device as listed in /sys/block (e.g. dm-0) or it can be the alias for the multipath device (e.g. mpath1) or the uid of the multipath device (e.g. 36005076303ffc56200000000000010aa). + .TP +-.B remove|del map $map ++.B remove|del map|multipath $map + Stop monitoring a multipath device. + .TP + .B resize map|multipath $map + Resizes map $map to the given size + .TP +-.B switch|switchgroup map $map group $group ++.B switch|switchgroup map|multipath $map group $group + Force a multipath device to switch to a specific path group. $group is the path group index, starting with 1. + .TP + .B reconfigure +@@ -104,6 +107,13 @@ Sets map $map into suspend state. + .B resume map|multipath $map + Resumes map $map from suspend state. + .TP ++.B reset map|multipath $map ++Reassign existing device-mapper table(s) use use the multipath device, instead ++of its path devices. ++.TP ++.B reload map|multipath $map ++Reload a multipath device. ++.TP + .B fail path $path + Sets path $path into failed state. + .TP +@@ -120,10 +130,29 @@ Restore queueing on all multipath device + Disable queuing on multipathed map $map + .TP + .B restorequeueing map|multipath $map +-Restore queuing on multipahted map $map ++Restore queuing on multipathed map $map ++.TP ++.B forcequeueing daemon ++Forces multipathd into queue_without_daemon mode, so that no_path_retry queueing ++will not be disabled when the daemon stops ++.TP ++.B restorequeueing daemon ++Restores configured queue_without_daemon mode ++.TP ++.B map|multipath $map setprstatus ++Enable persistent reservation management on $map ++.TP ++.B map|multipath $map unsetprstatus ++Disable persistent reservation management on $map ++.TP ++.B map|multipath $map getprstatus ++Get the current persistent reservation management status of $map + .TP + .B quit|exit + End interactive session. ++.TP ++.B shutdown ++Stop multipathd. + + .SH "SEE ALSO" + .BR multipath (8) +Index: multipath-tools-130222/libmultipath/prioritizers/alua.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua.c ++++ multipath-tools-130222/libmultipath/prioritizers/alua.c +@@ -119,10 +119,10 @@ int getprio (struct path * pp, char * ar + condlog(0, "%s: couldn't get target port group", pp->dev); + break; + case ALUA_PRIO_GETAAS_FAILED: +- condlog(0, "%s: couln't get asymmetric access state", pp->dev); ++ condlog(0, "%s: couldn't get asymmetric access state", pp->dev); + break; + case ALUA_PRIO_TPGS_FAILED: +- condlog(3, "%s: couln't get supported alua states", pp->dev); ++ condlog(3, "%s: couldn't get supported alua states", pp->dev); + break; + } + } diff --git a/SOURCES/0085-UPBZ-1110006-datacore-config.patch b/SOURCES/0085-UPBZ-1110006-datacore-config.patch new file mode 100644 index 0000000..cedb5e3 --- /dev/null +++ b/SOURCES/0085-UPBZ-1110006-datacore-config.patch @@ -0,0 +1,28 @@ +--- + libmultipath/hwtable.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1108,6 +1108,19 @@ static struct hwentry default_hw[] = { + .prio_name = PRIO_ALUA, + .prio_args = NULL, + }, ++ { ++ .vendor = "DataCore", ++ .product = "Virtual Disk", ++ .features = DEFAULT_FEATURES, ++ .hwhandler = DEFAULT_HWHANDLER, ++ .pgpolicy = GROUP_BY_PRIO, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .rr_weight = RR_WEIGHT_NONE, ++ .no_path_retry = NO_PATH_RETRY_QUEUE, ++ .checker_name = TUR, ++ .prio_name = PRIO_ALUA, ++ .prio_args = NULL, ++ }, + /* + * EOL + */ diff --git a/SOURCES/0086-RHBZ-1110007-orphan-path-on-failed-add.patch b/SOURCES/0086-RHBZ-1110007-orphan-path-on-failed-add.patch new file mode 100644 index 0000000..0d6aa58 --- /dev/null +++ b/SOURCES/0086-RHBZ-1110007-orphan-path-on-failed-add.patch @@ -0,0 +1,17 @@ +--- + multipathd/main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -562,7 +562,7 @@ rescan: + return 0; + } + else +- return 1; ++ goto fail; + + fail_map: + remove_map(mpp, vecs, 1); diff --git a/SOURCES/0087-RHBZ-1110013-config-error-checking.patch b/SOURCES/0087-RHBZ-1110013-config-error-checking.patch new file mode 100644 index 0000000..c774bc5 --- /dev/null +++ b/SOURCES/0087-RHBZ-1110013-config-error-checking.patch @@ -0,0 +1,190 @@ +--- + libmultipath/parser.c | 154 ++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 126 insertions(+), 28 deletions(-) + +Index: multipath-tools-130222/libmultipath/parser.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/parser.c ++++ multipath-tools-130222/libmultipath/parser.c +@@ -395,36 +395,57 @@ set_value(vector strvec) + char *alloc = NULL; + char *tmp; + +- if (!str) ++ if (!str) { ++ condlog(0, "option '%s' missing value", ++ (char *)VECTOR_SLOT(strvec, 0)); + return NULL; +- ++ } + size = strlen(str); +- if (size == 0) ++ if (size == 0) { ++ condlog(0, "option '%s' has empty value", ++ (char *)VECTOR_SLOT(strvec, 0)); + return NULL; +- +- if (*str == '"') { +- for (i = 2; i < VECTOR_SIZE(strvec); i++) { +- str = VECTOR_SLOT(strvec, i); +- len += strlen(str); +- if (!alloc) +- alloc = +- (char *) MALLOC(sizeof (char *) * +- (len + 1)); +- else { +- alloc = +- REALLOC(alloc, sizeof (char *) * (len + 1)); +- tmp = VECTOR_SLOT(strvec, i-1); +- if (alloc && *str != '"' && *tmp != '"') +- strncat(alloc, " ", 1); +- } +- +- if (alloc && i != VECTOR_SIZE(strvec)-1) +- strncat(alloc, str, strlen(str)); +- } +- } else { +- alloc = MALLOC(sizeof (char *) * (size + 1)); ++ } ++ if (*str != '"') { ++ alloc = MALLOC(sizeof (char) * (size + 1)); + if (alloc) + memcpy(alloc, str, size); ++ else ++ condlog(0, "can't allocate memeory for option '%s'", ++ (char *)VECTOR_SLOT(strvec, 0)); ++ return alloc; ++ } ++ /* Even empty quotes counts as a value (An empty string) */ ++ alloc = (char *) MALLOC(sizeof (char)); ++ if (!alloc) { ++ condlog(0, "can't allocate memeory for option '%s'", ++ (char *)VECTOR_SLOT(strvec, 0)); ++ return NULL; ++ } ++ for (i = 2; i < VECTOR_SIZE(strvec); i++) { ++ str = VECTOR_SLOT(strvec, i); ++ if (!str) { ++ free(alloc); ++ condlog(0, "parse error for option '%s'", ++ (char *)VECTOR_SLOT(strvec, 0)); ++ return NULL; ++ } ++ if (*str == '"') ++ break; ++ tmp = alloc; ++ /* The first +1 is for the NULL byte. The rest are for the ++ * spaces between words */ ++ len += strlen(str) + 1; ++ alloc = REALLOC(alloc, sizeof (char) * len); ++ if (!alloc) { ++ FREE(tmp); ++ condlog(0, "can't allocate memeory for option '%s'", ++ (char *)VECTOR_SLOT(strvec, 0)); ++ return NULL; ++ } ++ if (*alloc != '\0') ++ strncat(alloc, " ", 1); ++ strncat(alloc, str, strlen(str)); + } + return alloc; + } +@@ -465,6 +486,74 @@ void free_uniques(vector uniques) + } + + int ++is_sublevel_keyword(char *str) ++{ ++ return (strcmp(str, "defaults") == 0 || strcmp(str, "blacklist") == 0 || ++ strcmp(str, "blacklist_exceptions") == 0 || ++ strcmp(str, "devices") == 0 || strcmp(str, "devices") == 0 || ++ strcmp(str, "device") == 0 || strcmp(str, "multipaths") == 0 || ++ strcmp(str, "multipath") == 0); ++} ++ ++int ++validate_config_strvec(vector strvec) ++{ ++ char *str; ++ int i; ++ ++ str = VECTOR_SLOT(strvec, 0); ++ if (str == NULL) { ++ condlog(0, "can't parse option on line %d of config file", ++ line_nr); ++ return -1; ++ } ++ if (*str == '}') { ++ if (VECTOR_SIZE(strvec) > 1) ++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 1), line_nr); ++ return 0; ++ } ++ if (*str == '{') { ++ condlog(0, "invalid keyword '%s' on line %d of config file", str, line_nr); ++ return -1; ++ } ++ if (is_sublevel_keyword(str)) { ++ str = VECTOR_SLOT(strvec, 1); ++ if (str == NULL) ++ condlog(0, "missing '{' on line %d of config file", line_nr); ++ else if (*str != '{') ++ condlog(0, "expecting '{' on line %d of config file. found '%s'", line_nr, str); ++ else if (VECTOR_SIZE(strvec) > 2) ++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr); ++ return 0; ++ } ++ str = VECTOR_SLOT(strvec, 1); ++ if (str == NULL) { ++ condlog(0, "missing value for option '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 0), line_nr); ++ return -1; ++ } ++ if (*str != '"') { ++ if (VECTOR_SIZE(strvec) > 2) ++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr); ++ return 0; ++ } ++ for (i = 2; i < VECTOR_SIZE(strvec); i++) { ++ str = VECTOR_SLOT(strvec, i); ++ if (str == NULL) { ++ condlog(0, "can't parse value on line %d of config file", line_nr); ++ return -1; ++ } ++ if (*str == '"') { ++ if (VECTOR_SIZE(strvec) > i + 1) ++ condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr); ++ return 0; ++ } ++ } ++ condlog(0, "missing closing quotes on line %d of config file", ++ line_nr); ++ return 0; ++} ++ ++int + process_stream(vector keywords) + { + int i; +@@ -494,11 +583,20 @@ process_stream(vector keywords) + if (!strvec) + continue; + ++ if (validate_config_strvec(strvec) != 0) { ++ free_strvec(strvec); ++ continue; ++ } ++ + str = VECTOR_SLOT(strvec, 0); + +- if (!strcmp(str, EOB) && kw_level > 0) { +- free_strvec(strvec); +- break; ++ if (!strcmp(str, EOB)) { ++ if (kw_level > 0) { ++ free_strvec(strvec); ++ break; ++ } ++ condlog(0, "unmatched '%s' at line %d of config file", ++ EOB, line_nr); + } + + for (i = 0; i < VECTOR_SIZE(keywords); i++) { diff --git a/SOURCES/0088-RHBZ-1069811-configurable-prio-timeout.patch b/SOURCES/0088-RHBZ-1069811-configurable-prio-timeout.patch new file mode 100644 index 0000000..60f374b --- /dev/null +++ b/SOURCES/0088-RHBZ-1069811-configurable-prio-timeout.patch @@ -0,0 +1,178 @@ +--- + libmultipath/prio.c | 7 +++++++ + libmultipath/prio.h | 1 + + libmultipath/prioritizers/alua_rtpg.c | 5 +++-- + libmultipath/prioritizers/emc.c | 2 +- + libmultipath/prioritizers/hds.c | 2 +- + libmultipath/prioritizers/hp_sw.c | 2 +- + libmultipath/prioritizers/ontap.c | 4 ++-- + libmultipath/prioritizers/rdac.c | 2 +- + multipath.conf.annotated | 5 +++-- + multipath/multipath.conf.5 | 4 ++-- + 10 files changed, 22 insertions(+), 12 deletions(-) + +Index: multipath-tools-130222/libmultipath/prio.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prio.c ++++ multipath-tools-130222/libmultipath/prio.c +@@ -10,6 +10,13 @@ + + static LIST_HEAD(prioritizers); + ++unsigned int get_prio_timeout(unsigned int default_timeout) ++{ ++ if (conf->checker_timeout) ++ return conf->checker_timeout * 1000; ++ return default_timeout; ++} ++ + int init_prio (void) + { + if (!add_prio(DEFAULT_PRIO)) +Index: multipath-tools-130222/libmultipath/prio.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prio.h ++++ multipath-tools-130222/libmultipath/prio.h +@@ -51,6 +51,7 @@ struct prio { + int (*getprio)(struct path *, char *); + }; + ++unsigned int get_prio_timeout(unsigned int default_timeout); + int init_prio (void); + void cleanup_prio (void); + struct prio * add_prio (char *); +Index: multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua_rtpg.c ++++ multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c +@@ -21,6 +21,7 @@ + #define __user + #include + ++#include "../prio.h" + #include "alua_rtpg.h" + + #define SENSE_BUFF_LEN 32 +@@ -134,7 +135,7 @@ do_inquiry(int fd, int evpd, unsigned in + hdr.dxfer_len = resplen; + hdr.sbp = sense; + hdr.mx_sb_len = sizeof(sense); +- hdr.timeout = DEF_TIMEOUT; ++ hdr.timeout = get_prio_timeout(DEF_TIMEOUT); + + if (ioctl(fd, SG_IO, &hdr) < 0) { + PRINT_DEBUG("do_inquiry: IOCTL failed!\n"); +@@ -253,7 +254,7 @@ do_rtpg(int fd, void* resp, long resplen + hdr.dxfer_len = resplen; + hdr.mx_sb_len = sizeof(sense); + hdr.sbp = sense; +- hdr.timeout = DEF_TIMEOUT; ++ hdr.timeout = get_prio_timeout(DEF_TIMEOUT); + + if (ioctl(fd, SG_IO, &hdr) < 0) + return -RTPG_RTPG_FAILED; +Index: multipath-tools-130222/libmultipath/prioritizers/emc.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/emc.c ++++ multipath-tools-130222/libmultipath/prioritizers/emc.c +@@ -31,7 +31,7 @@ int emc_clariion_prio(const char *dev, i + io_hdr.dxferp = sense_buffer; + io_hdr.cmdp = inqCmdBlk; + io_hdr.sbp = sb; +- io_hdr.timeout = 60000; ++ io_hdr.timeout = get_prio_timeout(60000); + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_emc_log(0, "sending query command failed"); +Index: multipath-tools-130222/libmultipath/prioritizers/hds.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/hds.c ++++ multipath-tools-130222/libmultipath/prioritizers/hds.c +@@ -114,7 +114,7 @@ int hds_modular_prio (const char *dev, i + io_hdr.dxferp = inqBuff; + io_hdr.cmdp = inqCmdBlk; + io_hdr.sbp = sense_buffer; +- io_hdr.timeout = 2000; /* TimeOut = 2 seconds */ ++ io_hdr.timeout = get_prio_timeout(2000); /* TimeOut = 2 seconds */ + + if (ioctl (fd, SG_IO, &io_hdr) < 0) { + pp_hds_log(0, "SG_IO error"); +Index: multipath-tools-130222/libmultipath/prioritizers/hp_sw.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/hp_sw.c ++++ multipath-tools-130222/libmultipath/prioritizers/hp_sw.c +@@ -46,7 +46,7 @@ int hp_sw_prio(const char *dev, int fd) + io_hdr.dxfer_direction = SG_DXFER_NONE; + io_hdr.cmdp = turCmdBlk; + io_hdr.sbp = sb; +- io_hdr.timeout = 60000; ++ io_hdr.timeout = get_prio_timeout(60000); + io_hdr.pack_id = 0; + retry: + if (ioctl(fd, SG_IO, &io_hdr) < 0) { +Index: multipath-tools-130222/libmultipath/prioritizers/ontap.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/ontap.c ++++ multipath-tools-130222/libmultipath/prioritizers/ontap.c +@@ -89,7 +89,7 @@ static int send_gva(const char *dev, int + io_hdr.dxferp = results; + io_hdr.cmdp = cdb; + io_hdr.sbp = sb; +- io_hdr.timeout = SG_TIMEOUT; ++ io_hdr.timeout = get_prio_timeout(SG_TIMEOUT); + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_ontap_log(0, "SG_IO ioctl failed, errno=%d", errno); +@@ -141,7 +141,7 @@ static int get_proxy(const char *dev, in + io_hdr.dxferp = results; + io_hdr.cmdp = cdb; + io_hdr.sbp = sb; +- io_hdr.timeout = SG_TIMEOUT; ++ io_hdr.timeout = get_prio_timeout(SG_TIMEOUT); + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_ontap_log(0, "ioctl sending inquiry command failed, " +Index: multipath-tools-130222/libmultipath/prioritizers/rdac.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/rdac.c ++++ multipath-tools-130222/libmultipath/prioritizers/rdac.c +@@ -31,7 +31,7 @@ int rdac_prio(const char *dev, int fd) + io_hdr.dxferp = sense_buffer; + io_hdr.cmdp = inqCmdBlk; + io_hdr.sbp = sb; +- io_hdr.timeout = 60000; ++ io_hdr.timeout = get_prio_timeout(60000); + io_hdr.pack_id = 0; + if (ioctl(fd, SG_IO, &io_hdr) < 0) { + pp_rdac_log(0, "sending inquiry command failed"); +Index: multipath-tools-130222/multipath.conf.annotated +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.annotated ++++ multipath-tools-130222/multipath.conf.annotated +@@ -188,8 +188,9 @@ + # # + # # name : checker_timeout + # # scope : multipath & multipathd +-# # desc : The timeout to use for path checkers that issue scsi +-# # commands with an explicit timeout, in seconds. ++# # desc : The timeout to use for path checkers and prioritizers ++# # that issue scsi commands with an explicit timeout, in ++# # seconds. + # # values : n > 0 + # # default : taken from /sys/block/sd/device/timeout + # checker_timeout 60 +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -321,8 +321,8 @@ maximum number of open fds is taken from + if that number is greated than 1024. + .TP + .B checker_timeout +-Specify the timeout to user for path checkers that issue scsi commands with an +-explicit timeout, in seconds; default taken from ++Specify the timeout to use for path checkers and prioritizers that issue scsi ++commands with an explicit timeout, in seconds; default taken from + .I /sys/block/sd/device/timeout + .TP + .B fast_io_fail_tmo diff --git a/SOURCES/0089-RHBZ-1110016-add-noasync-option.patch b/SOURCES/0089-RHBZ-1110016-add-noasync-option.patch new file mode 100644 index 0000000..2651c0e --- /dev/null +++ b/SOURCES/0089-RHBZ-1110016-add-noasync-option.patch @@ -0,0 +1,158 @@ +--- + libmultipath/config.c | 1 + + libmultipath/config.h | 1 + + libmultipath/dict.c | 33 +++++++++++++++++++++++++++++++++ + libmultipath/discovery.c | 8 ++++++-- + multipath.conf.annotated | 10 ++++++++++ + multipath/multipath.conf.5 | 9 +++++++++ + 6 files changed, 60 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -556,6 +556,7 @@ load_config (char * file, struct udev *u + conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER; + conf->detect_prio = DEFAULT_DETECT_PRIO; + conf->hw_strmatch = 0; ++ conf->force_sync = 0; + + /* + * preload default hwtable +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -115,6 +115,7 @@ struct config { + int reassign_maps; + int retain_hwhandler; + int detect_prio; ++ int force_sync; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -712,6 +712,29 @@ def_hw_strmatch_handler(vector strvec) + return 0; + } + ++static int ++def_force_sync_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->force_sync = 0; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ conf->force_sync = 1; ++ else ++ conf->force_sync = 0; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -2822,6 +2845,15 @@ snprint_def_hw_strmatch(char * buff, int + } + + static int ++snprint_def_force_sync(char * buff, int len, void * data) ++{ ++ if (conf->force_sync) ++ return snprintf(buff, len, "yes"); ++ else ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -2889,6 +2921,7 @@ init_keywords(void) + install_keyword("retain_attached_hw_handler", &def_retain_hwhandler_handler, &snprint_def_retain_hwhandler_handler); + install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio); + install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch); ++ install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -952,8 +952,12 @@ get_state (struct path * pp, int daemon) + } + } + checker_clear_message(c); +- if (daemon) +- checker_set_async(c); ++ if (daemon) { ++ if (conf->force_sync == 0) ++ checker_set_async(c); ++ else ++ checker_set_sync(c); ++ } + if (!conf->checker_timeout && + (pp->bus != SYSFS_BUS_SCSI || + sysfs_get_timeout(pp, &(c->timeout)))) +Index: multipath-tools-130222/multipath.conf.annotated +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.annotated ++++ multipath-tools-130222/multipath.conf.annotated +@@ -214,6 +214,8 @@ + # # values : n > 0 + # # default : determined by the OS + # dev_loss_tmo 600 ++# ++# # + # # name : bindings_file + # # scope : multipath + # # desc : The location of the bindings file that is used with +@@ -222,6 +224,14 @@ + # # default : "/var/lib/multipath/bindings" + # bindings_file "/etc/multipath_bindings" + # ++# # ++# # name : force_sync ++# # scope : multipathd ++# # desc : If set to yes, multipath will run all of the checkers in ++# # sync mode, even if the checker has an async mode. ++# # values : yes|no ++# # default : no ++# force_sync yes + #} + # + ## +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -411,6 +411,15 @@ modify an existing config, or create a n + , the user device configs will be regular expression matched against the + built-in configs instead. Default is + .I no ++.TP ++.B force_sync ++If set to ++.I yes ++, multipathd will call the path checkers in sync mode only. This means that ++only one checker will run at a time. This is useful in the case where many ++multipathd checkers running in parallel causes significant CPU pressure. The ++Default is ++.I no + . + .SH "blacklist section" + The diff --git a/SOURCES/0090-UPBZ-1080038-reorder-paths-for-round-robin.patch b/SOURCES/0090-UPBZ-1080038-reorder-paths-for-round-robin.patch new file mode 100644 index 0000000..44f8407 --- /dev/null +++ b/SOURCES/0090-UPBZ-1080038-reorder-paths-for-round-robin.patch @@ -0,0 +1,529 @@ +--- + libmultipath/configure.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++ + libmultipath/configure.h | 2 + libmultipath/discovery.c | 87 +++++++++++++++++ + libmultipath/discovery.h | 2 + libmultipath/structs.c | 84 +++++++++++++++++ + libmultipath/structs.h | 25 ++++- + 6 files changed, 427 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -39,6 +39,219 @@ + #include "uxsock.h" + #include "wwids.h" + ++/* group paths in pg by host adapter ++ */ ++int group_by_host_adapter(struct pathgroup *pgp, vector adapters) ++{ ++ struct adapter_group *agp; ++ struct host_group *hgp; ++ struct path *pp, *pp1; ++ char adapter_name1[SLOT_NAME_SIZE]; ++ char adapter_name2[SLOT_NAME_SIZE]; ++ int i, j; ++ int found_hostgroup = 0; ++ ++ while (VECTOR_SIZE(pgp->paths) > 0) { ++ ++ pp = VECTOR_SLOT(pgp->paths, 0); ++ ++ if (sysfs_get_host_adapter_name(pp, adapter_name1)) ++ goto out; ++ /* create a new host adapter group ++ */ ++ agp = alloc_adaptergroup(); ++ if (!agp) ++ goto out; ++ agp->pgp = pgp; ++ ++ strncpy(agp->adapter_name, adapter_name1, SLOT_NAME_SIZE); ++ store_adaptergroup(adapters, agp); ++ ++ /* create a new host port group ++ */ ++ hgp = alloc_hostgroup(); ++ if (!hgp) ++ goto out; ++ if (store_hostgroup(agp->host_groups, hgp)) ++ goto out; ++ ++ hgp->host_no = pp->sg_id.host_no; ++ agp->num_hosts++; ++ if (store_path(hgp->paths, pp)) ++ goto out; ++ ++ hgp->num_paths++; ++ /* delete path from path group ++ */ ++ vector_del_slot(pgp->paths, 0); ++ ++ /* add all paths belonging to same host adapter ++ */ ++ vector_foreach_slot(pgp->paths, pp1, i) { ++ if (sysfs_get_host_adapter_name(pp1, adapter_name2)) ++ goto out; ++ if (strcmp(adapter_name1, adapter_name2) == 0) { ++ found_hostgroup = 0; ++ vector_foreach_slot(agp->host_groups, hgp, j) { ++ if (hgp->host_no == pp1->sg_id.host_no) { ++ if (store_path(hgp->paths, pp1)) ++ goto out; ++ hgp->num_paths++; ++ found_hostgroup = 1; ++ break; ++ } ++ } ++ if (!found_hostgroup) { ++ /* this path belongs to new host port ++ * within this adapter ++ */ ++ hgp = alloc_hostgroup(); ++ if (!hgp) ++ goto out; ++ ++ if (store_hostgroup(agp->host_groups, hgp)) ++ goto out; ++ ++ agp->num_hosts++; ++ if (store_path(hgp->paths, pp1)) ++ goto out; ++ ++ hgp->host_no = pp1->sg_id.host_no; ++ hgp->num_paths++; ++ } ++ /* delete paths from original path_group ++ * as they are added into adapter group now ++ */ ++ vector_del_slot(pgp->paths, i); ++ i--; ++ } ++ } ++ } ++ return 0; ++ ++out: /* add back paths into pg as re-ordering failed ++ */ ++ vector_foreach_slot(adapters, agp, i) { ++ vector_foreach_slot(agp->host_groups, hgp, j) { ++ while (VECTOR_SIZE(hgp->paths) > 0) { ++ pp = VECTOR_SLOT(hgp->paths, 0); ++ if (store_path(pgp->paths, pp)) ++ condlog(3, "failed to restore " ++ "path %s into path group", ++ pp->dev); ++ vector_del_slot(hgp->paths, 0); ++ } ++ } ++ } ++ free_adaptergroup(adapters); ++ return 1; ++} ++ ++/* re-order paths in pg by alternating adapters and host ports ++ * for optimized selection ++ */ ++int order_paths_in_pg_by_alt_adapters(struct pathgroup *pgp, vector adapters, ++ int total_paths) ++{ ++ int next_adapter_index = 0; ++ struct adapter_group *agp; ++ struct host_group *hgp; ++ struct path *pp; ++ ++ while (total_paths > 0) { ++ agp = VECTOR_SLOT(adapters, next_adapter_index); ++ if (!agp) { ++ condlog(0, "can't get adapter group %d", next_adapter_index); ++ return 1; ++ } ++ ++ hgp = VECTOR_SLOT(agp->host_groups, agp->next_host_index); ++ if (!hgp) { ++ condlog(0, "can't get host group %d of adapter group %d", next_adapter_index, agp->next_host_index); ++ return 1; ++ } ++ ++ if (!hgp->num_paths) { ++ agp->next_host_index++; ++ agp->next_host_index %= agp->num_hosts; ++ next_adapter_index++; ++ next_adapter_index %= VECTOR_SIZE(adapters); ++ continue; ++ } ++ ++ pp = VECTOR_SLOT(hgp->paths, 0); ++ ++ if (store_path(pgp->paths, pp)) ++ return 1; ++ ++ total_paths--; ++ ++ vector_del_slot(hgp->paths, 0); ++ ++ hgp->num_paths--; ++ ++ agp->next_host_index++; ++ agp->next_host_index %= agp->num_hosts; ++ next_adapter_index++; ++ next_adapter_index %= VECTOR_SIZE(adapters); ++ } ++ ++ /* all paths are added into path_group ++ * in crafted child order ++ */ ++ return 0; ++} ++ ++/* round-robin: order paths in path group to alternate ++ * between all host adapters ++ */ ++int rr_optimize_path_order(struct pathgroup *pgp) ++{ ++ vector adapters; ++ struct path *pp; ++ int total_paths; ++ int i; ++ ++ total_paths = VECTOR_SIZE(pgp->paths); ++ vector_foreach_slot(pgp->paths, pp, i) { ++ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP && ++ pp->sg_id.proto_id != SCSI_PROTOCOL_SAS && ++ pp->sg_id.proto_id != SCSI_PROTOCOL_ISCSI && ++ pp->sg_id.proto_id != SCSI_PROTOCOL_SRP) { ++ /* return success as default path order ++ * is maintained in path group ++ */ ++ return 0; ++ } ++ } ++ adapters = vector_alloc(); ++ if (!adapters) ++ return 0; ++ ++ /* group paths in path group by host adapters ++ */ ++ if (group_by_host_adapter(pgp, adapters)) { ++ /* already freed adapters */ ++ condlog(3, "Failed to group paths by adapters"); ++ return 0; ++ } ++ ++ /* re-order paths in pg to alternate between adapters and host ports ++ */ ++ if (order_paths_in_pg_by_alt_adapters(pgp, adapters, total_paths)) { ++ condlog(3, "Failed to re-order paths in pg by adapters " ++ "and host ports"); ++ free_adaptergroup(adapters); ++ /* return failure as original paths are ++ * removed form pgp ++ */ ++ return 1; ++ } ++ ++ free_adaptergroup(adapters); ++ return 0; ++} ++ + extern int + setup_map (struct multipath * mpp, char * params, int params_size) + { +@@ -101,6 +314,22 @@ setup_map (struct multipath * mpp, char + */ + mpp->bestpg = select_path_group(mpp); + ++ /* re-order paths in all path groups in an optimized way ++ * for round-robin path selectors to get maximum throughput. ++ */ ++ if (!strncmp(mpp->selector, "round-robin", 11)) { ++ vector_foreach_slot(mpp->pg, pgp, i) { ++ if (VECTOR_SIZE(pgp->paths) <= 2) ++ continue; ++ if (rr_optimize_path_order(pgp)) { ++ condlog(2, "cannot re-order paths for " ++ "optimization: %s", ++ mpp->alias); ++ return 1; ++ } ++ } ++ } ++ + /* + * transform the mp->pg vector of vectors of paths + * into a mp->params strings to feed the device-mapper +Index: multipath-tools-130222/libmultipath/configure.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.h ++++ multipath-tools-130222/libmultipath/configure.h +@@ -29,4 +29,4 @@ int reinstate_paths (struct multipath *m + int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload); + int get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid); + int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh); +- ++int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name); +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -310,6 +310,93 @@ sysfs_get_tgt_nodename (struct path *pp, + return 1; + } + ++int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name) ++{ ++ int proto_id; ++ ++ if (!pp || !adapter_name) ++ return 1; ++ ++ proto_id = pp->sg_id.proto_id; ++ ++ if (proto_id != SCSI_PROTOCOL_FCP && ++ proto_id != SCSI_PROTOCOL_SAS && ++ proto_id != SCSI_PROTOCOL_ISCSI && ++ proto_id != SCSI_PROTOCOL_SRP) { ++ return 1; ++ } ++ /* iscsi doesn't have adapter info in sysfs ++ * get ip_address for grouping paths ++ */ ++ if (pp->sg_id.proto_id == SCSI_PROTOCOL_ISCSI) ++ return sysfs_get_iscsi_ip_address(pp, adapter_name); ++ ++ /* fetch adapter pci name for other protocols ++ */ ++ return sysfs_get_host_pci_name(pp, adapter_name); ++} ++ ++int sysfs_get_host_pci_name(struct path *pp, char *pci_name) ++{ ++ struct udev_device *hostdev, *parent; ++ char host_name[HOST_NAME_LEN]; ++ const char *driver_name, *value; ++ ++ if (!pp || !pci_name) ++ return 1; ++ ++ sprintf(host_name, "host%d", pp->sg_id.host_no); ++ hostdev = udev_device_new_from_subsystem_sysname(conf->udev, ++ "scsi_host", host_name); ++ if (!hostdev) ++ return 1; ++ ++ parent = udev_device_get_parent(hostdev); ++ while (parent) { ++ driver_name = udev_device_get_driver(parent); ++ if (!driver_name) { ++ parent = udev_device_get_parent(parent); ++ continue; ++ } ++ if (!strcmp(driver_name, "pcieport")) ++ break; ++ parent = udev_device_get_parent(parent); ++ } ++ if (parent) { ++ /* pci_device found ++ */ ++ value = udev_device_get_sysname(parent); ++ ++ strncpy(pci_name, value, SLOT_NAME_SIZE); ++ udev_device_unref(hostdev); ++ return 0; ++ } ++ udev_device_unref(hostdev); ++ return 1; ++} ++ ++int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address) ++{ ++ struct udev_device *hostdev; ++ char host_name[HOST_NAME_LEN]; ++ const char *value; ++ ++ sprintf(host_name, "host%d", pp->sg_id.host_no); ++ hostdev = udev_device_new_from_subsystem_sysname(conf->udev, ++ "iscsi_host", host_name); ++ if (hostdev) { ++ value = udev_device_get_sysattr_value(hostdev, ++ "ipaddress"); ++ if (value) { ++ strncpy(ip_address, value, SLOT_NAME_SIZE); ++ udev_device_unref(hostdev); ++ return 0; ++ } else ++ udev_device_unref(hostdev); ++ } ++ return 1; ++} ++ + static void + sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp) + { +Index: multipath-tools-130222/libmultipath/discovery.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.h ++++ multipath-tools-130222/libmultipath/discovery.h +@@ -38,6 +38,8 @@ int store_pathinfo (vector pathvec, vect + struct path **pp_ptr); + int sysfs_set_scsi_tmo (struct multipath *mpp); + int sysfs_get_timeout(struct path *pp, unsigned int *timeout); ++int sysfs_get_host_pci_name(struct path *pp, char *pci_name); ++int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address); + + /* + * discovery bitmask +Index: multipath-tools-130222/libmultipath/structs.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.c ++++ multipath-tools-130222/libmultipath/structs.c +@@ -18,6 +18,70 @@ + #include "blacklist.h" + #include "prio.h" + ++struct adapter_group * ++alloc_adaptergroup(void) ++{ ++ struct adapter_group *agp; ++ ++ agp = (struct adapter_group *)MALLOC(sizeof(struct adapter_group)); ++ ++ if (!agp) ++ return NULL; ++ ++ agp->host_groups = vector_alloc(); ++ if (!agp->host_groups) { ++ FREE(agp); ++ agp = NULL; ++ } ++ return agp; ++} ++ ++void free_adaptergroup(vector adapters) ++{ ++ int i; ++ struct adapter_group *agp; ++ ++ vector_foreach_slot(adapters, agp, i) { ++ free_hostgroup(agp->host_groups); ++ FREE(agp); ++ } ++ vector_free(adapters); ++} ++ ++void free_hostgroup(vector hostgroups) ++{ ++ int i; ++ struct host_group *hgp; ++ ++ if (!hostgroups) ++ return; ++ ++ vector_foreach_slot(hostgroups, hgp, i) { ++ vector_free(hgp->paths); ++ FREE(hgp); ++ } ++ vector_free(hostgroups); ++} ++ ++struct host_group * ++alloc_hostgroup(void) ++{ ++ struct host_group *hgp; ++ ++ hgp = (struct host_group *)MALLOC(sizeof(struct host_group)); ++ ++ if (!hgp) ++ return NULL; ++ ++ hgp->paths = vector_alloc(); ++ ++ if (!hgp->paths) { ++ FREE(hgp); ++ hgp = NULL; ++ } ++ return hgp; ++} ++ + struct path * + alloc_path (void) + { +@@ -242,6 +306,26 @@ store_pathgroup (vector pgvec, struct pa + return 0; + } + ++int ++store_hostgroup(vector hostgroupvec, struct host_group * hgp) ++{ ++ if (!vector_alloc_slot(hostgroupvec)) ++ return 1; ++ ++ vector_set_slot(hostgroupvec, hgp); ++ return 0; ++} ++ ++int ++store_adaptergroup(vector adapters, struct adapter_group * agp) ++{ ++ if (!vector_alloc_slot(adapters)) ++ return 1; ++ ++ vector_set_slot(adapters, agp); ++ return 0; ++} ++ + struct multipath * + find_mp_by_minor (vector mpvec, int minor) + { +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -15,7 +15,8 @@ + #define BLK_DEV_SIZE 33 + #define PATH_SIZE 512 + #define NAME_SIZE 512 +- ++#define HOST_NAME_LEN 8 ++#define SLOT_NAME_SIZE 40 + + #define SCSI_VENDOR_SIZE 9 + #define SCSI_PRODUCT_SIZE 17 +@@ -251,6 +252,20 @@ struct pathgroup { + char * selector; + }; + ++struct adapter_group { ++ char adapter_name[SLOT_NAME_SIZE]; ++ struct pathgroup *pgp; ++ int num_hosts; ++ vector host_groups; ++ int next_host_index; ++}; ++ ++struct host_group { ++ int host_no; ++ int num_paths; ++ vector paths; ++}; ++ + struct path * alloc_path (void); + struct pathgroup * alloc_pathgroup (void); + struct multipath * alloc_multipath (void); +@@ -263,6 +278,14 @@ void free_multipath_attributes (struct m + void drop_multipath (vector mpvec, char * wwid, enum free_path_mode free_paths); + void free_multipathvec (vector mpvec, enum free_path_mode free_paths); + ++struct adapter_group * alloc_adaptergroup(void); ++struct host_group * alloc_hostgroup(void); ++void free_adaptergroup(vector adapters); ++void free_hostgroup(vector hostgroups); ++ ++int store_adaptergroup(vector adapters, struct adapter_group *agp); ++int store_hostgroup(vector hostgroupvec, struct host_group *hgp); ++ + int store_path (vector pathvec, struct path * pp); + int store_pathgroup (vector pgvec, struct pathgroup * pgp); + diff --git a/SOURCES/0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch b/SOURCES/0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch new file mode 100644 index 0000000..d164de1 --- /dev/null +++ b/SOURCES/0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch @@ -0,0 +1,38 @@ +--- + libmultipath/dict.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -43,6 +43,9 @@ def_fast_io_fail_handler(vector strvec) + char * buff; + + buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ + if (strlen(buff) == 3 && !strcmp(buff, "off")) + conf->fast_io_fail = MP_FAST_IO_FAIL_OFF; + else if (sscanf(buff, "%d", &conf->fast_io_fail) != 1 || +@@ -1002,6 +1005,9 @@ hw_dev_loss_handler(vector strvec) + char * buff; + struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); + ++ if (!hwe) ++ return 1; ++ + buff = set_value(strvec); + if (!buff) + return 1; +@@ -1021,6 +1027,9 @@ hw_pgpolicy_handler(vector strvec) + char * buff; + struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); + ++ if (!hwe) ++ return 1; ++ + buff = set_value(strvec); + + if (!buff) diff --git a/SOURCES/0092-UPBZ-1104605-reload-on-rename.patch b/SOURCES/0092-UPBZ-1104605-reload-on-rename.patch new file mode 100644 index 0000000..465257c --- /dev/null +++ b/SOURCES/0092-UPBZ-1104605-reload-on-rename.patch @@ -0,0 +1,63 @@ +--- + libmultipath/configure.c | 11 +++++++++++ + libmultipath/configure.h | 1 + + libmultipath/devmapper.c | 3 +-- + 3 files changed, 13 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -394,6 +394,8 @@ select_action (struct multipath * mpp, v + cmpp->alias, mpp->alias); + strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE); + mpp->action = ACT_RENAME; ++ if (force_reload) ++ mpp->action = ACT_RENAME2; + return; + } + mpp->action = ACT_CREATE; +@@ -632,6 +634,15 @@ domap (struct multipath * mpp, char * pa + r = dm_rename(mpp->alias_old, mpp->alias); + break; + ++ case ACT_RENAME2: ++ r = dm_rename(mpp->alias_old, mpp->alias); ++ if (r) { ++ r = dm_addmap_reload(mpp, params); ++ if (r) ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, mpp->alias, MPATH_UDEV_RELOAD_FLAG); ++ } ++ break; ++ + default: + break; + } +Index: multipath-tools-130222/libmultipath/configure.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.h ++++ multipath-tools-130222/libmultipath/configure.h +@@ -18,6 +18,7 @@ enum actions { + ACT_RENAME, + ACT_CREATE, + ACT_RESIZE, ++ ACT_RENAME2, + }; + + #define FLUSH_ONE 1 +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -565,10 +565,9 @@ dm_dev_t (const char * mapname, char * d + if (!dm_task_run(dmt)) + goto out; + +- if (!dm_task_get_info(dmt, &info)) ++ if (!dm_task_get_info(dmt, &info) || !info.exists) + goto out; + +- r = info.open_count; + if (snprintf(dev_t, len, "%i:%i", info.major, info.minor) > len) + goto out; + diff --git a/SOURCES/0093-UPBZ-1086825-user-friendly-name-remap.patch b/SOURCES/0093-UPBZ-1086825-user-friendly-name-remap.patch new file mode 100644 index 0000000..ab5abbd --- /dev/null +++ b/SOURCES/0093-UPBZ-1086825-user-friendly-name-remap.patch @@ -0,0 +1,199 @@ +--- + libmultipath/alias.c | 64 ++++++++++++++++++++++++++++++++++++++++++--- + libmultipath/alias.h | 2 + + libmultipath/propsel.c | 32 +++++++++++++++------- + libmultipath/structs_vec.c | 15 ++++++++++ + 4 files changed, 100 insertions(+), 13 deletions(-) + +Index: multipath-tools-130222/libmultipath/alias.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.c ++++ multipath-tools-130222/libmultipath/alias.c +@@ -145,7 +145,7 @@ lookup_binding(FILE *f, char *map_wwid, + } + + static int +-rlookup_binding(FILE *f, char *buff, char *map_alias) ++rlookup_binding(FILE *f, char *buff, char *map_alias, char *prefix) + { + char line[LINE_MAX]; + unsigned int line_nr = 0; +@@ -164,7 +164,7 @@ rlookup_binding(FILE *f, char *buff, cha + alias = strtok(line, " \t"); + if (!alias) /* blank line */ + continue; +- curr_id = scan_devname(alias, NULL); /* TBD: Why this call? */ ++ curr_id = scan_devname(alias, prefix); + if (curr_id >= id) + id = curr_id + 1; + wwid = strtok(NULL, " \t"); +@@ -188,6 +188,11 @@ rlookup_binding(FILE *f, char *buff, cha + } + } + condlog(3, "No matching alias [%s] in bindings file.", map_alias); ++ ++ /* Get the theoretical id for this map alias. ++ * Used by use_existing_alias ++ */ ++ id = scan_devname(map_alias, prefix); + return id; + } + +@@ -237,6 +242,59 @@ allocate_binding(int fd, char *wwid, int + } + + char * ++use_existing_alias (char *wwid, char *file, char *alias_old, ++ char *prefix, int bindings_read_only) ++{ ++ char *alias = NULL; ++ int id = 0; ++ int fd, can_write; ++ char buff[WWID_SIZE]; ++ FILE *f; ++ ++ fd = open_file(file, &can_write, BINDINGS_FILE_HEADER); ++ if (fd < 0) ++ return NULL; ++ ++ f = fdopen(fd, "r"); ++ if (!f) { ++ condlog(0, "cannot fdopen on bindings file descriptor"); ++ close(fd); ++ return NULL; ++ } ++ /* lookup the binding. if it exsists, the wwid will be in buff ++ * either way, id contains the id for the alias ++ */ ++ id = rlookup_binding(f , buff, alias_old, prefix); ++ if (id < 0) ++ goto out; ++ ++ if (strlen(buff) > 0) { ++ /* if buff is our wwid, it's already ++ * allocated correctly ++ */ ++ if (strcmp(buff, wwid) == 0) ++ alias = STRDUP(alias_old); ++ else { ++ alias = NULL; ++ condlog(0, "alias %s already bound to wwid %s, cannot reuse", ++ alias_old, buff); ++ } ++ goto out; ++ } ++ ++ /* allocate the existing alias in the bindings file */ ++ if (can_write && id && !bindings_read_only) { ++ alias = allocate_binding(fd, wwid, id, prefix); ++ condlog(0, "Allocated existing binding [%s] for WWID [%s]", ++ alias, wwid); ++ } ++ ++out: ++ fclose(f); ++ return alias; ++} ++ ++char * + get_user_friendly_alias(char *wwid, char *file, char *prefix, + int bindings_read_only) + { +@@ -305,7 +363,7 @@ get_user_friendly_wwid(char *alias, char + return -1; + } + +- rlookup_binding(f, buff, alias); ++ rlookup_binding(f, buff, alias, NULL); + if (!strlen(buff)) { + fclose(f); + return -1; +Index: multipath-tools-130222/libmultipath/alias.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.h ++++ multipath-tools-130222/libmultipath/alias.h +@@ -10,3 +10,5 @@ + char *get_user_friendly_alias(char *wwid, char *file, char *prefix, + int bindings_readonly); + int get_user_friendly_wwid(char *alias, char *buff, char *file); ++char *use_existing_alias (char *wwid, char *file, char *alias_old, ++ char *prefix, int bindings_read_only); +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -253,19 +253,31 @@ want_user_friendly_names(struct multipat + extern int + select_alias (struct multipath * mp) + { +- if (mp->mpe && mp->mpe->alias) ++ if (mp->mpe && mp->mpe->alias) { + mp->alias = STRDUP(mp->mpe->alias); +- else { +- mp->alias = NULL; +- if (want_user_friendly_names(mp)) { +- select_alias_prefix(mp); +- mp->alias = get_user_friendly_alias(mp->wwid, +- conf->bindings_file, mp->alias_prefix, conf->bindings_read_only); +- } +- if (mp->alias == NULL) +- mp->alias = STRDUP(mp->wwid); ++ goto out; + } + ++ mp->alias = NULL; ++ if (!want_user_friendly_names(mp)) ++ goto out; ++ ++ select_alias_prefix(mp); ++ ++ if (strlen(mp->alias_old) > 0) { ++ mp->alias = use_existing_alias(mp->wwid, conf->bindings_file, ++ mp->alias_old, mp->alias_prefix, ++ conf->bindings_read_only); ++ memset (mp->alias_old, 0, WWID_SIZE); ++ } ++ ++ if (mp->alias == NULL) ++ mp->alias = get_user_friendly_alias(mp->wwid, ++ conf->bindings_file, mp->alias_prefix, conf->bindings_read_only); ++out: ++ if (mp->alias == NULL) ++ mp->alias = STRDUP(mp->wwid); ++ + return mp->alias ? 0 : 1; + } + +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -430,6 +430,20 @@ out: + return NULL; + } + ++static void ++find_existing_alias (struct multipath * mpp, ++ struct vectors *vecs) ++{ ++ struct multipath * mp; ++ int i; ++ ++ vector_foreach_slot (vecs->mpvec, mp, i) ++ if (strcmp(mp->wwid, mpp->wwid) == 0) { ++ strncpy(mpp->alias_old, mp->alias, WWID_SIZE); ++ return; ++ } ++} ++ + extern struct multipath * + add_map_with_path (struct vectors * vecs, + struct path * pp, int add_vec) +@@ -443,6 +457,7 @@ add_map_with_path (struct vectors * vecs + mpp->hwe = pp->hwe; + + strcpy(mpp->wwid, pp->wwid); ++ find_existing_alias(mpp, vecs); + if (select_alias(mpp)) + goto out; + mpp->size = pp->size; diff --git a/SOURCES/0094-RHBZ-1086825-cleanup-remap.patch b/SOURCES/0094-RHBZ-1086825-cleanup-remap.patch new file mode 100644 index 0000000..7d85c2d --- /dev/null +++ b/SOURCES/0094-RHBZ-1086825-cleanup-remap.patch @@ -0,0 +1,107 @@ +--- + libmultipath/alias.c | 31 +++++++++++++++---------------- + libmultipath/propsel.c | 4 ++-- + 2 files changed, 17 insertions(+), 18 deletions(-) + +Index: multipath-tools-130222/libmultipath/alias.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.c ++++ multipath-tools-130222/libmultipath/alias.c +@@ -149,13 +149,11 @@ rlookup_binding(FILE *f, char *buff, cha + { + char line[LINE_MAX]; + unsigned int line_nr = 0; +- int id = 0; + + buff[0] = '\0'; + + while (fgets(line, LINE_MAX, f)) { + char *c, *alias, *wwid; +- int curr_id; + + line_nr++; + c = strpbrk(line, "#\n\r"); +@@ -164,9 +162,6 @@ rlookup_binding(FILE *f, char *buff, cha + alias = strtok(line, " \t"); + if (!alias) /* blank line */ + continue; +- curr_id = scan_devname(alias, prefix); +- if (curr_id >= id) +- id = curr_id + 1; + wwid = strtok(NULL, " \t"); + if (!wwid){ + condlog(3, +@@ -184,16 +179,12 @@ rlookup_binding(FILE *f, char *buff, cha + "\nSetting wwid to %s", alias, wwid); + strncpy(buff, wwid, WWID_SIZE); + buff[WWID_SIZE - 1] = '\0'; +- return id; ++ return 0; + } + } + condlog(3, "No matching alias [%s] in bindings file.", map_alias); + +- /* Get the theoretical id for this map alias. +- * Used by use_existing_alias +- */ +- id = scan_devname(map_alias, prefix); +- return id; ++ return -1; + } + + static char * +@@ -264,9 +255,7 @@ use_existing_alias (char *wwid, char *fi + /* lookup the binding. if it exsists, the wwid will be in buff + * either way, id contains the id for the alias + */ +- id = rlookup_binding(f , buff, alias_old, prefix); +- if (id < 0) +- goto out; ++ rlookup_binding(f, buff, alias_old, prefix); + + if (strlen(buff) > 0) { + /* if buff is our wwid, it's already +@@ -279,11 +268,21 @@ use_existing_alias (char *wwid, char *fi + condlog(0, "alias %s already bound to wwid %s, cannot reuse", + alias_old, buff); + } +- goto out; ++ goto out; + } + + /* allocate the existing alias in the bindings file */ +- if (can_write && id && !bindings_read_only) { ++ id = scan_devname(alias_old, prefix); ++ if (id <= 0) ++ goto out; ++ ++ if (fflush(f) != 0) { ++ condlog(0, "cannot fflush bindings file stream : %s", ++ strerror(errno)); ++ goto out; ++ } ++ ++ if (can_write && !bindings_read_only) { + alias = allocate_binding(fd, wwid, id, prefix); + condlog(0, "Allocated existing binding [%s] for WWID [%s]", + alias, wwid); +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -263,13 +263,13 @@ select_alias (struct multipath * mp) + goto out; + + select_alias_prefix(mp); +- ++ + if (strlen(mp->alias_old) > 0) { + mp->alias = use_existing_alias(mp->wwid, conf->bindings_file, + mp->alias_old, mp->alias_prefix, + conf->bindings_read_only); + memset (mp->alias_old, 0, WWID_SIZE); +- } ++ } + + if (mp->alias == NULL) + mp->alias = get_user_friendly_alias(mp->wwid, diff --git a/SOURCES/0095-RHBZ-1127944-xtremIO-config.patch b/SOURCES/0095-RHBZ-1127944-xtremIO-config.patch new file mode 100644 index 0000000..6807cbc --- /dev/null +++ b/SOURCES/0095-RHBZ-1127944-xtremIO-config.patch @@ -0,0 +1,28 @@ +--- + libmultipath/hwtable.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -1121,6 +1121,19 @@ static struct hwentry default_hw[] = { + .prio_name = PRIO_ALUA, + .prio_args = NULL, + }, ++ { ++ .vendor = "XtremIO", ++ .product = "XtremApp", ++ .features = DEFAULT_FEATURES, ++ .hwhandler = DEFAULT_HWHANDLER, ++ .selector = "queue-length 0", ++ .pgpolicy = MULTIBUS, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .checker_name = DIRECTIO, ++ .fast_io_fail = 15, ++ .prio_name = DEFAULT_PRIO, ++ .prio_args = NULL, ++ }, + /* + * EOL + */ diff --git a/SOURCES/0096-RHBZ-979474-new-wildcards.patch b/SOURCES/0096-RHBZ-979474-new-wildcards.patch new file mode 100644 index 0000000..9025efe --- /dev/null +++ b/SOURCES/0096-RHBZ-979474-new-wildcards.patch @@ -0,0 +1,120 @@ +--- + libmultipath/print.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 83 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "checkers.h" + #include "vector.h" +@@ -44,7 +45,7 @@ + * information printing helpers + */ + static int +-snprint_str (char * buff, size_t len, char * str) ++snprint_str (char * buff, size_t len, const char * str) + { + return snprintf(buff, len, "%s", str); + } +@@ -432,6 +433,83 @@ snprint_path_mpp (char * buff, size_t le + } + + static int ++snprint_host_attr (char * buff, size_t len, struct path * pp, char *attr) ++{ ++ struct udev_device *host_dev = NULL; ++ char host_id[32]; ++ const char *value = NULL; ++ int ret; ++ ++ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) ++ return snprintf(buff, len, "[undef]"); ++ sprintf(host_id, "host%d", pp->sg_id.host_no); ++ host_dev = udev_device_new_from_subsystem_sysname(conf->udev, "fc_host", ++ host_id); ++ if (!host_dev) { ++ condlog(1, "%s: No fc_host device for '%s'", pp->dev, host_id); ++ goto out; ++ } ++ value = udev_device_get_sysattr_value(host_dev, attr); ++ if (value) ++ ret = snprint_str(buff, len, value); ++ udev_device_unref(host_dev); ++out: ++ if (!value) ++ ret = snprintf(buff, len, "[unknown]"); ++ return ret; ++} ++ ++static int ++snprint_host_wwnn (char * buff, size_t len, struct path * pp) ++{ ++ return snprint_host_attr(buff, len, pp, "node_name"); ++} ++ ++static int ++snprint_host_wwpn (char * buff, size_t len, struct path * pp) ++{ ++ return snprint_host_attr(buff, len, pp, "port_name"); ++} ++ ++static int ++snprint_tgt_wwpn (char * buff, size_t len, struct path * pp) ++{ ++ struct udev_device *rport_dev = NULL; ++ char rport_id[32]; ++ const char *value = NULL; ++ int ret; ++ ++ if (pp->sg_id.proto_id != SCSI_PROTOCOL_FCP) ++ return snprintf(buff, len, "[undef]"); ++ sprintf(rport_id, "rport-%d:%d-%d", ++ pp->sg_id.host_no, pp->sg_id.channel, pp->sg_id.transport_id); ++ rport_dev = udev_device_new_from_subsystem_sysname(conf->udev, ++ "fc_remote_ports", rport_id); ++ if (!rport_dev) { ++ condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev, ++ rport_id); ++ goto out; ++ } ++ value = udev_device_get_sysattr_value(rport_dev, "port_name"); ++ if (value) ++ ret = snprint_str(buff, len, value); ++ udev_device_unref(rport_dev); ++out: ++ if (!value) ++ ret = snprintf(buff, len, "[unknown]"); ++ return ret; ++} ++ ++ ++static int ++snprint_tgt_wwnn (char * buff, size_t len, struct path * pp) ++{ ++ if (pp->tgt_node_name[0] == '\0') ++ return snprintf(buff, len, "[undef]"); ++ return snprint_str(buff, len, pp->tgt_node_name); ++} ++ ++static int + snprint_path_checker (char * buff, size_t len, struct path * pp) + { + struct checker * c = &pp->checker; +@@ -475,6 +553,10 @@ struct path_data pd[] = { + {'S', "size", 0, snprint_path_size}, + {'z', "serial", 0, snprint_path_serial}, + {'m', "multipath", 0, snprint_path_mpp}, ++ {'N', "host WWNN", 0, snprint_host_wwnn}, ++ {'n', "target WWNN", 0, snprint_tgt_wwnn}, ++ {'R', "host WWPN", 0, snprint_host_wwpn}, ++ {'r', "target WWPN", 0, snprint_tgt_wwpn}, + {0, NULL, 0 , NULL} + }; + diff --git a/SOURCES/0097-RH-fix-coverity-errors.patch b/SOURCES/0097-RH-fix-coverity-errors.patch new file mode 100644 index 0000000..8ce0e87 --- /dev/null +++ b/SOURCES/0097-RH-fix-coverity-errors.patch @@ -0,0 +1,158 @@ +--- + kpartx/devmapper.c | 3 ++- + libmultipath/alias.c | 1 + + libmultipath/blacklist.c | 7 +++++++ + libmultipath/prioritizers/iet.c | 2 ++ + libmultipath/prioritizers/weightedpath.c | 5 ++++- + libmultipath/regex.c | 5 ++++- + libmultipath/sysfs.c | 3 ++- + libmultipath/util.c | 2 +- + 8 files changed, 23 insertions(+), 5 deletions(-) + +Index: multipath-tools-130222/kpartx/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/devmapper.c ++++ multipath-tools-130222/kpartx/devmapper.c +@@ -132,8 +132,9 @@ dm_addmap (int task, const char *name, c + goto addout; + r = dm_task_run (dmt); + +- addout: ++addout: + dm_task_destroy (dmt); ++ free(prefixed_uuid); + + return r; + } +Index: multipath-tools-130222/libmultipath/alias.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/alias.c ++++ multipath-tools-130222/libmultipath/alias.c +@@ -328,6 +328,7 @@ get_user_friendly_alias(char *wwid, char + if (fflush(f) != 0) { + condlog(0, "cannot fflush bindings file stream : %s", + strerror(errno)); ++ free(alias); + fclose(f); + return NULL; + } +Index: multipath-tools-130222/libmultipath/blacklist.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/blacklist.c ++++ multipath-tools-130222/libmultipath/blacklist.c +@@ -79,6 +79,8 @@ set_ble_device (vector blist, char * ven + if (regcomp(&ble->vendor_reg, vendor, + REG_EXTENDED|REG_NOSUB)) { + FREE(vendor); ++ if (product) ++ FREE(product); + return 1; + } + ble->vendor = vendor; +@@ -87,6 +89,10 @@ set_ble_device (vector blist, char * ven + if (regcomp(&ble->product_reg, product, + REG_EXTENDED|REG_NOSUB)) { + FREE(product); ++ if (vendor) { ++ ble->vendor = NULL; ++ FREE(vendor); ++ } + return 1; + } + ble->product = product; +@@ -189,6 +195,7 @@ setup_default_blist (struct config * con + STRDUP(hwe->bl_product), + ORIGIN_DEFAULT)) { + FREE(ble); ++ vector_del_slot(conf->blist_device, VECTOR_SIZE(conf->blist_device) - 1); + return 1; + } + } +Index: multipath-tools-130222/libmultipath/prioritizers/iet.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/iet.c ++++ multipath-tools-130222/libmultipath/prioritizers/iet.c +@@ -109,6 +109,7 @@ int iet_prio(const char *dev, char * arg + ssize_t nchars = readlink(path, buffer, sizeof(buffer)-1); + if (nchars != -1) { + char *device; ++ buffer[nchars] = '\0'; + device = find_regex(buffer,"(sd[a-z]+)"); + // if device parsed is the right one + if (device!=NULL && strncmp(device, dev, strlen(device)) == 0) { +@@ -118,6 +119,7 @@ int iet_prio(const char *dev, char * arg + if (ip!=NULL && strncmp(ip, preferredip, strlen(ip)) == 0) { + // high prio + free(ip); ++ free(device); + closedir(dir_p); + return 20; + } +Index: multipath-tools-130222/libmultipath/prioritizers/weightedpath.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/weightedpath.c ++++ multipath-tools-130222/libmultipath/prioritizers/weightedpath.c +@@ -61,8 +61,10 @@ int prio_path_weight(struct path *pp, ch + regex = get_next_string(&temp, split_char); + + /* Return default priority if the argument is not parseable */ +- if (!regex) ++ if (!regex) { ++ FREE(arg); + return priority; ++ } + + if (!strcmp(regex, HBTL)) { + sprintf(path, "%d:%d:%d:%d", pp->sg_id.host_no, +@@ -72,6 +74,7 @@ int prio_path_weight(struct path *pp, ch + } else { + condlog(0, "%s: %s - Invalid arguments", pp->dev, + pp->prio.name); ++ FREE(arg); + return priority; + } + +Index: multipath-tools-130222/libmultipath/regex.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/regex.c ++++ multipath-tools-130222/libmultipath/regex.c +@@ -3936,8 +3936,11 @@ int eflags; + regs.num_regs = nmatch; + regs.start = TALLOC(nmatch, regoff_t); + regs.end = TALLOC(nmatch, regoff_t); +- if (regs.start == NULL || regs.end == NULL) ++ if (regs.start == NULL || regs.end == NULL) { ++ free(regs.start); ++ free(regs.end); + return (int) REG_NOMATCH; ++ } + } + + /* Perform the searching operation. */ +Index: multipath-tools-130222/libmultipath/sysfs.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/sysfs.c ++++ multipath-tools-130222/libmultipath/sysfs.c +@@ -88,7 +88,8 @@ ssize_t sysfs_attr_get_value(struct udev + } else if (size == value_len) { + condlog(4, "overflow while reading from %s", devpath); + size = 0; +- } ++ } else ++ value[size] = '\0'; + + close(fd); + return size; +Index: multipath-tools-130222/libmultipath/util.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/util.c ++++ multipath-tools-130222/libmultipath/util.c +@@ -175,7 +175,7 @@ devt2devname (char *devname, int devname + sprintf(block_path,"/sys/dev/block/%u:%u", major, minor); + if (lstat(block_path, &statbuf) == 0) { + if (S_ISLNK(statbuf.st_mode) && +- readlink(block_path, dev, FILE_NAME_SIZE) > 0) { ++ readlink(block_path, dev, FILE_NAME_SIZE-1) > 0) { + char *p = strrchr(dev, '/'); + + if (!p) { diff --git a/SOURCES/0098-UPBZ-1067171-mutipath-i.patch b/SOURCES/0098-UPBZ-1067171-mutipath-i.patch new file mode 100644 index 0000000..cf41863 --- /dev/null +++ b/SOURCES/0098-UPBZ-1067171-mutipath-i.patch @@ -0,0 +1,332 @@ +--- + libmultipath/config.h | 15 ++++++++- + libmultipath/configure.c | 2 - + libmultipath/discovery.c | 5 +-- + multipath/main.c | 75 +++++++++++++++++++++++++---------------------- + multipath/multipath.8 | 5 ++- + 5 files changed, 61 insertions(+), 41 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -23,6 +23,17 @@ enum devtypes { + DEV_DEVMAP + }; + ++enum mpath_cmds { ++ CMD_CREATE, ++ CMD_DRY_RUN, ++ CMD_LIST_SHORT, ++ CMD_LIST_LONG, ++ CMD_VALID_PATH, ++ CMD_REMOVE_WWID, ++ CMD_RESET_WWIDS, ++ CMD_ADD_WWID, ++}; ++ + struct hwentry { + char * vendor; + char * product; +@@ -79,8 +90,7 @@ struct mpentry { + + struct config { + int verbosity; +- int dry_run; +- int list; ++ enum mpath_cmds cmd; + int pgpolicy_flag; + int pgpolicy; + enum devtypes dev_type; +@@ -98,6 +108,7 @@ struct config { + int max_fds; + int force_reload; + int queue_without_daemon; ++ int ignore_wwids; + int checker_timeout; + int daemon; + int flush_on_last_del; +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -85,7 +85,7 @@ usage (char * progname) + { + fprintf (stderr, VERSION_STRING); + fprintf (stderr, "Usage:\n"); +- fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-T tm:val] [-r] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); ++ fprintf (stderr, " %s [-a|-A|-c|-w|-W] [-d] [-T tm:val] [-r] [-i] [-v lvl] [-p pol] [-b fil] [-q] [dev]\n", progname); + fprintf (stderr, " %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname); + fprintf (stderr, " %s -F [-v lvl]\n", progname); + fprintf (stderr, " %s -t\n", progname); +@@ -109,6 +109,7 @@ usage (char * progname) + " -d dry run, do not create or update devmaps\n" \ + " -t dump internal hardware table\n" \ + " -r force devmap reload\n" \ ++ " -i ignore wwids file\n" \ + " -B treat the bindings file as read only\n" \ + " -p policy failover|multibus|group_by_serial|group_by_prio\n" \ + " -b fil bindings file location\n" \ +@@ -209,18 +210,19 @@ get_dm_mpvec (vector curmp, vector pathv + * If not in "fast list mode", we need to fetch information + * about them + */ +- if (conf->list != 1) ++ if (conf->cmd != CMD_LIST_SHORT) + update_paths(mpp); + +- if (conf->list > 1) ++ if (conf->cmd == CMD_LIST_LONG) + mpp->bestpg = select_path_group(mpp); + + disassemble_status(status, mpp); + +- if (conf->list) ++ if (conf->cmd == CMD_LIST_SHORT || ++ conf->cmd == CMD_LIST_LONG) + print_multipath_topology(mpp, conf->verbosity); + +- if (!conf->dry_run) ++ if (conf->cmd == CMD_CREATE) + reinstate_paths(mpp); + } + return 0; +@@ -262,10 +264,11 @@ configure (void) + /* + * if we have a blacklisted device parameter, exit early + */ +- if (dev && conf->dev_type == DEV_DEVNODE && conf->dry_run != 3 && ++ if (dev && conf->dev_type == DEV_DEVNODE && ++ conf->cmd != CMD_REMOVE_WWID && + (filter_devnode(conf->blist_devnode, + conf->elist_devnode, dev) > 0)) { +- if (conf->dry_run == 2) ++ if (conf->cmd == CMD_VALID_PATH) + printf("%s is not a valid multipath device path\n", + conf->dev); + goto out; +@@ -278,13 +281,13 @@ configure (void) + int failed = get_refwwid(conf->dev, conf->dev_type, pathvec, + &refwwid); + if (!refwwid) { +- if (failed == 2 && conf->dry_run == 2) ++ if (failed == 2 && conf->cmd == CMD_VALID_PATH) + printf("%s is not a valid multipath device path\n", conf->dev); + else + condlog(3, "scope is nul"); + goto out; + } +- if (conf->dry_run == 3) { ++ if (conf->cmd == CMD_REMOVE_WWID) { + r = remove_wwid(refwwid); + if (r == 0) + printf("wwid '%s' removed\n", refwwid); +@@ -295,7 +298,7 @@ configure (void) + } + goto out; + } +- if (conf->dry_run == 5) { ++ if (conf->cmd == CMD_ADD_WWID) { + r = remember_wwid(refwwid); + if (r == 0) + printf("wwid '%s' added\n", refwwid); +@@ -305,13 +308,13 @@ configure (void) + goto out; + } + condlog(3, "scope limited to %s", refwwid); +- if (conf->dry_run == 2) { +- if (check_wwids_file(refwwid, 0) == 0){ +- printf("%s is a valid multipath device path\n", conf->dev); ++ if (conf->cmd == CMD_VALID_PATH) { ++ if (conf->ignore_wwids || ++ check_wwids_file(refwwid, 0) == 0) + r = 0; +- } +- else +- printf("%s is not a valid multipath device path\n", conf->dev); ++ ++ printf("%s %s a valid multipath device path\n", ++ conf->dev, r == 0 ? "is" : "is not"); + goto out; + } + } +@@ -319,13 +322,13 @@ configure (void) + /* + * get a path list + */ +- if (conf->dev && !conf->list) ++ if (conf->dev) + di_flag = DI_WWID; + +- if (conf->list > 1) ++ if (conf->cmd == CMD_LIST_LONG) + /* extended path info '-ll' */ + di_flag |= DI_SYSFS | DI_CHECKER; +- else if (conf->list) ++ else if (conf->cmd == CMD_LIST_SHORT) + /* minimum path info '-l' */ + di_flag |= DI_SYSFS; + else +@@ -345,7 +348,7 @@ configure (void) + + filter_pathvec(pathvec, refwwid); + +- if (conf->list) { ++ if (conf->cmd != CMD_CREATE && conf->cmd != CMD_DRY_RUN) { + r = 0; + goto out; + } +@@ -440,7 +443,7 @@ main (int argc, char *argv[]) + int r = 1; + long int timestamp = -1; + int valid = -1; +- while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BritT:qwW")) != EOF ) { + switch(arg) { + case 'T': + if (optarg[0] == ':') +@@ -476,7 +479,7 @@ main (int argc, char *argv[]) + if (dm_prereq()) + exit(1); + +- while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BrtT:qwW")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":aAdchl::FfM:v:p:b:BritT:qwW")) != EOF ) { + switch(arg) { + case 1: printf("optarg : %s\n",optarg); + break; +@@ -499,11 +502,11 @@ main (int argc, char *argv[]) + conf->allow_queueing = 1; + break; + case 'c': +- conf->dry_run = 2; ++ conf->cmd = CMD_VALID_PATH; + break; + case 'd': +- if (!conf->dry_run) +- conf->dry_run = 1; ++ if (conf->cmd == CMD_CREATE) ++ conf->cmd = CMD_DRY_RUN; + break; + case 'f': + conf->remove = FLUSH_ONE; +@@ -512,11 +515,10 @@ main (int argc, char *argv[]) + conf->remove = FLUSH_ALL; + break; + case 'l': +- conf->list = 1; +- conf->dry_run = 1; +- + if (optarg && !strncmp(optarg, "l", 1)) +- conf->list++; ++ conf->cmd = CMD_LIST_LONG; ++ else ++ conf->cmd = CMD_LIST_SHORT; + + break; + case 'M': +@@ -535,6 +537,9 @@ main (int argc, char *argv[]) + case 'r': + conf->force_reload = 1; + break; ++ case 'i': ++ conf->ignore_wwids = 1; ++ break; + case 't': + r = dump_config(); + goto out; +@@ -548,13 +553,13 @@ main (int argc, char *argv[]) + usage(argv[0]); + exit(0); + case 'w': +- conf->dry_run = 3; ++ conf->cmd = CMD_REMOVE_WWID; + break; + case 'W': +- conf->dry_run = 4; ++ conf->cmd = CMD_RESET_WWIDS; + break; + case 'a': +- conf->dry_run = 5; ++ conf->cmd = CMD_ADD_WWID; + break; + case ':': + fprintf(stderr, "Missing option argument\n"); +@@ -600,16 +605,16 @@ main (int argc, char *argv[]) + } + dm_init(); + +- if (conf->dry_run == 2 && ++ if (conf->cmd == CMD_VALID_PATH && + (!conf->dev || conf->dev_type == DEV_DEVMAP)) { + condlog(0, "the -c option requires a path to check"); + goto out; + } +- if (conf->dry_run == 3 && !conf->dev) { ++ if (conf->cmd == CMD_REMOVE_WWID && !conf->dev) { + condlog(0, "the -w option requires a device"); + goto out; + } +- if (conf->dry_run == 4) { ++ if (conf->cmd == CMD_RESET_WWIDS) { + struct multipath * mpp; + int i; + vector curmp; +Index: multipath-tools-130222/multipath/multipath.8 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.8 ++++ multipath-tools-130222/multipath/multipath.8 +@@ -8,7 +8,7 @@ multipath \- Device mapper target autoco + .RB [\| \-b\ \c + .IR bindings_file \|] + .RB [\| \-d \|] +-.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-a | \-A | \-w | \-W \|] ++.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F | \-B | \-c | \-q | \|-r | \-r | \-a | \-A | \-w | \-W \|] + .RB [\| \-p\ \c + .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|] + .RB [\| device \|] +@@ -55,6 +55,9 @@ print internal hardware table to stdout + .B \-r + force devmap reload + .TP ++.B \-i ++ignore wwids file when processing devices ++.TP + .B \-B + treat the bindings file as read only + .TP +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -580,7 +580,7 @@ domap (struct multipath * mpp, char * pa + /* + * last chance to quit before touching the devmaps + */ +- if (conf->dry_run && mpp->action != ACT_NOTHING) { ++ if (conf->cmd == CMD_DRY_RUN && mpp->action != ACT_NOTHING) { + print_multipath_topology(mpp, conf->verbosity); + return DOMAP_DRY; + } +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -54,7 +54,8 @@ store_pathinfo (vector pathvec, vector h + } + pp->udev = udev_device_ref(udevice); + err = pathinfo(pp, hwtable, +- (conf->dry_run == 3)? flag : (flag | DI_BLACKLIST)); ++ (conf->cmd == CMD_REMOVE_WWID)? flag : ++ (flag | DI_BLACKLIST)); + if (err) + goto out; + +@@ -1101,7 +1102,7 @@ get_uid (struct path * pp) + + memset(pp->wwid, 0, WWID_SIZE); + value = udev_device_get_property_value(pp->udev, pp->uid_attribute); +- if ((!value || strlen(value) == 0) && conf->dry_run == 2) ++ if ((!value || strlen(value) == 0) && conf->cmd == CMD_VALID_PATH) + value = getenv(pp->uid_attribute); + if (value && strlen(value)) { + size_t len = WWID_SIZE; diff --git a/SOURCES/0099-RH-add-all-devs.patch b/SOURCES/0099-RH-add-all-devs.patch new file mode 100644 index 0000000..aca6d4c --- /dev/null +++ b/SOURCES/0099-RH-add-all-devs.patch @@ -0,0 +1,170 @@ +--- + libmultipath/config.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++- + libmultipath/config.h | 1 + libmultipath/dict.c | 38 +++++++++++++++++++++++++++++ + 3 files changed, 102 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -113,6 +113,8 @@ find_hwe (vector hwtable, char * vendor, + * continuing to the generic entries + */ + vector_foreach_slot_backwards (hwtable, tmp, i) { ++ if (tmp->all_devs == 1) ++ continue; + if (hwe_regmatch(tmp, &hwe)) + continue; + ret = tmp; +@@ -348,6 +350,62 @@ merge_hwe (struct hwentry * dst, struct + return 0; + } + ++#define overwrite_str(s) \ ++do { \ ++ if (src->s) { \ ++ if (dst->s) \ ++ FREE(dst->s); \ ++ if (!(dst->s = set_param_str(src->s))) \ ++ return 1; \ ++ } \ ++} while(0) ++ ++#define overwrite_num(s) \ ++do { \ ++ if (src->s) \ ++ dst->s = src->s; \ ++} while(0) ++ ++static int ++overwrite_hwe (struct hwentry * dst, struct hwentry * src) ++{ ++ overwrite_str(vendor); ++ overwrite_str(product); ++ overwrite_str(revision); ++ overwrite_str(uid_attribute); ++ overwrite_str(features); ++ overwrite_str(hwhandler); ++ overwrite_str(selector); ++ overwrite_str(checker_name); ++ overwrite_str(prio_name); ++ overwrite_str(prio_args); ++ overwrite_str(alias_prefix); ++ overwrite_str(bl_product); ++ overwrite_num(pgpolicy); ++ overwrite_num(pgfailback); ++ overwrite_num(rr_weight); ++ overwrite_num(no_path_retry); ++ overwrite_num(minio); ++ overwrite_num(minio_rq); ++ overwrite_num(pg_timeout); ++ overwrite_num(flush_on_last_del); ++ overwrite_num(fast_io_fail); ++ overwrite_num(dev_loss); ++ overwrite_num(user_friendly_names); ++ overwrite_num(retain_hwhandler); ++ overwrite_num(detect_prio); ++ ++ /* ++ * Make sure features is consistent with ++ * no_path_retry ++ */ ++ if (dst->no_path_retry == NO_PATH_RETRY_FAIL) ++ remove_feature(&dst->features, "queue_if_no_path"); ++ else if (dst->no_path_retry != NO_PATH_RETRY_UNDEF) ++ add_feature(&dst->features, "queue_if_no_path"); ++ return 0; ++} ++ + int + store_hwe (vector hwtable, struct hwentry * dhwe) + { +@@ -431,7 +489,11 @@ restart: + break; + j = n; + vector_foreach_slot_after(hw, hwe2, j) { +- if (conf->hw_strmatch) { ++ if (hwe2->all_devs == 1) { ++ overwrite_hwe(hwe1, hwe2); ++ continue; ++ } ++ else if (conf->hw_strmatch) { + if (hwe_strmatch(hwe2, hwe1)) + continue; + } +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -47,6 +47,7 @@ struct hwentry { + char * prio_args; + char * alias_prefix; + ++ int all_devs; + int pgpolicy; + int pgfailback; + int rr_weight; +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -918,6 +918,32 @@ device_handler(vector strvec) + } + + static int ++all_devs_handler(vector strvec) ++{ ++ char * buff; ++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); ++ ++ if (!hwe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ hwe->all_devs = 0; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ hwe->all_devs = 1; ++ else ++ hwe->all_devs = 0; ++ ++ FREE(buff); ++ return 0; ++} ++ ++static int + vendor_handler(vector strvec) + { + struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); +@@ -2182,6 +2208,17 @@ snprint_hw_dev_loss(char * buff, int len + } + + static int ++snprint_hw_all_devs (char *buff, int len, void *data) ++{ ++ struct hwentry * hwe = (struct hwentry *)data; ++ ++ if (!hwe->all_devs) ++ return 0; ++ ++ return snprintf(buff, len, "yes"); ++} ++ ++static int + snprint_hw_vendor (char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -2968,6 +3005,7 @@ init_keywords(void) + install_keyword_root("devices", &devices_handler); + install_keyword_multi("device", &device_handler, NULL); + install_sublevel(); ++ install_keyword("all_devs", &all_devs_handler, &snprint_hw_all_devs); + install_keyword("vendor", &vendor_handler, &snprint_hw_vendor); + install_keyword("product", &product_handler, &snprint_hw_product); + install_keyword("revision", &revision_handler, &snprint_hw_revision); diff --git a/SOURCES/0100-RHBZ-1067171-multipath-i-update.patch b/SOURCES/0100-RHBZ-1067171-multipath-i-update.patch new file mode 100644 index 0000000..9a67e7a --- /dev/null +++ b/SOURCES/0100-RHBZ-1067171-multipath-i-update.patch @@ -0,0 +1,54 @@ +--- + multipath/main.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -198,6 +198,9 @@ get_dm_mpvec (vector curmp, vector pathv + continue; + } + ++ if (conf->cmd == CMD_VALID_PATH) ++ continue; ++ + dm_get_map(mpp->alias, &mpp->size, params); + condlog(3, "params = %s", params); + dm_get_status(mpp->alias, status); +@@ -308,7 +311,13 @@ configure (void) + goto out; + } + condlog(3, "scope limited to %s", refwwid); +- if (conf->cmd == CMD_VALID_PATH) { ++ /* 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 */ ++ if (conf->cmd == CMD_VALID_PATH && ++ (!conf->find_multipaths || !conf->ignore_wwids)) { + if (conf->ignore_wwids || + check_wwids_file(refwwid, 0) == 0) + r = 0; +@@ -348,6 +357,20 @@ configure (void) + + filter_pathvec(pathvec, refwwid); + ++ ++ if (conf->cmd == CMD_VALID_PATH) { ++ /* This only happens if find_multipaths is and ++ * ignore_wwids is set. ++ * 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 || VECTOR_SIZE(pathvec) > 1) ++ r = 0; ++ printf("%s %s a valid multipath device path\n", ++ conf->dev, r == 0 ? "is" : "is not"); ++ goto out; ++ } ++ + if (conf->cmd != CMD_CREATE && conf->cmd != CMD_DRY_RUN) { + r = 0; + goto out; diff --git a/SOURCES/0101-RH-cleanup-partmaps-code.patch b/SOURCES/0101-RH-cleanup-partmaps-code.patch new file mode 100644 index 0000000..57fb402 --- /dev/null +++ b/SOURCES/0101-RH-cleanup-partmaps-code.patch @@ -0,0 +1,199 @@ +--- + libmultipath/devmapper.c | 155 ++++++++++++++++++----------------------------- + 1 file changed, 61 insertions(+), 94 deletions(-) + +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -1006,8 +1006,9 @@ bad: + return NULL; + } + +-int +-dm_remove_partmaps (const char * mapname, int need_sync) ++static int ++do_foreach_partmaps (const char * mapname, int (*partmap_func)(char *, void *), ++ void *data) + { + struct dm_task *dmt; + struct dm_names *names; +@@ -1059,26 +1060,8 @@ dm_remove_partmaps (const char * mapname + */ + strstr(params, dev_t) + ) { +- /* +- * then it's a kpartx generated partition. +- * remove it. +- */ +- /* +- * if the opencount is 0 maybe some other +- * partitions depend on it. +- */ +- if (dm_get_opencount(names->name)) { +- dm_remove_partmaps(names->name, need_sync); +- if (dm_get_opencount(names->name)) { +- condlog(2, "%s: map in use", +- names->name); +- goto out; +- } +- } +- condlog(4, "partition map %s removed", +- names->name); +- dm_simplecmd_flush(DM_DEVICE_REMOVE, names->name, +- need_sync, 0); ++ if (partmap_func(names->name, data) != 0) ++ goto out; + } + + next = names->next; +@@ -1091,6 +1074,35 @@ out: + return r; + } + ++struct remove_data { ++ int need_sync; ++}; ++ ++static int ++remove_partmap(char *name, void *data) ++{ ++ struct remove_data *rd = (struct remove_data *)data; ++ ++ if (dm_get_opencount(name)) { ++ dm_remove_partmaps(name, rd->need_sync); ++ if (dm_get_opencount(name)) { ++ condlog(2, "%s: map in use", name); ++ return 1; ++ } ++ } ++ condlog(4, "partition map %s removed", name); ++ dm_simplecmd_flush(DM_DEVICE_REMOVE, name, ++ rd->need_sync, 0); ++ return 0; ++} ++ ++int ++dm_remove_partmaps (const char * mapname, int need_sync) ++{ ++ struct remove_data rd = { need_sync }; ++ return do_foreach_partmaps(mapname, remove_partmap, &rd); ++} ++ + static struct dm_info * + alloc_dminfo (void) + { +@@ -1140,86 +1152,41 @@ out: + return r; + } + +-int +-dm_rename_partmaps (char * old, char * new) ++struct rename_data { ++ char *old; ++ char *new; ++ char *delim; ++}; ++ ++static int ++rename_partmap (char *name, void *data) + { +- struct dm_task *dmt; +- struct dm_names *names; +- unsigned next = 0; + char buff[PARAMS_SIZE]; +- unsigned long long size; +- char dev_t[32]; +- int r = 1; + int offset; +- char *delim; +- +- if (!(dmt = dm_task_create(DM_DEVICE_LIST))) +- return 1; ++ struct rename_data *rd = (struct rename_data *)data; + +- dm_task_no_open_count(dmt); +- +- if (!dm_task_run(dmt)) +- goto out; +- +- if (!(names = dm_task_get_names(dmt))) +- goto out; +- +- if (!names->dev) { +- r = 0; /* this is perfectly valid */ +- goto out; +- } ++ if (strncmp(name, rd->old, strlen(rd->old)) != 0) ++ return 0; ++ for (offset = strlen(rd->old); name[offset] && !(isdigit(name[offset])); offset++); /* do nothing */ ++ snprintf(buff, PARAMS_SIZE, "%s%s%s", rd->new, rd->delim, ++ name + offset); ++ dm_rename(name, buff); ++ condlog(4, "partition map %s renamed", name); ++ return 0; ++} + +- if (dm_dev_t(old, &dev_t[0], 32)) +- goto out; ++int ++dm_rename_partmaps (char * old, char * new) ++{ ++ struct rename_data rd; + ++ rd.old = old; ++ rd.new = new; + if (isdigit(new[strlen(new)-1])) +- delim = "p"; ++ rd.delim = "p"; + else +- delim = ""; +- +- do { +- if ( +- /* +- * if devmap target is "linear" +- */ +- (dm_type(names->name, TGT_PART) > 0) && +- +- /* +- * and the multipath mapname and the part mapname start +- * the same +- */ +- !strncmp(names->name, old, strlen(old)) && +- +- /* +- * and we can fetch the map table from the kernel +- */ +- !dm_get_map(names->name, &size, &buff[0]) && +- +- /* +- * and the table maps over the multipath map +- */ +- strstr(buff, dev_t) +- ) { +- /* +- * then it's a kpartx generated partition. +- * Rename it. +- */ +- for (offset = strlen(old); names->name[offset] && !(isdigit(names->name[offset])); offset++); /* do nothing */ +- snprintf(buff, PARAMS_SIZE, "%s%s%s", +- new, delim, names->name + offset); +- dm_rename(names->name, buff); +- condlog(4, "partition map %s renamed", +- names->name); +- } +- +- next = names->next; +- names = (void *) names + next; +- } while (next); +- +- r = 0; +-out: +- dm_task_destroy (dmt); +- return r; ++ rd.delim = ""; ++ return do_foreach_partmaps(old, rename_partmap, &rd); + } + + int diff --git a/SOURCES/0102-RHBZ-631009-deferred-remove.patch b/SOURCES/0102-RHBZ-631009-deferred-remove.patch new file mode 100644 index 0000000..9e40337 --- /dev/null +++ b/SOURCES/0102-RHBZ-631009-deferred-remove.patch @@ -0,0 +1,764 @@ +--- + libmultipath/Makefile | 6 + + libmultipath/config.c | 3 + libmultipath/config.h | 3 + libmultipath/configure.c | 1 + libmultipath/defaults.h | 1 + libmultipath/devmapper.c | 142 ++++++++++++++++++++++++++++++++++++++++----- + libmultipath/devmapper.h | 11 ++- + libmultipath/dict.c | 116 ++++++++++++++++++++++++++++++++++++ + libmultipath/propsel.c | 28 ++++++++ + libmultipath/propsel.h | 1 + libmultipath/structs.h | 8 ++ + libmultipath/structs_vec.c | 3 + multipath/multipath.conf.5 | 14 ++++ + multipathd/main.c | 23 +++++-- + 14 files changed, 333 insertions(+), 27 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -337,6 +337,7 @@ merge_hwe (struct hwentry * dst, struct + merge_num(user_friendly_names); + merge_num(retain_hwhandler); + merge_num(detect_prio); ++ merge_num(deferred_remove); + + /* + * Make sure features is consistent with +@@ -394,6 +395,7 @@ overwrite_hwe (struct hwentry * dst, str + overwrite_num(user_friendly_names); + overwrite_num(retain_hwhandler); + overwrite_num(detect_prio); ++ overwrite_num(deferred_remove); + + /* + * Make sure features is consistent with +@@ -617,6 +619,7 @@ load_config (char * file, struct udev *u + conf->fast_io_fail = DEFAULT_FAST_IO_FAIL; + conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER; + conf->detect_prio = DEFAULT_DETECT_PRIO; ++ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE; + conf->hw_strmatch = 0; + conf->force_sync = 0; + +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -61,6 +61,7 @@ struct hwentry { + int user_friendly_names; + int retain_hwhandler; + int detect_prio; ++ int deferred_remove; + char * bl_product; + }; + +@@ -84,6 +85,7 @@ struct mpentry { + int flush_on_last_del; + int attribute_flags; + int user_friendly_names; ++ int deferred_remove; + uid_t uid; + gid_t gid; + mode_t mode; +@@ -128,6 +130,7 @@ struct config { + int retain_hwhandler; + int detect_prio; + int force_sync; ++ int deferred_remove; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -290,6 +290,7 @@ setup_map (struct multipath * mpp, char + select_dev_loss(mpp); + select_reservation_key(mpp); + select_retain_hwhandler(mpp); ++ select_deferred_remove(mpp); + + sysfs_set_scsi_tmo(mpp); + /* +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -19,6 +19,7 @@ + #define DEFAULT_FAST_IO_FAIL 5 + #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF + #define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF ++#define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF + + #define DEFAULT_CHECKINT 5 + #define MAX_CHECKINT(a) (a << 2) +Index: multipath-tools-130222/libmultipath/devmapper.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.c ++++ multipath-tools-130222/libmultipath/devmapper.c +@@ -32,6 +32,8 @@ + #define UUID_PREFIX "mpath-" + #define UUID_PREFIX_LEN 6 + ++static int dm_cancel_remove_partmaps(const char * mapname); ++ + #ifndef LIBDM_API_COOKIE + static inline int dm_task_set_cookie(struct dm_task *dmt, uint32_t *c, int a) + { +@@ -103,7 +105,9 @@ dm_lib_prereq (void) + { + char version[64]; + int v[3]; +-#if defined(DM_SUBSYSTEM_UDEV_FLAG0) ++#if defined(LIBDM_API_DEFERRED) ++ int minv[3] = {1, 2, 89}; ++#elif defined(DM_SUBSYSTEM_UDEV_FLAG0) + int minv[3] = {1, 2, 82}; + #elif defined(LIBDM_API_COOKIE) + int minv[3] = {1, 2, 38}; +@@ -201,8 +205,10 @@ dm_prereq (void) + return dm_drv_prereq(); + } + ++#define do_deferred(x) ((x) == DEFERRED_REMOVE_ON || (x) == DEFERRED_REMOVE_IN_PROGRESS) ++ + static int +-dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags) { ++dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t udev_flags, int deferred_remove) { + int r = 0; + int udev_wait_flag = (need_sync && (task == DM_DEVICE_RESUME || + task == DM_DEVICE_REMOVE)); +@@ -220,7 +226,10 @@ dm_simplecmd (int task, const char *name + if (no_flush) + dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */ + #endif +- ++#ifdef LIBDM_API_DEFERRED ++ if (do_deferred(deferred_remove)) ++ dm_task_deferred_remove(dmt); ++#endif + if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, ((conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0) | udev_flags)) + goto out; + r = dm_task_run (dmt); +@@ -232,12 +241,18 @@ dm_simplecmd (int task, const char *name + + extern int + dm_simplecmd_flush (int task, const char *name, int needsync, uint16_t udev_flags) { +- return dm_simplecmd(task, name, 0, needsync, udev_flags); ++ return dm_simplecmd(task, name, 0, needsync, udev_flags, 0); + } + + extern int + dm_simplecmd_noflush (int task, const char *name, uint16_t udev_flags) { +- return dm_simplecmd(task, name, 1, 1, udev_flags); ++ return dm_simplecmd(task, name, 1, 1, udev_flags, 0); ++} ++ ++static int ++dm_device_remove (const char *name, int needsync, int deferred_remove) { ++ return dm_simplecmd(DM_DEVICE_REMOVE, name, 0, needsync, 0, ++ deferred_remove); + } + + extern int +@@ -653,7 +668,7 @@ out: + } + + extern int +-_dm_flush_map (const char * mapname, int need_sync) ++_dm_flush_map (const char * mapname, int need_sync, int deferred_remove) + { + int r; + +@@ -663,23 +678,46 @@ _dm_flush_map (const char * mapname, int + if (dm_type(mapname, TGT_MPATH) <= 0) + return 0; /* nothing to do */ + +- if (dm_remove_partmaps(mapname, need_sync)) ++ if (dm_remove_partmaps(mapname, need_sync, deferred_remove)) + return 1; + +- if (dm_get_opencount(mapname)) { ++ if (!do_deferred(deferred_remove) && dm_get_opencount(mapname)) { + condlog(2, "%s: map in use", mapname); + return 1; + } + +- r = dm_simplecmd_flush(DM_DEVICE_REMOVE, mapname, need_sync, 0); ++ r = dm_device_remove(mapname, need_sync, deferred_remove); + + if (r) { ++ if (do_deferred(deferred_remove) && dm_map_present(mapname)) { ++ condlog(4, "multipath map %s remove deferred", ++ mapname); ++ return 2; ++ } + condlog(4, "multipath map %s removed", mapname); + return 0; + } + return 1; + } + ++#ifdef LIBDM_API_DEFERRED ++ ++int ++dm_flush_map_nopaths(const char * mapname, int deferred_remove) ++{ ++ return _dm_flush_map(mapname, 1, deferred_remove); ++} ++ ++#else ++ ++int ++dm_flush_map_nopaths(const char * mapname, int deferred_remove) ++{ ++ return _dm_flush_map(mapname, 1, 0); ++} ++ ++#endif ++ + extern int + dm_suspend_and_flush_map (const char * mapname) + { +@@ -1076,6 +1114,7 @@ out: + + struct remove_data { + int need_sync; ++ int deferred_remove; + }; + + static int +@@ -1084,25 +1123,98 @@ remove_partmap(char *name, void *data) + struct remove_data *rd = (struct remove_data *)data; + + if (dm_get_opencount(name)) { +- dm_remove_partmaps(name, rd->need_sync); +- if (dm_get_opencount(name)) { ++ dm_remove_partmaps(name, rd->need_sync, rd->deferred_remove); ++ if (!do_deferred(rd->deferred_remove) && ++ dm_get_opencount(name)) { + condlog(2, "%s: map in use", name); + return 1; + } + } + condlog(4, "partition map %s removed", name); +- dm_simplecmd_flush(DM_DEVICE_REMOVE, name, +- rd->need_sync, 0); ++ dm_device_remove(name, rd->need_sync, rd->deferred_remove); + return 0; + } + + int +-dm_remove_partmaps (const char * mapname, int need_sync) ++dm_remove_partmaps (const char * mapname, int need_sync, int deferred_remove) + { +- struct remove_data rd = { need_sync }; ++ struct remove_data rd = { need_sync, deferred_remove }; + return do_foreach_partmaps(mapname, remove_partmap, &rd); + } + ++#ifdef LIBDM_API_DEFERRED ++ ++static int ++cancel_remove_partmap (char *name, void *unused) ++{ ++ if (dm_get_opencount(name)) ++ dm_cancel_remove_partmaps(name); ++ if (dm_message(name, "@cancel_deferred_remove") != 0) ++ condlog(0, "%s: can't cancel deferred remove: %s", name, ++ strerror(errno)); ++ return 0; ++} ++ ++static int ++dm_get_deferred_remove (char * mapname) ++{ ++ int r = -1; ++ struct dm_task *dmt; ++ struct dm_info info; ++ ++ if (!(dmt = dm_task_create(DM_DEVICE_INFO))) ++ return -1; ++ ++ if (!dm_task_set_name(dmt, mapname)) ++ goto out; ++ ++ if (!dm_task_run(dmt)) ++ goto out; ++ ++ if (!dm_task_get_info(dmt, &info)) ++ goto out; ++ ++ r = info.deferred_remove; ++out: ++ dm_task_destroy(dmt); ++ return r; ++} ++ ++static int ++dm_cancel_remove_partmaps(const char * mapname) { ++ return do_foreach_partmaps(mapname, cancel_remove_partmap, NULL); ++} ++ ++int ++dm_cancel_deferred_remove (struct multipath *mpp) ++{ ++ int r = 0; ++ ++ if (!dm_get_deferred_remove(mpp->alias)) ++ return 0; ++ if (mpp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) ++ mpp->deferred_remove = DEFERRED_REMOVE_ON; ++ ++ dm_cancel_remove_partmaps(mpp->alias); ++ r = dm_message(mpp->alias, "@cancel_deferred_remove"); ++ if (r) ++ condlog(0, "%s: can't cancel deferred remove: %s", mpp->alias, ++ strerror(errno)); ++ else ++ condlog(2, "%s: canceled deferred remove", mpp->alias); ++ return r; ++} ++ ++#else ++ ++int ++dm_cancel_deferred_remove (struct multipath *mpp) ++{ ++ return 0; ++} ++ ++#endif ++ + static struct dm_info * + alloc_dminfo (void) + { +Index: multipath-tools-130222/libmultipath/devmapper.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/devmapper.h ++++ multipath-tools-130222/libmultipath/devmapper.h +@@ -23,9 +23,11 @@ int dm_map_present (const char *); + int dm_get_map(const char *, unsigned long long *, char *); + int dm_get_status(char *, char *); + int dm_type(const char *, char *); +-int _dm_flush_map (const char *, int); +-#define dm_flush_map(mapname) _dm_flush_map(mapname, 1) +-#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0) ++int _dm_flush_map (const char *, int, int); ++int dm_flush_map_nopaths(const char * mapname, int deferred_remove); ++#define dm_flush_map(mapname) _dm_flush_map(mapname, 1, 0) ++#define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0, 0) ++int dm_cancel_deferred_remove(struct multipath *mpp); + int dm_suspend_and_flush_map(const char * mapname); + int dm_flush_maps (void); + int dm_fail_path(char * mapname, char * path); +@@ -40,7 +42,8 @@ int dm_geteventnr (char *name); + int dm_get_major (char *name); + int dm_get_minor (char *name); + char * dm_mapname(int major, int minor); +-int dm_remove_partmaps (const char * mapname, int need_sync); ++int dm_remove_partmaps (const char * mapname, int need_sync, ++ int deferred_remove); + int dm_get_uuid(char *name, char *uuid); + int dm_get_info (char * mapname, struct dm_info ** dmi); + int dm_rename (char * old, char * new); +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -738,6 +738,29 @@ def_force_sync_handler(vector strvec) + return 0; + } + ++static int ++def_deferred_remove_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->deferred_remove = DEFERRED_REMOVE_OFF; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ conf->deferred_remove = DEFERRED_REMOVE_ON; ++ else ++ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -1445,6 +1468,33 @@ hw_detect_prio_handler(vector strvec) + return 0; + } + ++static int ++hw_deferred_remove_handler(vector strvec) ++{ ++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); ++ char * buff; ++ ++ if (!hwe) ++ return 1; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ hwe->deferred_remove = DEFERRED_REMOVE_OFF; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ hwe->deferred_remove = DEFERRED_REMOVE_ON; ++ else ++ hwe->deferred_remove = DEFERRED_REMOVE_UNDEF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * multipaths block handlers + */ +@@ -1920,6 +1970,32 @@ mp_names_handler(vector strvec) + return 0; + } + ++static int ++mp_deferred_remove_handler(vector strvec) ++{ ++ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); ++ char * buff; ++ ++ if (!mpe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && strcmp(buff, "no") == 0) || ++ (strlen(buff) == 1 && strcmp(buff, "0") == 0)) ++ mpe->deferred_remove = DEFERRED_REMOVE_OFF; ++ else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) || ++ (strlen(buff) == 1 && strcmp(buff, "1") == 0)) ++ mpe->deferred_remove = DEFERRED_REMOVE_ON; ++ else ++ mpe->deferred_remove = DEFERRED_REMOVE_UNDEF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * config file keywords printing + */ +@@ -2165,7 +2241,7 @@ snprint_mp_reservation_key (char * buff, + return snprintf(buff, len, "0x%" PRIx64, prkey); + } + +- static int ++static int + snprint_mp_user_friendly_names (char * buff, int len, void * data) + { + struct mpentry * mpe = (struct mpentry *)data; +@@ -2179,6 +2255,19 @@ snprint_mp_user_friendly_names (char * b + } + + static int ++snprint_mp_deferred_remove (char * buff, int len, void * data) ++{ ++ struct mpentry * mpe = (struct mpentry *)data; ++ ++ if (mpe->deferred_remove == DEFERRED_REMOVE_UNDEF) ++ return 0; ++ else if (mpe->deferred_remove == DEFERRED_REMOVE_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return snprintf(buff, len, "yes"); ++} ++ ++static int + snprint_hw_fast_io_fail(char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -2507,6 +2596,19 @@ snprint_hw_retain_hwhandler_handler(char + } + + static int ++snprint_hw_deferred_remove(char * buff, int len, void * data) ++{ ++ struct hwentry * hwe = (struct hwentry *)data; ++ ++ if (hwe->deferred_remove == DEFERRED_REMOVE_ON) ++ return snprintf(buff, len, "yes"); ++ else if (hwe->deferred_remove == DEFERRED_REMOVE_OFF) ++ return snprintf(buff, len, "no"); ++ else ++ return 0; ++} ++ ++static int + snprint_detect_prio(char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -2900,6 +3002,15 @@ snprint_def_force_sync(char * buff, int + } + + static int ++snprint_def_deferred_remove(char * buff, int len, void * data) ++{ ++ if (conf->deferred_remove == DEFERRED_REMOVE_ON) ++ return snprintf(buff, len, "yes"); ++ else ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -2968,6 +3079,7 @@ init_keywords(void) + install_keyword("detect_prio", &def_detect_prio_handler, &snprint_def_detect_prio); + install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch); + install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync); ++ install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +@@ -3032,6 +3144,7 @@ init_keywords(void) + install_keyword("user_friendly_names", &hw_names_handler, &snprint_hw_user_friendly_names); + install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler_handler); + install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_detect_prio); ++ install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove); + install_sublevel_end(); + + install_keyword_root("multipaths", &multipaths_handler); +@@ -3056,5 +3169,6 @@ init_keywords(void) + install_keyword("gid", &mp_gid_handler, &snprint_mp_gid); + install_keyword("reservation_key", &mp_reservation_key_handler, &snprint_mp_reservation_key); + install_keyword("user_friendly_names", &mp_names_handler, &snprint_mp_user_friendly_names); ++ install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove); + install_sublevel_end(); + } +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -744,6 +744,34 @@ select_retain_hwhandler (struct multipat + } + + extern int ++select_deferred_remove (struct multipath *mp) ++{ ++ if (mp->deferred_remove == DEFERRED_REMOVE_IN_PROGRESS) { ++ condlog(3, "%s: deferred_remove in progress", mp->alias); ++ return 0; ++ } ++ if (mp->mpe && mp->mpe->deferred_remove) { ++ mp->deferred_remove = mp->mpe->deferred_remove; ++ condlog(3, "%s: deferred_remove = %i (multipath setting)", ++ mp->alias, mp->deferred_remove); ++ return 0; ++ } ++ if (mp->hwe && mp->hwe->deferred_remove) { ++ mp->deferred_remove = mp->hwe->deferred_remove; ++ condlog(3, "%s: deferred_remove = %d (controller default)", mp->alias, mp->deferred_remove); ++ return 0; ++ } ++ if (conf->deferred_remove) { ++ mp->deferred_remove = conf->deferred_remove; ++ condlog(3, "%s: deferred_remove = %d (config file default)", mp->alias, mp->deferred_remove); ++ return 0; ++ } ++ mp->deferred_remove = DEFAULT_DEFERRED_REMOVE; ++ condlog(3, "%s: deferred_remove = %d (compiled in default)", mp->alias, mp->deferred_remove); ++ return 0; ++} ++ ++extern int + select_detect_prio (struct path * pp) + { + if (pp->hwe && pp->hwe->detect_prio) { +Index: multipath-tools-130222/libmultipath/propsel.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.h ++++ multipath-tools-130222/libmultipath/propsel.h +@@ -20,3 +20,4 @@ int select_dev_loss(struct multipath *mp + int select_reservation_key(struct multipath *mp); + int select_retain_hwhandler (struct multipath * mp); + int select_detect_prio(struct path * pp); ++int select_deferred_remove(struct multipath *mp); +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -114,6 +114,13 @@ enum detect_prio_states { + DETECT_PRIO_ON, + }; + ++enum deferred_remove_states { ++ DEFERRED_REMOVE_UNDEF, ++ DEFERRED_REMOVE_OFF, ++ DEFERRED_REMOVE_ON, ++ DEFERRED_REMOVE_IN_PROGRESS, ++}; ++ + enum scsi_protocol { + SCSI_PROTOCOL_FCP = 0, /* Fibre Channel */ + SCSI_PROTOCOL_SPI = 1, /* parallel SCSI */ +@@ -207,6 +214,7 @@ struct multipath { + int attribute_flags; + int fast_io_fail; + int retain_hwhandler; ++ int deferred_remove; + unsigned int dev_loss; + uid_t uid; + gid_t gid; +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -214,19 +214,30 @@ sync_maps_state(vector mpvec) + } + + static int +-flush_map(struct multipath * mpp, struct vectors * vecs) ++flush_map(struct multipath * mpp, struct vectors * vecs, int nopaths) + { ++ int r; ++ ++ if (nopaths) ++ r = dm_flush_map_nopaths(mpp->alias, mpp->deferred_remove); ++ else ++ r = dm_flush_map(mpp->alias); + /* + * clear references to this map before flushing so we can ignore + * the spurious uevent we may generate with the dm_flush_map call below + */ +- if (dm_flush_map(mpp->alias)) { ++ if (r) { + /* + * May not really be an error -- if the map was already flushed + * from the device mapper by dmsetup(8) for instance. + */ +- condlog(0, "%s: can't flush", mpp->alias); +- return 1; ++ if (r == 1) ++ condlog(0, "%s: can't flush", mpp->alias); ++ else { ++ condlog(2, "%s: devmap deferred remove", mpp->alias); ++ mpp->deferred_remove = DEFERRED_REMOVE_IN_PROGRESS; ++ } ++ return r; + } + else { + dm_lib_release(); +@@ -372,7 +383,7 @@ ev_remove_map (char * devname, char * al + mpp->alias, mpp->dmi->minor, minor); + return 0; + } +- return flush_map(mpp, vecs); ++ return flush_map(mpp, vecs, 0); + } + + static int +@@ -628,7 +639,7 @@ ev_remove_path (struct path *pp, struct + mpp->flush_on_last_del = FLUSH_IN_PROGRESS; + dm_queue_if_no_path(mpp->alias, 0); + } +- if (!flush_map(mpp, vecs)) { ++ if (!flush_map(mpp, vecs, 1)) { + condlog(2, "%s: removed map after" + " removing all paths", + alias); +Index: multipath-tools-130222/libmultipath/structs_vec.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs_vec.c ++++ multipath-tools-130222/libmultipath/structs_vec.c +@@ -392,6 +392,8 @@ __setup_multipath (struct vectors * vecs + set_no_path_retry(mpp); + select_pg_timeout(mpp); + select_flush_on_last_del(mpp); ++ if (VECTOR_SIZE(mpp->paths) != 0) ++ dm_cancel_deferred_remove(mpp); + } + + return 0; +@@ -565,7 +567,6 @@ int update_multipath (struct vectors *ve + } + } + } +- + return 0; + } + +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -420,6 +420,16 @@ only one checker will run at a time. Th + multipathd checkers running in parallel causes significant CPU pressure. The + Default is + .I no ++.TP ++.B deferred_remove ++If set to ++.I yes ++, multipathd will do a deferred remove instead of a regular remove when the ++last path device has been deleted. This means that if the multipath device is ++still in use, it will be freed when the last user closes it. If path is added ++to the multipath device before the last user closes it, the deferred remove ++will be canceled. Default is ++.I no + . + .SH "blacklist section" + The +@@ -521,6 +531,8 @@ section: + .B features + .TP + .B reservation_key ++.TP ++.B deferred_remove + .RE + .PD + .LP +@@ -611,6 +623,8 @@ section: + .B retain_attached_hw_handler + .TP + .B detect_prio ++.TP ++.B deferred_remove + .RE + .PD + .LP +Index: multipath-tools-130222/libmultipath/Makefile +=================================================================== +--- multipath-tools-130222.orig/libmultipath/Makefile ++++ multipath-tools-130222/libmultipath/Makefile +@@ -36,6 +36,12 @@ ifneq ($(strip $(LIBUDEV_API_RECVBUF)),0 + CFLAGS += -DLIBUDEV_API_RECVBUF + endif + ++LIBDM_API_DEFERRED = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_deferred_remove' /usr/include/libdevmapper.h) ++ ++ifneq ($(strip $(LIBDM_API_DEFERRED)),0) ++ CFLAGS += -DLIBDM_API_DEFERRED ++endif ++ + + all: $(LIBS) + diff --git a/SOURCES/0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch b/SOURCES/0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch new file mode 100644 index 0000000..8c793bb --- /dev/null +++ b/SOURCES/0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch @@ -0,0 +1,10 @@ +diff -purN multipath-tools-130222.orig/multipath/multipath.rules multipath-tools-130222/multipath/multipath.rules +--- multipath-tools-130222.orig/multipath/multipath.rules 2014-11-03 14:37:41.269413134 +0100 ++++ multipath-tools-130222/multipath/multipath.rules 2014-11-03 14:38:43.694281901 +0100 +@@ -45,5 +45,5 @@ ACTION!="change", GOTO="end_mpath" + ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath" + ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" + ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" +-RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode" ++ENV{DM_ACTIVATION}=="1", RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode" + LABEL="end_mpath" diff --git a/SOURCES/0104-RHBZ-1159337-fix-double-free.patch b/SOURCES/0104-RHBZ-1159337-fix-double-free.patch new file mode 100644 index 0000000..cbe4d1e --- /dev/null +++ b/SOURCES/0104-RHBZ-1159337-fix-double-free.patch @@ -0,0 +1,20 @@ +--- + multipathd/main.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -669,9 +669,8 @@ ev_remove_path (struct path *pp, struct + /* + * update our state from kernel + */ +- if (setup_multipath(vecs, mpp)) { +- goto fail; +- } ++ if (setup_multipath(vecs, mpp)) ++ return 1; + sync_map_state(mpp); + + condlog(2, "%s [%s]: path removed from map %s", diff --git a/SOURCES/0105-RHBZ-1180032-find-multipaths-man.patch b/SOURCES/0105-RHBZ-1180032-find-multipaths-man.patch new file mode 100644 index 0000000..c5e6bcf --- /dev/null +++ b/SOURCES/0105-RHBZ-1180032-find-multipaths-man.patch @@ -0,0 +1,37 @@ +--- + multipath/multipath.conf.5 | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -84,6 +84,28 @@ directory where the dynamic shared objec + dependent, commonly + .I /lib/multipath + .TP ++.B find_multipaths ++If set to ++.I yes ++, instead of trying to create a multipath device for every non-blacklisted ++path, multipath will only create a device if one of three condidions are ++met. ++.I 1 ++There are at least two non-blacklisted paths with the same wwid, ++.I 2 ++the user manually forces the creation, by specifying a device with the multipath ++command, or ++.I 3 ++a path has the same WWID as a multipath device that was previously created ++while find_multipaths was set (even if that multipath device doesn't currently ++exist). ++Whenever a multipath device is created with find_multipaths set, multipath will ++remeber the WWID of the device, so that it will automatically create the ++device again, as soon as it sees a path with that WWID. This should allow most ++users to have multipath automatically choose the correct paths to make into ++multipath devices, without having to edit the blacklist; Default is ++.I no ++.TP + .B verbosity + default verbosity. Higher values increase the verbosity level. Valid + levels are between 0 and 6; default is diff --git a/SOURCES/0106-RHBZ-1169935-no-new-devs.patch b/SOURCES/0106-RHBZ-1169935-no-new-devs.patch new file mode 100644 index 0000000..99ae35a --- /dev/null +++ b/SOURCES/0106-RHBZ-1169935-no-new-devs.patch @@ -0,0 +1,231 @@ +--- + libmultipath/config.c | 4 ++++ + libmultipath/config.h | 1 + + libmultipath/configure.c | 5 ++--- + libmultipath/dict.c | 33 +++++++++++++++++++++++++++++++++ + libmultipath/util.c | 30 ++++++++++++++++++++++++++++++ + libmultipath/util.h | 1 + + libmultipath/wwids.c | 21 ++++++++++++++------- + multipathd/main.c | 3 +-- + 8 files changed, 86 insertions(+), 12 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -131,6 +131,7 @@ struct config { + int detect_prio; + int force_sync; + int deferred_remove; ++ int ignore_new_boot_devs; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -775,9 +775,8 @@ coalesce_paths (struct vectors * vecs, v + if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE)) + continue; + +- /* If find_multipaths was selected check if the path is valid */ +- if (conf->find_multipaths && !refwwid && +- !should_multipath(pp1, pathvec)) { ++ /* check if the path is valid */ ++ if (!refwwid && !should_multipath(pp1, pathvec)) { + orphan_path(pp1); + continue; + } +Index: multipath-tools-130222/libmultipath/wwids.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/wwids.c ++++ multipath-tools-130222/libmultipath/wwids.c +@@ -15,6 +15,7 @@ + #include "wwids.h" + #include "defaults.h" + #include "config.h" ++#include "util.h" + + /* + * Copyright (c) 2010 Benjamin Marzinski, Redhat +@@ -268,15 +269,21 @@ should_multipath(struct path *pp1, vecto + { + int i; + struct path *pp2; ++ int ignore_new_devs = (conf->ignore_new_boot_devs && in_initrd()); ++ ++ if (!conf->find_multipaths && !ignore_new_devs) ++ return 1; + + condlog(4, "checking if %s should be multipathed", pp1->dev); +- vector_foreach_slot(pathvec, pp2, i) { +- if (pp1->dev == pp2->dev) +- continue; +- if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) { +- condlog(3, "found multiple paths with wwid %s, " +- "multipathing %s", pp1->wwid, pp1->dev); +- return 1; ++ if (!ignore_new_devs) { ++ vector_foreach_slot(pathvec, pp2, i) { ++ if (pp1->dev == pp2->dev) ++ continue; ++ if (strncmp(pp1->wwid, pp2->wwid, WWID_SIZE) == 0) { ++ condlog(3, "found multiple paths with wwid %s, " ++ "multipathing %s", pp1->wwid, pp1->dev); ++ return 1; ++ } + } + } + if (check_wwids_file(pp1->wwid, 0) < 0) { +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -503,8 +503,7 @@ rescan: + return 1; + } + +- if (conf->find_multipaths && +- !should_multipath(pp, vecs->pathvec)) { ++ if (!should_multipath(pp, vecs->pathvec)) { + orphan_path(pp); + return 0; + } +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -622,6 +622,7 @@ load_config (char * file, struct udev *u + conf->deferred_remove = DEFAULT_DEFERRED_REMOVE; + conf->hw_strmatch = 0; + conf->force_sync = 0; ++ conf->ignore_new_boot_devs = 0; + + /* + * preload default hwtable +@@ -732,6 +733,9 @@ load_config (char * file, struct udev *u + !conf->wwids_file) + goto out; + ++ if (conf->ignore_new_boot_devs) ++ in_initrd(); ++ + return 0; + out: + free_config(conf); +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -761,6 +761,29 @@ def_deferred_remove_handler(vector strve + return 0; + } + ++static int ++def_ignore_new_boot_devs_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->ignore_new_boot_devs = 0; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ conf->ignore_new_boot_devs = 1; ++ else ++ conf->ignore_new_boot_devs = 0; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -3011,6 +3034,15 @@ snprint_def_deferred_remove(char * buff, + } + + static int ++snprint_def_ignore_new_boot_devs(char * buff, int len, void * data) ++{ ++ if (conf->ignore_new_boot_devs == 1) ++ return snprintf(buff, len, "yes"); ++ else ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -3080,6 +3112,7 @@ init_keywords(void) + install_keyword("hw_str_match", &def_hw_strmatch_handler, &snprint_def_hw_strmatch); + install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync); + install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove); ++ install_keyword("ignore_new_boot_devs", &def_ignore_new_boot_devs_handler, &snprint_def_ignore_new_boot_devs); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +Index: multipath-tools-130222/libmultipath/util.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/util.c ++++ multipath-tools-130222/libmultipath/util.c +@@ -3,6 +3,8 @@ + #include + #include + #include ++#include ++#include + + #include "debug.h" + #include "memory.h" +@@ -267,3 +269,31 @@ dev_t parse_devt(const char *dev_t) + + return makedev(maj, min); + } ++ ++/* This define was taken from systemd. src/shared/macro.h */ ++#define F_TYPE_EQUAL(a, b) (a == (typeof(a)) b) ++ ++/* This function was taken from systemd. src/shared/util.c */ ++int in_initrd(void) { ++ static int saved = -1; ++ struct statfs s; ++ ++ if (saved >= 0) ++ return saved; ++ ++ /* We make two checks here: ++ * ++ * 1. the flag file /etc/initrd-release must exist ++ * 2. the root file system must be a memory file system ++ * The second check is extra paranoia, since misdetecting an ++ * initrd can have bad bad consequences due the initrd ++ * emptying when transititioning to the main systemd. ++ */ ++ ++ saved = access("/etc/initrd-release", F_OK) >= 0 && ++ statfs("/", &s) >= 0 && ++ (F_TYPE_EQUAL(s.f_type, TMPFS_MAGIC) || ++ F_TYPE_EQUAL(s.f_type, RAMFS_MAGIC)); ++ ++ return saved; ++} +Index: multipath-tools-130222/libmultipath/util.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/util.h ++++ multipath-tools-130222/libmultipath/util.h +@@ -11,6 +11,7 @@ void remove_trailing_chars(char *path, c + int devt2devname (char *, int, char *); + dev_t parse_devt(const char *dev_t); + char *convert_dev(char *dev, int is_path_device); ++int in_initrd(void); + + #define safe_sprintf(var, format, args...) \ + snprintf(var, sizeof(var), format, ##args) >= sizeof(var) diff --git a/SOURCES/0107-RH-adapter-name-wildcard.patch b/SOURCES/0107-RH-adapter-name-wildcard.patch new file mode 100644 index 0000000..3c67de5 --- /dev/null +++ b/SOURCES/0107-RH-adapter-name-wildcard.patch @@ -0,0 +1,33 @@ +--- + libmultipath/print.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -510,6 +510,16 @@ snprint_tgt_wwnn (char * buff, size_t le + } + + static int ++snprint_host_adapter (char * buff, size_t len, struct path * pp) ++{ ++ char adapter[SLOT_NAME_SIZE]; ++ ++ if (sysfs_get_host_adapter_name(pp, adapter)) ++ return snprintf(buff, len, "[undef]"); ++ return snprint_str(buff, len, adapter); ++} ++ ++static int + snprint_path_checker (char * buff, size_t len, struct path * pp) + { + struct checker * c = &pp->checker; +@@ -557,6 +567,7 @@ struct path_data pd[] = { + {'n', "target WWNN", 0, snprint_tgt_wwnn}, + {'R', "host WWPN", 0, snprint_host_wwpn}, + {'r', "target WWPN", 0, snprint_tgt_wwpn}, ++ {'a', "host adapter", 0, snprint_host_adapter}, + {0, NULL, 0 , NULL} + }; + diff --git a/SOURCES/0108-RHBZ-1153832-kpartx-remove-devs.patch b/SOURCES/0108-RHBZ-1153832-kpartx-remove-devs.patch new file mode 100644 index 0000000..f02551a --- /dev/null +++ b/SOURCES/0108-RHBZ-1153832-kpartx-remove-devs.patch @@ -0,0 +1,15 @@ +--- + multipath/multipath.rules | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -45,5 +45,5 @@ ACTION!="change", GOTO="end_mpath" + ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath" + ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" + ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" +-ENV{DM_ACTIVATION}=="1", RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode" ++ENV{DM_ACTIVATION}=="1", RUN+="$env{MPATH_SBIN_PATH}/kpartx -u $tempnode" + LABEL="end_mpath" diff --git a/SOURCES/0109-RH-read-only-bindings.patch b/SOURCES/0109-RH-read-only-bindings.patch new file mode 100644 index 0000000..c08120f --- /dev/null +++ b/SOURCES/0109-RH-read-only-bindings.patch @@ -0,0 +1,27 @@ +--- + multipathd/main.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -1879,7 +1879,7 @@ main (int argc, char *argv[]) + if (!conf) + exit(1); + +- while ((arg = getopt(argc, argv, ":dv:k::")) != EOF ) { ++ while ((arg = getopt(argc, argv, ":dv:k::B")) != EOF ) { + switch(arg) { + case 'd': + logsink = 0; +@@ -1895,6 +1895,9 @@ main (int argc, char *argv[]) + case 'k': + uxclnt(optarg); + exit(0); ++ case 'B': ++ conf->bindings_read_only = 1; ++ break; + default: + ; + } diff --git a/SOURCES/0110-RHBZ-blacklist-vd-devs.patch b/SOURCES/0110-RHBZ-blacklist-vd-devs.patch new file mode 100644 index 0000000..af52d0d --- /dev/null +++ b/SOURCES/0110-RHBZ-blacklist-vd-devs.patch @@ -0,0 +1,17 @@ +--- + libmultipath/blacklist.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/blacklist.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/blacklist.c ++++ multipath-tools-130222/libmultipath/blacklist.c +@@ -169,7 +169,7 @@ setup_default_blist (struct config * con + if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT)) + return 1; + +- str = STRDUP("^(td|hd)[a-z]"); ++ str = STRDUP("^(td|hd|vd)[a-z]"); + if (!str) + return 1; + if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT)) diff --git a/SOURCES/0111-RH-dont-show-pg-timeout.patch b/SOURCES/0111-RH-dont-show-pg-timeout.patch new file mode 100644 index 0000000..f545cc5 --- /dev/null +++ b/SOURCES/0111-RH-dont-show-pg-timeout.patch @@ -0,0 +1,147 @@ +--- + libmultipath/dict.c | 97 ---------------------------------------------------- + 1 file changed, 97 deletions(-) + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -473,26 +473,6 @@ def_checker_timeout_handler(vector strve + static int + def_pg_timeout_handler(vector strvec) + { +- int pg_timeout; +- char * buff; +- +- buff = set_value(strvec); +- +- if (!buff) +- return 1; +- +- if (strlen(buff) == 4 && !strcmp(buff, "none")) +- conf->pg_timeout = -PGTIMEOUT_NONE; +- else if (sscanf(buff, "%d", &pg_timeout) == 1 && pg_timeout >= 0) { +- if (pg_timeout == 0) +- conf->pg_timeout = -PGTIMEOUT_NONE; +- else +- conf->pg_timeout = pg_timeout; +- } +- else +- conf->pg_timeout = PGTIMEOUT_UNDEF; +- +- FREE(buff); + return 0; + } + +@@ -1358,30 +1338,6 @@ hw_minio_rq_handler(vector strvec) + static int + hw_pg_timeout_handler(vector strvec) + { +- int pg_timeout; +- struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); +- char *buff; +- +- if (!hwe) +- return 1; +- +- buff = set_value(strvec); +- +- if (!buff) +- return 1; +- +- if (strlen(buff) == 4 && !strcmp(buff, "none")) +- hwe->pg_timeout = -PGTIMEOUT_NONE; +- else if (sscanf(buff, "%d", &pg_timeout) == 1 && pg_timeout >= 0) { +- if (pg_timeout == 0) +- hwe->pg_timeout = -PGTIMEOUT_NONE; +- else +- hwe->pg_timeout = pg_timeout; +- } +- else +- hwe->pg_timeout = PGTIMEOUT_UNDEF; +- +- FREE(buff); + return 0; + } + +@@ -1819,29 +1775,6 @@ mp_minio_rq_handler(vector strvec) + static int + mp_pg_timeout_handler(vector strvec) + { +- int pg_timeout; +- struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); +- char *buff; +- +- if (!mpe) +- return 1; +- +- buff = set_value(strvec); +- +- if (!buff) +- return 1; +- if (strlen(buff) == 4 && !strcmp(buff, "none")) +- mpe->pg_timeout = -PGTIMEOUT_NONE; +- else if (sscanf(buff, "%d", &pg_timeout) == 1 && pg_timeout >= 0) { +- if (pg_timeout == 0) +- mpe->pg_timeout = -PGTIMEOUT_NONE; +- else +- mpe->pg_timeout = pg_timeout; +- } +- else +- mpe->pg_timeout = PGTIMEOUT_UNDEF; +- +- FREE(buff); + return 0; + } + +@@ -2180,16 +2113,6 @@ snprint_mp_rr_min_io_rq (char * buff, in + static int + snprint_mp_pg_timeout (char * buff, int len, void * data) + { +- struct mpentry * mpe = (struct mpentry *)data; +- +- switch (mpe->pg_timeout) { +- case PGTIMEOUT_UNDEF: +- break; +- case -PGTIMEOUT_NONE: +- return snprintf(buff, len, "\"none\""); +- default: +- return snprintf(buff, len, "%i", mpe->pg_timeout); +- } + return 0; + } + +@@ -2551,19 +2474,6 @@ snprint_hw_rr_min_io_rq (char * buff, in + static int + snprint_hw_pg_timeout (char * buff, int len, void * data) + { +- struct hwentry * hwe = (struct hwentry *)data; +- +- if (!hwe->pg_timeout) +- return 0; +- +- switch (hwe->pg_timeout) { +- case PGTIMEOUT_UNDEF: +- break; +- case -PGTIMEOUT_NONE: +- return snprintf(buff, len, "\"none\""); +- default: +- return snprintf(buff, len, "%i", hwe->pg_timeout); +- } + return 0; + } + +@@ -2895,13 +2805,6 @@ snprint_def_checker_timeout (char *buff, + static int + snprint_def_pg_timeout (char * buff, int len, void * data) + { +- switch (conf->pg_timeout) { +- case PGTIMEOUT_UNDEF: +- case -PGTIMEOUT_NONE: +- return snprintf(buff, len, "\"none\""); +- default: +- return snprintf(buff, len, "%i", conf->pg_timeout); +- } + return 0; + } + diff --git a/SOURCES/0112-RHBZ-1194917-add-config_dir-option.patch b/SOURCES/0112-RHBZ-1194917-add-config_dir-option.patch new file mode 100644 index 0000000..6cc07e7 --- /dev/null +++ b/SOURCES/0112-RHBZ-1194917-add-config_dir-option.patch @@ -0,0 +1,616 @@ +--- + libmultipath/config.c | 56 +++++++++++++++++++++++++++++++- + libmultipath/config.h | 2 + + libmultipath/defaults.h | 1 + libmultipath/dict.c | 69 +++++++++++++++++++++++++++++++++++---- + libmultipath/parser.c | 78 +++++++++++++++++++++++---------------------- + libmultipath/parser.h | 3 - + multipath.conf.annotated | 10 +++++ + multipath.conf.defaults | 1 + multipath/multipath.conf.5 | 7 ++++ + 9 files changed, 179 insertions(+), 48 deletions(-) + +Index: multipath-tools-130222/libmultipath/parser.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/parser.c ++++ multipath-tools-130222/libmultipath/parser.c +@@ -18,6 +18,7 @@ + */ + + #include ++#include + + #include "parser.h" + #include "memory.h" +@@ -453,14 +454,15 @@ set_value(vector strvec) + /* non-recursive configuration stream handler */ + static int kw_level = 0; + +-int warn_on_duplicates(vector uniques, char *str) ++int warn_on_duplicates(vector uniques, char *str, char *file) + { + char *tmp; + int i; + + vector_foreach_slot(uniques, tmp, i) { + if (!strcmp(str, tmp)) { +- condlog(1, "multipath.conf line %d, duplicate keyword: %s", line_nr, str); ++ condlog(1, "%s line %d, duplicate keyword: %s", ++ file, line_nr, str); + return 0; + } + } +@@ -496,65 +498,70 @@ is_sublevel_keyword(char *str) + } + + int +-validate_config_strvec(vector strvec) ++validate_config_strvec(vector strvec, char *file) + { + char *str; + int i; + + str = VECTOR_SLOT(strvec, 0); + if (str == NULL) { +- condlog(0, "can't parse option on line %d of config file", +- line_nr); ++ condlog(0, "can't parse option on line %d of %s", ++ line_nr, file); + return -1; + } + if (*str == '}') { + if (VECTOR_SIZE(strvec) > 1) +- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 1), line_nr); ++ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 1), line_nr, file); + return 0; + } + if (*str == '{') { +- condlog(0, "invalid keyword '%s' on line %d of config file", str, line_nr); ++ condlog(0, "invalid keyword '%s' on line %d of %s", ++ str, line_nr, file); + return -1; + } + if (is_sublevel_keyword(str)) { + str = VECTOR_SLOT(strvec, 1); + if (str == NULL) +- condlog(0, "missing '{' on line %d of config file", line_nr); ++ condlog(0, "missing '{' on line %d of %s", ++ line_nr, file); + else if (*str != '{') +- condlog(0, "expecting '{' on line %d of config file. found '%s'", line_nr, str); ++ condlog(0, "expecting '{' on line %d of %s. found '%s'", ++ line_nr, file, str); + else if (VECTOR_SIZE(strvec) > 2) +- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr); ++ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file); + return 0; + } + str = VECTOR_SLOT(strvec, 1); + if (str == NULL) { +- condlog(0, "missing value for option '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 0), line_nr); ++ condlog(0, "missing value for option '%s' on line %d of %s", ++ (char *)VECTOR_SLOT(strvec, 0), line_nr, file); + return -1; + } + if (*str != '"') { + if (VECTOR_SIZE(strvec) > 2) +- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, 2), line_nr); ++ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file); + return 0; + } + for (i = 2; i < VECTOR_SIZE(strvec); i++) { + str = VECTOR_SLOT(strvec, i); + if (str == NULL) { +- condlog(0, "can't parse value on line %d of config file", line_nr); ++ condlog(0, "can't parse value on line %d of %s", ++ line_nr, file); + return -1; + } + if (*str == '"') { + if (VECTOR_SIZE(strvec) > i + 1) +- condlog(0, "ignoring extra data starting with '%s' on line %d of config file", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr); ++ condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr, file); + return 0; + } + } +- condlog(0, "missing closing quotes on line %d of config file", +- line_nr); ++ condlog(0, "missing closing quotes on line %d of %s", ++ line_nr, file); + return 0; + } + +-int +-process_stream(vector keywords) ++static int ++process_stream(vector keywords, char *file) + { + int i; + int r = 0; +@@ -583,7 +590,7 @@ process_stream(vector keywords) + if (!strvec) + continue; + +- if (validate_config_strvec(strvec) != 0) { ++ if (validate_config_strvec(strvec, file) != 0) { + free_strvec(strvec); + continue; + } +@@ -595,8 +602,8 @@ process_stream(vector keywords) + free_strvec(strvec); + break; + } +- condlog(0, "unmatched '%s' at line %d of config file", +- EOB, line_nr); ++ condlog(0, "unmatched '%s' at line %d of %s", ++ EOB, line_nr, file); + } + + for (i = 0; i < VECTOR_SIZE(keywords); i++) { +@@ -604,7 +611,7 @@ process_stream(vector keywords) + + if (!strcmp(keyword->string, str)) { + if (keyword->unique && +- warn_on_duplicates(uniques, str)) { ++ warn_on_duplicates(uniques, str, file)) { + r = 1; + free_strvec(strvec); + goto out; +@@ -614,15 +621,15 @@ process_stream(vector keywords) + + if (keyword->sub) { + kw_level++; +- r += process_stream(keyword->sub); ++ r += process_stream(keyword->sub, file); + kw_level--; + } + break; + } + } + if (i >= VECTOR_SIZE(keywords)) +- condlog(1, "multipath.conf +%d, invalid keyword: %s", +- line_nr, str); ++ condlog(1, "%s line %d, invalid keyword: %s", ++ file, line_nr, str); + + free_strvec(strvec); + } +@@ -646,27 +653,24 @@ int alloc_keywords(void) + + /* Data initialization */ + int +-init_data(char *conf_file, void (*init_keywords) (void)) ++process_file(char *file) + { + int r; + +- stream = fopen(conf_file, "r"); ++ if (!keywords) { ++ condlog(0, "No keywords alocated"); ++ return 1; ++ } ++ stream = fopen(file, "r"); + if (!stream) { +- syslog(LOG_WARNING, "Configuration file open problem"); ++ condlog(0, "couldn't open configuration file '%s': %s", ++ file, strerror(errno)); + return 1; + } + +- /* Init Keywords structure */ +- (*init_keywords) (); +- +-/* Dump configuration * +- vector_dump(keywords); +- dump_keywords(keywords, 0); +-*/ +- + /* Stream handling */ + line_nr = 0; +- r = process_stream(keywords); ++ r = process_stream(keywords, file); + fclose(stream); + //free_keywords(keywords); + +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -117,6 +117,8 @@ reassign_maps_handler(vector strvec) + static int + multipath_dir_handler(vector strvec) + { ++ if (conf->multipath_dir) ++ FREE(conf->multipath_dir); + conf->multipath_dir = set_value(strvec); + + if (!conf->multipath_dir) +@@ -128,6 +130,8 @@ multipath_dir_handler(vector strvec) + static int + def_selector_handler(vector strvec) + { ++ if (conf->selector) ++ FREE(conf->selector); + conf->selector = set_value(strvec); + + if (!conf->selector) +@@ -155,6 +159,8 @@ def_pgpolicy_handler(vector strvec) + static int + def_uid_attribute_handler(vector strvec) + { ++ if (conf->uid_attribute) ++ FREE(conf->uid_attribute); + conf->uid_attribute = set_value(strvec); + + if (!conf->uid_attribute) +@@ -166,6 +172,8 @@ def_uid_attribute_handler(vector strvec) + static int + def_prio_handler(vector strvec) + { ++ if (conf->prio_name) ++ FREE(conf->prio_name); + conf->prio_name = set_value(strvec); + + if (!conf->prio_name) +@@ -177,6 +185,8 @@ def_prio_handler(vector strvec) + static int + def_alias_prefix_handler(vector strvec) + { ++ if (conf->alias_prefix) ++ FREE(conf->alias_prefix); + conf->alias_prefix = set_value(strvec); + + if (!conf->alias_prefix) +@@ -188,6 +198,8 @@ def_alias_prefix_handler(vector strvec) + static int + def_prio_args_handler(vector strvec) + { ++ if (conf->prio_args) ++ FREE(conf->prio_args); + conf->prio_args = set_value(strvec); + + if (!conf->prio_args) +@@ -199,6 +211,8 @@ def_prio_args_handler(vector strvec) + static int + def_features_handler(vector strvec) + { ++ if (conf->features) ++ FREE(conf->features); + conf->features = set_value(strvec); + + if (!conf->features) +@@ -210,6 +224,8 @@ def_features_handler(vector strvec) + static int + def_path_checker_handler(vector strvec) + { ++ if (conf->checker_name) ++ FREE(conf->checker_name); + conf->checker_name = set_value(strvec); + + if (!conf->checker_name) +@@ -432,6 +448,23 @@ def_no_path_retry_handler(vector strvec) + return 0; + } + ++ ++static int ++def_config_dir_handler(vector strvec) ++{ ++ /* this is only valid in the main config file */ ++ if (conf->processed_main_config) ++ return 0; ++ if (conf->config_dir) ++ FREE(conf->config_dir); ++ conf->config_dir = set_value(strvec); ++ ++ if (!conf->config_dir) ++ return 1; ++ ++ return 0; ++} ++ + static int + def_queue_without_daemon(vector strvec) + { +@@ -611,6 +644,8 @@ def_names_handler(vector strvec) + static int + bindings_file_handler(vector strvec) + { ++ if (conf->bindings_file) ++ FREE(conf->bindings_file); + conf->bindings_file = set_value(strvec); + + if (!conf->bindings_file) +@@ -622,6 +657,8 @@ bindings_file_handler(vector strvec) + static int + wwids_file_handler(vector strvec) + { ++ if (conf->wwids_file) ++ FREE(conf->wwids_file); + conf->wwids_file = set_value(strvec); + + if (!conf->wwids_file) +@@ -770,9 +807,12 @@ def_ignore_new_boot_devs_handler(vector + static int + blacklist_handler(vector strvec) + { +- conf->blist_devnode = vector_alloc(); +- conf->blist_wwid = vector_alloc(); +- conf->blist_device = vector_alloc(); ++ if (!conf->blist_devnode) ++ conf->blist_devnode = vector_alloc(); ++ if (!conf->blist_wwid) ++ conf->blist_wwid = vector_alloc(); ++ if (!conf->blist_device) ++ conf->blist_device = vector_alloc(); + + if (!conf->blist_devnode || !conf->blist_wwid || !conf->blist_device) + return 1; +@@ -783,9 +823,12 @@ blacklist_handler(vector strvec) + static int + blacklist_exceptions_handler(vector strvec) + { +- conf->elist_devnode = vector_alloc(); +- conf->elist_wwid = vector_alloc(); +- conf->elist_device = vector_alloc(); ++ if (!conf->elist_devnode) ++ conf->elist_devnode = vector_alloc(); ++ if (!conf->elist_wwid) ++ conf->elist_wwid = vector_alloc(); ++ if (!conf->elist_device) ++ conf->elist_device = vector_alloc(); + + if (!conf->elist_devnode || !conf->elist_wwid || !conf->elist_device) + return 1; +@@ -1480,7 +1523,8 @@ hw_deferred_remove_handler(vector strvec + static int + multipaths_handler(vector strvec) + { +- conf->mptable = vector_alloc(); ++ if (!conf->mptable) ++ conf->mptable = vector_alloc(); + + if (!conf->mptable) + return 1; +@@ -2945,6 +2989,16 @@ snprint_def_ignore_new_boot_devs(char * + return snprintf(buff, len, "no"); + } + ++ ++static int ++snprint_def_config_dir (char * buff, int len, void * data) ++{ ++ if (!conf->config_dir) ++ return 0; ++ ++ return snprintf(buff, len, "\"%s\"", conf->config_dir); ++} ++ + static int + snprint_ble_simple (char * buff, int len, void * data) + { +@@ -3016,6 +3070,7 @@ init_keywords(void) + install_keyword("force_sync", &def_force_sync_handler, &snprint_def_force_sync); + install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove); + install_keyword("ignore_new_boot_devs", &def_ignore_new_boot_devs_handler, &snprint_def_ignore_new_boot_devs); ++ install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +Index: multipath-tools-130222/libmultipath/parser.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/parser.h ++++ multipath-tools-130222/libmultipath/parser.h +@@ -76,9 +76,8 @@ extern int read_line(char *buf, int size + extern vector read_value_block(void); + extern int alloc_value_block(vector strvec, void (*alloc_func) (vector)); + extern void *set_value(vector strvec); +-extern int process_stream(vector keywords); + extern int alloc_keywords(void); +-extern int init_data(char *conf_file, void (*init_keywords) (void)); ++extern int process_file(char *conf_file); + extern struct keyword * find_keyword(vector v, char * name); + void set_current_keywords (vector *k); + int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -6,6 +6,9 @@ + #include + #include + #include ++#include ++#include ++#include + + #include "checkers.h" + #include "memory.h" +@@ -556,6 +559,7 @@ free_config (struct config * conf) + + if (conf->wwids_file) + FREE(conf->wwids_file); ++ + if (conf->prio_name) + FREE(conf->prio_name); + +@@ -567,6 +571,10 @@ free_config (struct config * conf) + + if (conf->checker_name) + FREE(conf->checker_name); ++ ++ if (conf->config_dir) ++ FREE(conf->config_dir); ++ + if (conf->reservation_key) + FREE(conf->reservation_key); + +@@ -584,6 +592,43 @@ free_config (struct config * conf) + FREE(conf); + } + ++/* if multipath fails to process the config directory, it should continue, ++ * with just a warning message */ ++static void ++process_config_dir(vector keywords, char *dir) ++{ ++ struct dirent **namelist; ++ int i, n; ++ char path[LINE_MAX]; ++ int old_hwtable_size; ++ ++ if (dir[0] != '/') { ++ condlog(1, "config_dir '%s' must be a fully qualified path", ++ dir); ++ return; ++ } ++ n = scandir(dir, &namelist, NULL, alphasort); ++ if (n < 0) { ++ if (errno == ENOENT) ++ condlog(3, "No configuration dir '%s'", dir); ++ else ++ condlog(0, "couldn't open configuration dir '%s': %s", ++ dir, strerror(errno)); ++ return; ++ } ++ for (i = 0; i < n; i++) { ++ if (!strstr(namelist[i]->d_name, ".conf")) ++ continue; ++ old_hwtable_size = VECTOR_SIZE(conf->hwtable); ++ snprintf(path, LINE_MAX, "%s/%s", dir, namelist[i]->d_name); ++ path[LINE_MAX-1] = '\0'; ++ process_file(path); ++ if (VECTOR_SIZE(conf->hwtable) > old_hwtable_size) ++ factorize_hwtable(conf->hwtable, old_hwtable_size); ++ ++ } ++} ++ + int + load_config (char * file, struct udev *udev) + { +@@ -623,6 +668,7 @@ load_config (char * file, struct udev *u + conf->hw_strmatch = 0; + conf->force_sync = 0; + conf->ignore_new_boot_devs = 0; ++ conf->processed_main_config = 0; + + /* + * preload default hwtable +@@ -641,11 +687,12 @@ load_config (char * file, struct udev *u + */ + set_current_keywords(&conf->keywords); + alloc_keywords(); ++ init_keywords(); + if (filepresent(file)) { + int builtin_hwtable_size; + + builtin_hwtable_size = VECTOR_SIZE(conf->hwtable); +- if (init_data(file, init_keywords)) { ++ if (process_file(file)) { + condlog(0, "error parsing config file"); + goto out; + } +@@ -658,7 +705,6 @@ load_config (char * file, struct udev *u + } + + } else { +- init_keywords(); + condlog(0, "/etc/multipath.conf does not exist, blacklisting all devices."); + condlog(0, "A default multipath.conf file is located at"); + condlog(0, "/usr/share/doc/device-mapper-multipath-%d.%d.%d/multipath.conf", MULTIPATH_VERSION(VERSION_CODE)); +@@ -677,6 +723,12 @@ load_config (char * file, struct udev *u + } + } + ++ conf->processed_main_config = 1; ++ if (conf->config_dir == NULL) ++ conf->config_dir = set_default(DEFAULT_CONFIG_DIR); ++ if (conf->config_dir && conf->config_dir[0] != '\0') ++ process_config_dir(conf->keywords, conf->config_dir); ++ + /* + * fill the voids left in the config file + */ +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -132,6 +132,7 @@ struct config { + int force_sync; + int deferred_remove; + int ignore_new_boot_devs; ++ int processed_main_config; + unsigned int version[3]; + + char * dev; +@@ -147,6 +148,7 @@ struct config { + char * prio_args; + char * checker_name; + char * alias_prefix; ++ char * config_dir; + unsigned char * reservation_key; + + vector keywords; +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -31,5 +31,6 @@ + #define DEFAULT_CONFIGFILE "/etc/multipath.conf" + #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings" + #define DEFAULT_WWIDS_FILE "/etc/multipath/wwids" ++#define DEFAULT_CONFIG_DIR "/etc/multipath/conf.d" + + char * set_default (char * str); +Index: multipath-tools-130222/multipath.conf.annotated +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.annotated ++++ multipath-tools-130222/multipath.conf.annotated +@@ -232,6 +232,16 @@ + # # values : yes|no + # # default : no + # force_sync yes ++# ++# # ++# # name : config_dir ++# # scope : multipath & multipathd ++# # desc : If not set to an empty string, multipath will search ++# # this directory alphabetically for files ending in ".conf" ++# # and it will read configuration information from these ++# # files, just as if it was in /etc/multipath.conf ++# # values : "" or a fully qualified pathname ++# # default : "/etc/multipath/conf.d" + #} + # + ## +Index: multipath-tools-130222/multipath.conf.defaults +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.defaults ++++ multipath-tools-130222/multipath.conf.defaults +@@ -26,6 +26,7 @@ + # log_checker_err always + # retain_attached_hw_handler no + # detect_prio no ++# config_dir "/etc/multipath/conf.d" + #} + #blacklist { + # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -452,6 +452,13 @@ still in use, it will be freed when the + to the multipath device before the last user closes it, the deferred remove + will be canceled. Default is + .I no ++.TP ++.B config_dir ++If set to anything other than "", multipath will search this directory ++alphabetically for file ending in ".conf" and it will read configuration ++information from them, just as if it was in /etc/multipath.conf. config_dir ++must either be "" or a fully qualified directory name. Default is ++.I "/etc/multipath/conf.d" + . + .SH "blacklist section" + The diff --git a/SOURCES/0113-RHBZ-1194917-cleanup.patch b/SOURCES/0113-RHBZ-1194917-cleanup.patch new file mode 100644 index 0000000..cf95c98 --- /dev/null +++ b/SOURCES/0113-RHBZ-1194917-cleanup.patch @@ -0,0 +1,185 @@ +--- + libmultipath/parser.c | 103 +++----------------------------------------------- + libmultipath/parser.h | 6 -- + 2 files changed, 8 insertions(+), 101 deletions(-) + +Index: multipath-tools-130222/libmultipath/parser.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/parser.c ++++ multipath-tools-130222/libmultipath/parser.c +@@ -280,8 +280,8 @@ out: + return NULL; + } + +-int +-read_line(char *buf, int size) ++static int ++read_line(FILE *stream, char *buf, int size) + { + int ch; + int count = 0; +@@ -297,95 +297,6 @@ read_line(char *buf, int size) + return (ch == EOF) ? 0 : 1; + } + +-vector +-read_value_block(void) +-{ +- char *buf; +- int i; +- char *str = NULL; +- char *dup; +- vector vec = NULL; +- vector elements = vector_alloc(); +- +- if (!elements) +- return NULL; +- +- buf = (char *) MALLOC(MAXBUF); +- +- if (!buf) { +- vector_free(elements); +- return NULL; +- } +- +- while (read_line(buf, MAXBUF)) { +- vec = alloc_strvec(buf); +- if (vec) { +- str = VECTOR_SLOT(vec, 0); +- if (!strcmp(str, EOB)) { +- free_strvec(vec); +- break; +- } +- +- for (i = 0; i < VECTOR_SIZE(vec); i++) { +- str = VECTOR_SLOT(vec, i); +- dup = (char *) MALLOC(strlen(str) + 1); +- if (!dup) +- goto out; +- memcpy(dup, str, strlen(str)); +- +- if (!vector_alloc_slot(elements)) { +- free_strvec(vec); +- goto out1; +- } +- +- vector_set_slot(elements, dup); +- } +- free_strvec(vec); +- } +- memset(buf, 0, MAXBUF); +- } +- FREE(buf); +- return elements; +-out1: +- FREE(dup); +-out: +- FREE(buf); +- vector_free(elements); +- return NULL; +-} +- +-int +-alloc_value_block(vector strvec, void (*alloc_func) (vector)) +-{ +- char *buf; +- char *str = NULL; +- vector vec = NULL; +- +- buf = (char *) MALLOC(MAXBUF); +- +- if (!buf) +- return 1; +- +- while (read_line(buf, MAXBUF)) { +- vec = alloc_strvec(buf); +- if (vec) { +- str = VECTOR_SLOT(vec, 0); +- if (!strcmp(str, EOB)) { +- free_strvec(vec); +- break; +- } +- +- if (VECTOR_SIZE(vec)) +- (*alloc_func) (vec); +- +- free_strvec(vec); +- } +- memset(buf, 0, MAXBUF); +- } +- FREE(buf); +- return 0; +-} +- + void * + set_value(vector strvec) + { +@@ -561,7 +472,7 @@ validate_config_strvec(vector strvec, ch + } + + static int +-process_stream(vector keywords, char *file) ++process_stream(FILE *stream, vector keywords, char *file) + { + int i; + int r = 0; +@@ -582,7 +493,7 @@ process_stream(vector keywords, char *fi + return 1; + } + +- while (read_line(buf, MAXBUF)) { ++ while (read_line(stream, buf, MAXBUF)) { + line_nr++; + strvec = alloc_strvec(buf); + memset(buf,0, MAXBUF); +@@ -621,7 +532,8 @@ process_stream(vector keywords, char *fi + + if (keyword->sub) { + kw_level++; +- r += process_stream(keyword->sub, file); ++ r += process_stream(stream, ++ keyword->sub, file); + kw_level--; + } + break; +@@ -656,6 +568,7 @@ int + process_file(char *file) + { + int r; ++ FILE *stream; + + if (!keywords) { + condlog(0, "No keywords alocated"); +@@ -670,7 +583,7 @@ process_file(char *file) + + /* Stream handling */ + line_nr = 0; +- r = process_stream(keywords, file); ++ r = process_stream(stream, keywords, file); + fclose(stream); + //free_keywords(keywords); + +Index: multipath-tools-130222/libmultipath/parser.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/parser.h ++++ multipath-tools-130222/libmultipath/parser.h +@@ -47,9 +47,6 @@ struct keyword { + int unique; + }; + +-/* global var exported */ +-FILE *stream; +- + /* Reloading helpers */ + #define SET_RELOAD (reload = 1) + #define UNSET_RELOAD (reload = 0) +@@ -72,9 +69,6 @@ extern int _install_keyword(char *string + extern void dump_keywords(vector keydump, int level); + extern void free_keywords(vector keywords); + extern vector alloc_strvec(char *string); +-extern int read_line(char *buf, int size); +-extern vector read_value_block(void); +-extern int alloc_value_block(vector strvec, void (*alloc_func) (vector)); + extern void *set_value(vector strvec); + extern int alloc_keywords(void); + extern int process_file(char *conf_file); diff --git a/SOURCES/0114-RHBZ-1196394-delayed-reintegration.patch b/SOURCES/0114-RHBZ-1196394-delayed-reintegration.patch new file mode 100644 index 0000000..b0647a5 --- /dev/null +++ b/SOURCES/0114-RHBZ-1196394-delayed-reintegration.patch @@ -0,0 +1,744 @@ +--- + libmultipath/checkers.c | 3 + libmultipath/checkers.h | 9 + + libmultipath/config.c | 4 + libmultipath/config.h | 6 + + libmultipath/configure.c | 2 + libmultipath/defaults.h | 1 + libmultipath/dict.c | 204 ++++++++++++++++++++++++++++++++++++++++++++- + libmultipath/print.c | 2 + libmultipath/propsel.c | 52 +++++++++++ + libmultipath/propsel.h | 2 + libmultipath/structs.h | 9 + + multipath.conf.annotated | 40 ++++++++ + multipath.conf.defaults | 2 + multipath/multipath.conf.5 | 27 +++++ + multipathd/main.c | 34 ++++++- + 15 files changed, 388 insertions(+), 9 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -62,6 +62,8 @@ struct hwentry { + int retain_hwhandler; + int detect_prio; + int deferred_remove; ++ int delay_watch_checks; ++ int delay_wait_checks; + char * bl_product; + }; + +@@ -86,6 +88,8 @@ struct mpentry { + int attribute_flags; + int user_friendly_names; + int deferred_remove; ++ int delay_watch_checks; ++ int delay_wait_checks; + uid_t uid; + gid_t gid; + mode_t mode; +@@ -133,6 +137,8 @@ struct config { + int deferred_remove; + int ignore_new_boot_devs; + int processed_main_config; ++ int delay_watch_checks; ++ int delay_wait_checks; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -134,6 +134,11 @@ enum scsi_protocol { + SCSI_PROTOCOL_UNSPEC = 0xf, /* No specific protocol */ + }; + ++enum delay_checks_states { ++ DELAY_CHECKS_OFF = -1, ++ DELAY_CHECKS_UNDEF = 0, ++}; ++ + struct sg_id { + int host_no; + int channel; +@@ -180,6 +185,8 @@ struct path { + int priority; + int pgindex; + int detect_prio; ++ int watch_checks; ++ int wait_checks; + char * uid_attribute; + struct prio prio; + char * prio_args; +@@ -215,6 +222,8 @@ struct multipath { + int fast_io_fail; + int retain_hwhandler; + int deferred_remove; ++ int delay_watch_checks; ++ int delay_wait_checks; + unsigned int dev_loss; + uid_t uid; + gid_t gid; +Index: multipath-tools-130222/libmultipath/checkers.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers.h ++++ multipath-tools-130222/libmultipath/checkers.h +@@ -46,6 +46,14 @@ + * PATH_PENDING: + * - Use: All async checkers + * - Description: Indicates a check IO is in flight. ++ * ++ * PATH_DELAYED: ++ * - Use: None of the checkers (returned if the path is being delayed before ++ * reintegration. ++ * - Description: If a path fails after being up for less than ++ * delay_watch_checks checks, when it comes back up again, it will not ++ * be marked as up until it has been up for delay_wait_checks checks. ++ * During this time, it is marked as "delayed" + */ + enum path_check_state { + PATH_WILD, +@@ -55,6 +63,7 @@ enum path_check_state { + PATH_SHAKY, + PATH_GHOST, + PATH_PENDING, ++ PATH_DELAYED, + PATH_MAX_STATE + }; + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -291,6 +291,8 @@ setup_map (struct multipath * mpp, char + select_reservation_key(mpp); + select_retain_hwhandler(mpp); + select_deferred_remove(mpp); ++ select_delay_watch_checks(mpp); ++ select_delay_wait_checks(mpp); + + sysfs_set_scsi_tmo(mpp); + /* +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -20,6 +20,7 @@ + #define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF + #define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF + #define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF ++#define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF + + #define DEFAULT_CHECKINT 5 + #define MAX_CHECKINT(a) (a << 2) +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -801,6 +801,44 @@ def_ignore_new_boot_devs_handler(vector + return 0; + } + ++static int ++def_delay_watch_checks_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->delay_watch_checks = DELAY_CHECKS_OFF; ++ else if ((conf->delay_watch_checks = atoi(buff)) < 1) ++ conf->delay_watch_checks = DELAY_CHECKS_OFF; ++ ++ FREE(buff); ++ return 0; ++} ++ ++static int ++def_delay_wait_checks_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->delay_wait_checks = DELAY_CHECKS_OFF; ++ else if ((conf->delay_wait_checks = atoi(buff)) < 1) ++ conf->delay_wait_checks = DELAY_CHECKS_OFF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -1517,6 +1555,52 @@ hw_deferred_remove_handler(vector strvec + return 0; + } + ++static int ++hw_delay_watch_checks_handler(vector strvec) ++{ ++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); ++ char * buff; ++ ++ if (!hwe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ hwe->delay_watch_checks = DELAY_CHECKS_OFF; ++ else if ((hwe->delay_watch_checks = atoi(buff)) < 1) ++ hwe->delay_watch_checks = DELAY_CHECKS_OFF; ++ ++ FREE(buff); ++ return 0; ++} ++ ++static int ++hw_delay_wait_checks_handler(vector strvec) ++{ ++ struct hwentry *hwe = VECTOR_LAST_SLOT(conf->hwtable); ++ char * buff; ++ ++ if (!hwe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ hwe->delay_wait_checks = DELAY_CHECKS_OFF; ++ else if ((hwe->delay_wait_checks = atoi(buff)) < 1) ++ hwe->delay_wait_checks = DELAY_CHECKS_OFF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * multipaths block handlers + */ +@@ -1996,6 +2080,52 @@ mp_deferred_remove_handler(vector strvec + return 0; + } + ++static int ++mp_delay_watch_checks_handler(vector strvec) ++{ ++ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); ++ char * buff; ++ ++ if (!mpe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ mpe->delay_watch_checks = DELAY_CHECKS_OFF; ++ else if ((mpe->delay_watch_checks = atoi(buff)) < 1) ++ mpe->delay_watch_checks = DELAY_CHECKS_OFF; ++ ++ FREE(buff); ++ return 0; ++} ++ ++static int ++mp_delay_wait_checks_handler(vector strvec) ++{ ++ struct mpentry *mpe = VECTOR_LAST_SLOT(conf->mptable); ++ char * buff; ++ ++ if (!mpe) ++ return 1; ++ ++ buff = set_value(strvec); ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ mpe->delay_wait_checks = DELAY_CHECKS_OFF; ++ else if ((mpe->delay_wait_checks = atoi(buff)) < 1) ++ mpe->delay_wait_checks = DELAY_CHECKS_OFF; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * config file keywords printing + */ +@@ -2258,6 +2388,30 @@ snprint_mp_deferred_remove (char * buff, + } + + static int ++snprint_mp_delay_watch_checks(char * buff, int len, void * data) ++{ ++ struct mpentry * mpe = (struct mpentry *)data; ++ ++ if (mpe->delay_watch_checks == DELAY_CHECKS_UNDEF) ++ return 0; ++ if (mpe->delay_watch_checks == DELAY_CHECKS_OFF) ++ return snprintf(buff, len, "no"); ++ return snprintf(buff, len, "%d", mpe->delay_watch_checks); ++} ++ ++static int ++snprint_mp_delay_wait_checks(char * buff, int len, void * data) ++{ ++ struct mpentry * mpe = (struct mpentry *)data; ++ ++ if (mpe->delay_wait_checks == DELAY_CHECKS_UNDEF) ++ return 0; ++ if (mpe->delay_wait_checks == DELAY_CHECKS_OFF) ++ return snprintf(buff, len, "no"); ++ return snprintf(buff, len, "%d", mpe->delay_wait_checks); ++} ++ ++static int + snprint_hw_fast_io_fail(char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -2586,6 +2740,30 @@ snprint_hw_deferred_remove(char * buff, + } + + static int ++snprint_hw_delay_watch_checks(char * buff, int len, void * data) ++{ ++ struct hwentry * hwe = (struct hwentry *)data; ++ ++ if (hwe->delay_watch_checks == DELAY_CHECKS_UNDEF) ++ return 0; ++ if (hwe->delay_watch_checks == DELAY_CHECKS_OFF) ++ return snprintf(buff, len, "no"); ++ return snprintf(buff, len, "%d", hwe->delay_watch_checks); ++} ++ ++static int ++snprint_hw_delay_wait_checks(char * buff, int len, void * data) ++{ ++ struct hwentry * hwe = (struct hwentry *)data; ++ ++ if (hwe->delay_wait_checks == DELAY_CHECKS_UNDEF) ++ return 0; ++ if (hwe->delay_wait_checks == DELAY_CHECKS_OFF) ++ return snprintf(buff, len, "no"); ++ return snprintf(buff, len, "%d", hwe->delay_wait_checks); ++} ++ ++static int + snprint_detect_prio(char * buff, int len, void * data) + { + struct hwentry * hwe = (struct hwentry *)data; +@@ -2883,7 +3061,6 @@ snprint_def_find_multipaths (char * buff + return snprintf(buff, len, "yes"); + } + +- + static int + snprint_def_user_friendly_names (char * buff, int len, void * data) + { +@@ -2989,7 +3166,6 @@ snprint_def_ignore_new_boot_devs(char * + return snprintf(buff, len, "no"); + } + +- + static int + snprint_def_config_dir (char * buff, int len, void * data) + { +@@ -3000,6 +3176,24 @@ snprint_def_config_dir (char * buff, int + } + + static int ++snprint_def_delay_watch_checks(char * buff, int len, void * data) ++{ ++ if (conf->delay_watch_checks == DELAY_CHECKS_UNDEF || ++ conf->delay_watch_checks == DELAY_CHECKS_OFF) ++ return snprintf(buff, len, "no"); ++ return snprintf(buff, len, "%d", conf->delay_watch_checks); ++} ++ ++static int ++snprint_def_delay_wait_checks(char * buff, int len, void * data) ++{ ++ if (conf->delay_wait_checks == DELAY_CHECKS_UNDEF || ++ conf->delay_wait_checks == DELAY_CHECKS_OFF) ++ return snprintf(buff, len, "no"); ++ return snprintf(buff, len, "%d", conf->delay_wait_checks); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -3071,6 +3265,8 @@ init_keywords(void) + install_keyword("deferred_remove", &def_deferred_remove_handler, &snprint_def_deferred_remove); + install_keyword("ignore_new_boot_devs", &def_ignore_new_boot_devs_handler, &snprint_def_ignore_new_boot_devs); + install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir); ++ install_keyword("delay_watch_checks", &def_delay_watch_checks_handler, &snprint_def_delay_watch_checks); ++ install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +@@ -3136,6 +3332,8 @@ init_keywords(void) + install_keyword("retain_attached_hw_handler", &hw_retain_hwhandler_handler, &snprint_hw_retain_hwhandler_handler); + install_keyword("detect_prio", &hw_detect_prio_handler, &snprint_detect_prio); + install_keyword("deferred_remove", &hw_deferred_remove_handler, &snprint_hw_deferred_remove); ++ install_keyword("delay_watch_checks", &hw_delay_watch_checks_handler, &snprint_hw_delay_watch_checks); ++ install_keyword("delay_wait_checks", &hw_delay_wait_checks_handler, &snprint_hw_delay_wait_checks); + install_sublevel_end(); + + install_keyword_root("multipaths", &multipaths_handler); +@@ -3161,5 +3359,7 @@ init_keywords(void) + install_keyword("reservation_key", &mp_reservation_key_handler, &snprint_mp_reservation_key); + install_keyword("user_friendly_names", &mp_names_handler, &snprint_mp_user_friendly_names); + install_keyword("deferred_remove", &mp_deferred_remove_handler, &snprint_mp_deferred_remove); ++ install_keyword("delay_watch_checks", &mp_delay_watch_checks_handler, &snprint_mp_delay_watch_checks); ++ install_keyword("delay_wait_checks", &mp_delay_wait_checks_handler, &snprint_mp_delay_wait_checks); + install_sublevel_end(); + } +Index: multipath-tools-130222/libmultipath/print.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/print.c ++++ multipath-tools-130222/libmultipath/print.c +@@ -336,6 +336,8 @@ snprint_chk_state (char * buff, size_t l + return snprintf(buff, len, "shaky"); + case PATH_GHOST: + return snprintf(buff, len, "ghost"); ++ case PATH_DELAYED: ++ return snprintf(buff, len, "delayed"); + default: + return snprintf(buff, len, "undef"); + } +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -788,3 +788,55 @@ select_detect_prio (struct path * pp) + condlog(3, "%s: detect_prio = %d (compiled in default)", pp->dev, pp->detect_prio); + return 0; + } ++ ++extern int ++select_delay_watch_checks (struct multipath * mp) ++{ ++ if (mp->mpe && mp->mpe->delay_watch_checks != DELAY_CHECKS_UNDEF) { ++ mp->delay_watch_checks = mp->mpe->delay_watch_checks; ++ condlog(3, "delay_watch_checks = %i (multipath setting)", ++ mp->delay_watch_checks); ++ return 0; ++ } ++ if (mp->hwe && mp->hwe->delay_watch_checks != DELAY_CHECKS_UNDEF) { ++ mp->delay_watch_checks = mp->hwe->delay_watch_checks; ++ condlog(3, "delay_watch_checks = %i (controler setting)", ++ mp->delay_watch_checks); ++ return 0; ++ } ++ if (conf->delay_watch_checks != DELAY_CHECKS_UNDEF) { ++ mp->delay_watch_checks = conf->delay_watch_checks; ++ condlog(3, "delay_watch_checks = %i (config file default)", ++ mp->delay_watch_checks); ++ return 0; ++ } ++ mp->delay_watch_checks = DEFAULT_DELAY_CHECKS; ++ condlog(3, "delay_watch_checks = DISABLED (internal default)"); ++ return 0; ++} ++ ++extern int ++select_delay_wait_checks (struct multipath * mp) ++{ ++ if (mp->mpe && mp->mpe->delay_wait_checks != DELAY_CHECKS_UNDEF) { ++ mp->delay_wait_checks = mp->mpe->delay_wait_checks; ++ condlog(3, "delay_wait_checks = %i (multipath setting)", ++ mp->delay_wait_checks); ++ return 0; ++ } ++ if (mp->hwe && mp->hwe->delay_wait_checks != DELAY_CHECKS_UNDEF) { ++ mp->delay_wait_checks = mp->hwe->delay_wait_checks; ++ condlog(3, "delay_wait_checks = %i (controler setting)", ++ mp->delay_wait_checks); ++ return 0; ++ } ++ if (conf->delay_wait_checks != DELAY_CHECKS_UNDEF) { ++ mp->delay_wait_checks = conf->delay_wait_checks; ++ condlog(3, "delay_wait_checks = %i (config file default)", ++ mp->delay_wait_checks); ++ return 0; ++ } ++ mp->delay_wait_checks = DEFAULT_DELAY_CHECKS; ++ condlog(3, "delay_wait_checks = DISABLED (internal default)"); ++ return 0; ++} +Index: multipath-tools-130222/libmultipath/propsel.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.h ++++ multipath-tools-130222/libmultipath/propsel.h +@@ -21,3 +21,5 @@ int select_reservation_key(struct multip + int select_retain_hwhandler (struct multipath * mp); + int select_detect_prio(struct path * pp); + int select_deferred_remove(struct multipath *mp); ++int select_delay_watch_checks (struct multipath * mp); ++int select_delay_wait_checks (struct multipath * mp); +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -188,7 +188,8 @@ sync_map_state(struct multipath *mpp) + vector_foreach_slot (mpp->pg, pgp, i){ + vector_foreach_slot (pgp->paths, pp, j){ + if (pp->state == PATH_UNCHECKED || +- pp->state == PATH_WILD) ++ pp->state == PATH_WILD || ++ pp->state == PATH_DELAYED) + continue; + if ((pp->dmstate == PSTATE_FAILED || + pp->dmstate == PSTATE_UNDEF) && +@@ -1165,6 +1166,16 @@ check_path (struct vectors * vecs, struc + if (!pp->mpp) + return; + ++ if ((newstate == PATH_UP || newstate == PATH_GHOST) && ++ pp->wait_checks > 0) { ++ if (pp->mpp && pp->mpp->nr_active > 0) { ++ pp->state = PATH_DELAYED; ++ pp->wait_checks--; ++ return; ++ } else ++ pp->wait_checks = 0; ++ } ++ + pp->chkrstate = newstate; + if (newstate != pp->state) { + int oldstate = pp->state; +@@ -1182,9 +1193,14 @@ check_path (struct vectors * vecs, struc + * proactively fail path in the DM + */ + if (oldstate == PATH_UP || +- oldstate == PATH_GHOST) ++ oldstate == PATH_GHOST) { + fail_path(pp, 1); +- else ++ if (pp->mpp->delay_wait_checks > 0 && ++ pp->watch_checks > 0) { ++ pp->wait_checks = pp->mpp->delay_wait_checks; ++ pp->watch_checks = 0; ++ } ++ }else + fail_path(pp, 0); + + /* +@@ -1211,11 +1227,15 @@ check_path (struct vectors * vecs, struc + * reinstate this path + */ + if (oldstate != PATH_UP && +- oldstate != PATH_GHOST) ++ oldstate != PATH_GHOST) { ++ if (pp->mpp->delay_watch_checks > 0) ++ pp->watch_checks = pp->mpp->delay_watch_checks; + reinstate_path(pp, 1); +- else ++ } else { ++ if (pp->watch_checks > 0) ++ pp->watch_checks--; + reinstate_path(pp, 0); +- ++ } + new_path_up = 1; + + if (oldchkrstate != PATH_UP && oldchkrstate != PATH_GHOST) +@@ -1245,6 +1265,8 @@ check_path (struct vectors * vecs, struc + else + pp->checkint = conf->max_checkint; + } ++ if (pp->watch_checks > 0) ++ pp->watch_checks--; + pp->tick = pp->checkint; + condlog(4, "%s: delay next check %is", + pp->dev_t, pp->tick); +Index: multipath-tools-130222/multipath.conf.annotated +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.annotated ++++ multipath-tools-130222/multipath.conf.annotated +@@ -242,6 +242,30 @@ + # # files, just as if it was in /etc/multipath.conf + # # values : "" or a fully qualified pathname + # # default : "/etc/multipath/conf.d" ++# ++# # ++# # name : delay_watch_checks ++# # scope : multipathd ++# # desc : If set to a value greater than 0, multipathd will watch ++# # paths that have recently become valid for this many ++# # checks. If they fail again while they are being watched, ++# # when they next become valid, they will not be used until ++# # they have stayed up for delay_wait_checks checks. ++# # values : no| > 0 ++# # default : no ++# delay_watch_checks 12 ++# ++# # ++# # name : delay_wait_checks ++# # scope : multipathd ++# # desc : If set to a value greater than 0, when a device that has ++# # recently come back online fails again within ++# # delay_watch_checks checks, the next time it comes back ++# # online, it will marked and delayed, and not used until ++# # it has passed delay_wait_checks checks. ++# # values : no| > 0 ++# # default : no ++# delay_wait_checks 12 + #} + # + ## +@@ -383,6 +407,13 @@ + # # + # flush_on_last_del yes + # ++# # ++# # name : delay_watch_checks ++# # See defualts section for information. ++# ++# # ++# # name : delay_wait_checks ++# # See defualts section for information. + # } + # multipath { + # wwid 1DEC_____321816758474 +@@ -566,6 +597,15 @@ + # # before removing it from the system. + # # values : n > 0 + # dev_loss_tmo 600 ++# ++# # ++# # name : delay_watch_checks ++# # See defaults section for information. ++# ++# # ++# # name : delay_wait_checks ++# # See defaults section for information. ++# + # } + # device { + # vendor "COMPAQ " +Index: multipath-tools-130222/multipath.conf.defaults +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.defaults ++++ multipath-tools-130222/multipath.conf.defaults +@@ -27,6 +27,8 @@ + # retain_attached_hw_handler no + # detect_prio no + # config_dir "/etc/multipath/conf.d" ++# delay_watch_checks no ++# delay_wait_checks no + #} + #blacklist { + # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -459,6 +459,25 @@ alphabetically for file ending in ".conf + information from them, just as if it was in /etc/multipath.conf. config_dir + must either be "" or a fully qualified directory name. Default is + .I "/etc/multipath/conf.d" ++.TP ++.B delay_watch_checks ++If set to a value greater than 0, multipathd will watch paths that have ++recently become valid for this many checks. If they fail again while they are ++being watched, when they next become valid, they will not be used until they ++have stayed up for ++.I delay_wait_checks ++checks. Default is ++.I no ++.TP ++.B delay_wait_checks ++If set to a value greater than 0, when a device that has recently come back ++online fails again within ++.I delay_watch_checks ++checks, the next time it comes back online, it will marked and delayed, and not ++used until it has passed ++.I delay_wait_checks ++checks. Default is ++.I no + . + .SH "blacklist section" + The +@@ -562,6 +581,10 @@ section: + .B reservation_key + .TP + .B deferred_remove ++.TP ++.B delay_watch_checks ++.TP ++.B delay_wait_checks + .RE + .PD + .LP +@@ -654,6 +677,10 @@ section: + .B detect_prio + .TP + .B deferred_remove ++.TP ++.B delay_watch_checks ++.TP ++.B delay_wait_checks + .RE + .PD + .LP +Index: multipath-tools-130222/libmultipath/checkers.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/checkers.c ++++ multipath-tools-130222/libmultipath/checkers.c +@@ -16,7 +16,8 @@ char *checker_state_names[] = { + "up", + "shaky", + "ghost", +- "pending" ++ "pending", ++ "delayed" + }; + + static LIST_HEAD(checkers); +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -341,6 +341,8 @@ merge_hwe (struct hwentry * dst, struct + merge_num(retain_hwhandler); + merge_num(detect_prio); + merge_num(deferred_remove); ++ merge_num(delay_watch_checks); ++ merge_num(delay_wait_checks); + + /* + * Make sure features is consistent with +@@ -399,6 +401,8 @@ overwrite_hwe (struct hwentry * dst, str + overwrite_num(retain_hwhandler); + overwrite_num(detect_prio); + overwrite_num(deferred_remove); ++ overwrite_num(delay_watch_checks); ++ overwrite_num(delay_wait_checks); + + /* + * Make sure features is consistent with diff --git a/SOURCES/0115-RHBZ-1198418-fix-double-free.patch b/SOURCES/0115-RHBZ-1198418-fix-double-free.patch new file mode 100644 index 0000000..a403760 --- /dev/null +++ b/SOURCES/0115-RHBZ-1198418-fix-double-free.patch @@ -0,0 +1,28 @@ +--- + multipathd/main.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -310,10 +310,15 @@ ev_add_map (char * dev, char * alias, st + /* + * now we can register the map + */ +- if (map_present && (mpp = add_map_without_path(vecs, alias))) { +- sync_map_state(mpp); +- condlog(2, "%s: devmap %s registered", alias, dev); +- return 0; ++ if (map_present) { ++ if ((mpp = add_map_without_path(vecs, alias))) { ++ sync_map_state(mpp); ++ condlog(2, "%s: devmap %s registered", alias, dev); ++ return 0; ++ } else { ++ condlog(2, "%s: uev_add_map failed", dev); ++ return 1; ++ } + } + r = get_refwwid(dev, DEV_DEVMAP, vecs->pathvec, &refwwid); + diff --git a/SOURCES/0116-UPBZ-1188179-dell-36xxi.patch b/SOURCES/0116-UPBZ-1188179-dell-36xxi.patch new file mode 100644 index 0000000..e32118b --- /dev/null +++ b/SOURCES/0116-UPBZ-1188179-dell-36xxi.patch @@ -0,0 +1,83 @@ +--- + libmultipath/hwtable.c | 30 ++++++++++++++++++++++++++++++ + multipath.conf.defaults | 26 ++++++++++++++++++++++++++ + 2 files changed, 56 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -772,6 +772,36 @@ static struct hwentry default_hw[] = { + .prio_name = PRIO_RDAC, + .prio_args = NULL, + }, ++ { ++ /* DELL MD36xxi */ ++ .vendor = "DELL", ++ .product = "MD36xxi", ++ .bl_product = "Universal Xport", ++ .features = "2 pg_init_retries 50", ++ .hwhandler = "1 rdac", ++ .pgpolicy = GROUP_BY_PRIO, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .rr_weight = RR_WEIGHT_NONE, ++ .no_path_retry = 15, ++ .checker_name = RDAC, ++ .prio_name = PRIO_RDAC, ++ .prio_args = NULL, ++ }, ++ { ++ /* DELL MD36xxf */ ++ .vendor = "DELL", ++ .product = "MD36xxf", ++ .bl_product = "Universal Xport", ++ .features = "2 pg_init_retries 50", ++ .hwhandler = "1 rdac", ++ .pgpolicy = GROUP_BY_PRIO, ++ .pgfailback = -FAILBACK_IMMEDIATE, ++ .rr_weight = RR_WEIGHT_NONE, ++ .no_path_retry = 15, ++ .checker_name = RDAC, ++ .prio_name = PRIO_RDAC, ++ .prio_args = NULL, ++ }, + /* + * NETAPP controller family + * +Index: multipath-tools-130222/multipath.conf.defaults +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.defaults ++++ multipath-tools-130222/multipath.conf.defaults +@@ -655,6 +655,32 @@ + # no_path_retry 15 + # } + # device { ++# vendor "DELL" ++# product "MD36xxi" ++# product_blacklist "Universal Xport" ++# path_grouping_policy "group_by_prio" ++# path_checker "rdac" ++# features "2 pg_init_retries 50" ++# hardware_handler "1 rdac" ++# prio "rdac" ++# failback "immediate" ++# rr_weight "uniform" ++# no_path_retry 15 ++# } ++# device { ++# vendor "DELL" ++# product "MD36xxf" ++# product_blacklist "Universal Xport" ++# path_grouping_policy "group_by_prio" ++# path_checker "rdac" ++# features "2 pg_init_retries 50" ++# hardware_handler "1 rdac" ++# prio "rdac" ++# failback "immediate" ++# rr_weight "uniform" ++# no_path_retry 15 ++# } ++# device { + # vendor "NETAPP" + # product "LUN.*" + # path_grouping_policy "group_by_prio" diff --git a/SOURCES/0117-RHBZ-1198424-autodetect-clariion-alua.patch b/SOURCES/0117-RHBZ-1198424-autodetect-clariion-alua.patch new file mode 100644 index 0000000..64a302d --- /dev/null +++ b/SOURCES/0117-RHBZ-1198424-autodetect-clariion-alua.patch @@ -0,0 +1,31 @@ +--- + libmultipath/hwtable.c | 2 ++ + multipath.conf.defaults | 2 ++ + 2 files changed, 4 insertions(+) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -272,6 +272,8 @@ static struct hwentry default_hw[] = { + .checker_name = EMC_CLARIION, + .prio_name = PRIO_EMC, + .prio_args = NULL, ++ .retain_hwhandler = RETAIN_HWHANDLER_ON, ++ .detect_prio = DETECT_PRIO_ON, + }, + { + .vendor = "EMC", +Index: multipath-tools-130222/multipath.conf.defaults +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.defaults ++++ multipath-tools-130222/multipath.conf.defaults +@@ -261,6 +261,8 @@ + # failback immediate + # rr_weight "uniform" + # no_path_retry 60 ++# retain_attached_hw_handler yes ++# detect_prio yes + # } + # device { + # vendor "EMC" diff --git a/SOURCES/0118-UPBZ-1200738-update-eternus-config.patch b/SOURCES/0118-UPBZ-1200738-update-eternus-config.patch new file mode 100644 index 0000000..10e96e3 --- /dev/null +++ b/SOURCES/0118-UPBZ-1200738-update-eternus-config.patch @@ -0,0 +1,31 @@ +--- + libmultipath/hwtable.c | 2 +- + multipath.conf.defaults | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/libmultipath/hwtable.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/hwtable.c ++++ multipath-tools-130222/libmultipath/hwtable.c +@@ -310,7 +310,7 @@ static struct hwentry default_hw[] = { + }, + { + .vendor = "FUJITSU", +- .product = "ETERNUS_DX(L|400|8000)", ++ .product = "ETERNUS_DX(H|L|M|400|8000)", + .features = "1 queue_if_no_path", + .hwhandler = DEFAULT_HWHANDLER, + .pgpolicy = GROUP_BY_PRIO, +Index: multipath-tools-130222/multipath.conf.defaults +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.defaults ++++ multipath-tools-130222/multipath.conf.defaults +@@ -288,7 +288,7 @@ + # } + # device { + # vendor "FUJITSU" +-# product "ETERNUS_DX(L|400|8000)" ++# product "ETERNUS_DX(H|L|M|400|8000)" + # path_grouping_policy "group_by_prio" + # path_checker "tur" + # features "1 queue_if_no_path" diff --git a/SOURCES/0119-RHBZ-1081397-save-alua-info.patch b/SOURCES/0119-RHBZ-1081397-save-alua-info.patch new file mode 100644 index 0000000..c9913f3 --- /dev/null +++ b/SOURCES/0119-RHBZ-1081397-save-alua-info.patch @@ -0,0 +1,565 @@ +--- + libmultipath/prio.c | 34 ++++++++++++++++- + libmultipath/prio.h | 7 +++ + libmultipath/prioritizers/alua.c | 62 +++++++++++++++++++++++-------- + libmultipath/prioritizers/alua_rtpg.c | 22 +++++++++-- + libmultipath/prioritizers/alua_rtpg.h | 4 +- + libmultipath/prioritizers/const.c | 4 ++ + libmultipath/prioritizers/datacore.c | 3 + + libmultipath/prioritizers/def_func.h | 11 +++++ + libmultipath/prioritizers/emc.c | 4 ++ + libmultipath/prioritizers/hds.c | 4 ++ + libmultipath/prioritizers/hp_sw.c | 4 ++ + libmultipath/prioritizers/iet.c | 4 ++ + libmultipath/prioritizers/ontap.c | 4 ++ + libmultipath/prioritizers/random.c | 4 ++ + libmultipath/prioritizers/rdac.c | 4 ++ + libmultipath/prioritizers/weightedpath.c | 3 + + libmultipath/propsel.c | 4 +- + multipathd/main.c | 24 ++++++++---- + 18 files changed, 174 insertions(+), 32 deletions(-) + +Index: multipath-tools-130222/libmultipath/prio.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prio.c ++++ multipath-tools-130222/libmultipath/prio.c +@@ -112,9 +112,24 @@ struct prio * add_prio (char * name) + p->getprio = (int (*)(struct path *, char *)) dlsym(p->handle, "getprio"); + errstr = dlerror(); + if (errstr != NULL) +- condlog(0, "A dynamic linking error occurred: (%s)", errstr); ++ condlog(0, "A dynamic linking error occurred with getprio: (%s)", errstr); + if (!p->getprio) + goto out; ++ ++ p->initprio = (int (*)(struct prio *)) dlsym(p->handle, "initprio"); ++ errstr = dlerror(); ++ if (errstr != NULL) ++ condlog(0, "A dynamic linking error occurred with initprio: (%s)", errstr); ++ if (!p->initprio) ++ goto out; ++ ++ p->freeprio = (int (*)(struct prio *)) dlsym(p->handle, "freeprio"); ++ errstr = dlerror(); ++ if (errstr != NULL) ++ condlog(0, "A dynamic linking error occurred with freeprio: (%s)", errstr); ++ if (!p->freeprio) ++ goto out; ++ + list_add(&p->node, &prioritizers); + return p; + out: +@@ -122,6 +137,13 @@ out: + return NULL; + } + ++int prio_init (struct prio * p) ++{ ++ if (!p || !p->initprio) ++ return 1; ++ return p->initprio(p); ++} ++ + int prio_getprio (struct prio * p, struct path * pp) + { + return p->getprio(pp, p->args); +@@ -156,8 +178,16 @@ void prio_get (struct prio * dst, char * + strncpy(dst->name, src->name, PRIO_NAME_LEN); + if (args) + strncpy(dst->args, args, PRIO_ARGS_LEN); ++ dst->initprio = src->initprio; + dst->getprio = src->getprio; ++ dst->freeprio = src->freeprio; + dst->handle = NULL; ++ dst->context = NULL; ++ ++ if (dst->initprio(dst) != 0){ ++ memset(dst, 0x0, sizeof(struct prio)); ++ return; ++ } + + src->refcount++; + } +@@ -173,6 +203,8 @@ void prio_put (struct prio * dst) + src = NULL; + else + src = prio_lookup(dst->name); ++ if (dst->freeprio) ++ dst->freeprio(dst); + memset(dst, 0x0, sizeof(struct prio)); + free_prio(src); + } +Index: multipath-tools-130222/libmultipath/prio.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prio.h ++++ multipath-tools-130222/libmultipath/prio.h +@@ -46,9 +46,15 @@ struct prio { + void *handle; + int refcount; + struct list_head node; ++ void * context; + char name[PRIO_NAME_LEN]; + char args[PRIO_ARGS_LEN]; ++ int (*initprio)(struct prio * p); ++ /* You are allowed to call initprio multiple times without calling ++ * freeprio. Doing so will reinitialize it (possibly skipping ++ * allocations) */ + int (*getprio)(struct path *, char *); ++ int (*freeprio)(struct prio * p); + }; + + unsigned int get_prio_timeout(unsigned int default_timeout); +@@ -57,6 +63,7 @@ void cleanup_prio (void); + struct prio * add_prio (char *); + struct prio * prio_lookup (char *); + int prio_getprio (struct prio *, struct path *); ++int prio_init (struct prio *); + void prio_get (struct prio *, char *, char *); + void prio_put (struct prio *); + int prio_selected (struct prio *); +Index: multipath-tools-130222/libmultipath/prioritizers/alua.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua.c ++++ multipath-tools-130222/libmultipath/prioritizers/alua.c +@@ -37,6 +37,12 @@ static const char * aas_string[] = { + [AAS_TRANSITIONING] = "transitioning between states", + }; + ++struct alua_context { ++ int tpg_support; ++ int tpg; ++ int buflen; ++}; ++ + static const char *aas_print_string(int rc) + { + rc &= 0x7f; +@@ -51,25 +57,26 @@ static const char *aas_print_string(int + } + + int +-get_alua_info(int fd) ++get_alua_info(int fd, struct alua_context *ct) + { + int rc; +- int tpg; + int aas; + +- rc = get_target_port_group_support(fd); +- if (rc < 0) +- return -ALUA_PRIO_TPGS_FAILED; +- +- if (rc == TPGS_NONE) +- return -ALUA_PRIO_NOT_SUPPORTED; +- +- tpg = get_target_port_group(fd); +- if (tpg < 0) +- return -ALUA_PRIO_RTPG_FAILED; ++ if (ct->tpg_support <= 0 || ct->tpg < 0) { ++ ct->tpg_support = get_target_port_group_support(fd); ++ if (ct->tpg_support < 0) ++ return -ALUA_PRIO_TPGS_FAILED; ++ ++ if (ct->tpg_support == TPGS_NONE) ++ return -ALUA_PRIO_NOT_SUPPORTED; ++ ++ ct->tpg = get_target_port_group(fd, &ct->buflen); ++ if (ct->tpg < 0) ++ return -ALUA_PRIO_RTPG_FAILED; ++ } + +- condlog(3, "reported target port group is %i", tpg); +- rc = get_asymmetric_access_state(fd, tpg); ++ condlog(3, "reported target port group is %i", ct->tpg); ++ rc = get_asymmetric_access_state(fd, ct->tpg, &ct->buflen); + if (rc < 0) + return -ALUA_PRIO_GETAAS_FAILED; + aas = (rc & 0x0f); +@@ -88,7 +95,7 @@ int getprio (struct path * pp, char * ar + if (pp->fd < 0) + return -ALUA_PRIO_NO_INFORMATION; + +- rc = get_alua_info(pp->fd); ++ rc = get_alua_info(pp->fd, pp->prio.context); + if (rc >= 0) { + aas = (rc & 0x0f); + priopath = (rc & 0x80); +@@ -128,3 +135,28 @@ int getprio (struct path * pp, char * ar + } + return rc; + } ++ ++int initprio(struct prio *p) ++{ ++ if (!p->context) { ++ struct alua_context *ct; ++ ++ ct = malloc(sizeof(struct alua_context)); ++ if (!ct) ++ return 1; ++ p->context = ct; ++ } ++ memset(p->context, 0, sizeof(struct alua_context)); ++ return 0; ++} ++ ++ ++int freeprio(struct prio *p) ++{ ++ if (p->context) { ++ free(p->context); ++ p->context = NULL; ++ } ++ return 0; ++} ++ +Index: multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua_rtpg.c ++++ multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.c +@@ -171,7 +171,7 @@ get_target_port_group_support(int fd) + } + + int +-get_target_port_group(int fd) ++get_target_port_group(int fd, int *buflen_ptr) + { + unsigned char *buf; + struct vpd83_data * vpd83; +@@ -179,7 +179,12 @@ get_target_port_group(int fd) + int rc; + int buflen, scsi_buflen; + +- buflen = 128; /* Lets start from 128 */ ++ if (!buflen_ptr || *buflen_ptr == 0) { ++ buflen = 128; /* Lets start from 128 */ ++ if (buflen_ptr) ++ *buflen_ptr = 128; ++ } else ++ buflen = *buflen_ptr; + buf = (unsigned char *)malloc(buflen); + if (!buf) { + PRINT_DEBUG("malloc failed: could not allocate" +@@ -202,6 +207,8 @@ get_target_port_group(int fd) + return -RTPG_RTPG_FAILED; + } + buflen = scsi_buflen; ++ if (buflen_ptr) ++ *buflen_ptr = buflen; + memset(buf, 0, buflen); + rc = do_inquiry(fd, 1, 0x83, buf, buflen); + if (rc < 0) +@@ -269,7 +276,7 @@ do_rtpg(int fd, void* resp, long resplen + } + + int +-get_asymmetric_access_state(int fd, unsigned int tpg) ++get_asymmetric_access_state(int fd, unsigned int tpg, int *buflen_ptr) + { + unsigned char *buf; + struct rtpg_data * tpgd; +@@ -278,7 +285,12 @@ get_asymmetric_access_state(int fd, unsi + int buflen; + uint32_t scsi_buflen; + +- buflen = 128; /* Initial value from old code */ ++ if (!buflen_ptr || *buflen_ptr == 0) { ++ buflen = 128; /* Initial value from old code */ ++ if (buflen_ptr) ++ *buflen_ptr = 128; ++ } else ++ buflen = *buflen_ptr; + buf = (unsigned char *)malloc(buflen); + if (!buf) { + PRINT_DEBUG ("malloc failed: could not allocate" +@@ -299,6 +311,8 @@ get_asymmetric_access_state(int fd, unsi + return -RTPG_RTPG_FAILED; + } + buflen = scsi_buflen; ++ if (buflen_ptr) ++ *buflen_ptr = buflen; + memset(buf, 0, buflen); + rc = do_rtpg(fd, buf, buflen); + if (rc < 0) +Index: multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/alua_rtpg.h ++++ multipath-tools-130222/libmultipath/prioritizers/alua_rtpg.h +@@ -23,8 +23,8 @@ + #define RTPG_TPG_NOT_FOUND 4 + + int get_target_port_group_support(int fd); +-int get_target_port_group(int fd); +-int get_asymmetric_access_state(int fd, unsigned int tpg); ++int get_target_port_group(int fd, int *buflen_ptr); ++int get_asymmetric_access_state(int fd, unsigned int tpg, int *buflen_ptr); + + #endif /* __RTPG_H__ */ + +Index: multipath-tools-130222/libmultipath/prioritizers/const.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/const.c ++++ multipath-tools-130222/libmultipath/prioritizers/const.c +@@ -1,8 +1,12 @@ + #include + + #include ++#include "def_func.h" + + int getprio (struct path * pp, char * args) + { + return 1; + } ++ ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/prioritizers/datacore.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/datacore.c ++++ multipath-tools-130222/libmultipath/prioritizers/datacore.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include "def_func.h" + + #define INQ_REPLY_LEN 255 + #define INQ_CMD_CODE 0x12 +@@ -111,3 +112,5 @@ int getprio (struct path * pp, char * ar + return datacore_prio(pp->dev, pp->fd, args); + } + ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/prioritizers/def_func.h +=================================================================== +--- /dev/null ++++ multipath-tools-130222/libmultipath/prioritizers/def_func.h +@@ -0,0 +1,11 @@ ++#ifndef _DEF_FUNC_H ++#define _DEF_FUNC_H ++ ++#include "prio.h" ++ ++#define declare_nop_prio(name) \ ++int name (struct prio *p) \ ++{ \ ++ return 0; \ ++} ++#endif /* _DEF_FUNC_H */ +Index: multipath-tools-130222/libmultipath/prioritizers/emc.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/emc.c ++++ multipath-tools-130222/libmultipath/prioritizers/emc.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include "def_func.h" + + #define INQUIRY_CMD 0x12 + #define INQUIRY_CMDLEN 6 +@@ -85,3 +86,6 @@ int getprio (struct path * pp, char * ar + { + return emc_clariion_prio(pp->dev, pp->fd); + } ++ ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/prioritizers/hds.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/hds.c ++++ multipath-tools-130222/libmultipath/prioritizers/hds.c +@@ -76,6 +76,7 @@ + #include + #include + #include ++#include "def_func.h" + + #define INQ_REPLY_LEN 255 + #define INQ_CMD_CODE 0x12 +@@ -170,3 +171,6 @@ int getprio (struct path * pp, char * ar + { + return hds_modular_prio(pp->dev, pp->fd); + } ++ ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/prioritizers/hp_sw.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/hp_sw.c ++++ multipath-tools-130222/libmultipath/prioritizers/hp_sw.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include "def_func.h" + + #define TUR_CMD_LEN 6 + #define SCSI_CHECK_CONDITION 0x2 +@@ -99,3 +100,6 @@ int getprio (struct path * pp, char * ar + { + return hp_sw_prio(pp->dev, pp->fd); + } ++ ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/prioritizers/iet.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/iet.c ++++ multipath-tools-130222/libmultipath/prioritizers/iet.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include "def_func.h" + + // + // This prioritizer suits iSCSI needs, makes it possible to prefer one path. +@@ -141,3 +142,6 @@ int getprio(struct path * pp, char * arg + { + return iet_prio(pp->dev, args); + } ++ ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/prioritizers/ontap.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/ontap.c ++++ multipath-tools-130222/libmultipath/prioritizers/ontap.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include "def_func.h" + + #define INQUIRY_CMD 0x12 + #define INQUIRY_CMDLEN 6 +@@ -245,3 +246,6 @@ int getprio (struct path * pp, char * ar + { + return ontap_prio(pp->dev, pp->fd); + } ++ ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/prioritizers/random.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/random.c ++++ multipath-tools-130222/libmultipath/prioritizers/random.c +@@ -4,6 +4,7 @@ + #include + + #include ++#include "def_func.h" + + int getprio (struct path * pp, char * args) + { +@@ -13,3 +14,6 @@ int getprio (struct path * pp, char * ar + srand((unsigned int)tv.tv_usec); + return 1+(int) (10.0*rand()/(RAND_MAX+1.0)); + } ++ ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/prioritizers/rdac.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/rdac.c ++++ multipath-tools-130222/libmultipath/prioritizers/rdac.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include "def_func.h" + + #define INQUIRY_CMD 0x12 + #define INQUIRY_CMDLEN 6 +@@ -95,3 +96,6 @@ int getprio (struct path * pp, char * ar + { + return rdac_prio(pp->dev, pp->fd); + } ++ ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/prioritizers/weightedpath.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/prioritizers/weightedpath.c ++++ multipath-tools-130222/libmultipath/prioritizers/weightedpath.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include "def_func.h" + + char *get_next_string(char **temp, char *split_char) + { +@@ -104,3 +105,5 @@ int getprio(struct path *pp, char *args) + return prio_path_weight(pp, args); + } + ++declare_nop_prio(initprio) ++declare_nop_prio(freeprio) +Index: multipath-tools-130222/libmultipath/propsel.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/propsel.c ++++ multipath-tools-130222/libmultipath/propsel.c +@@ -401,10 +401,10 @@ detect_prio(struct path * pp) + + if (get_target_port_group_support(pp->fd) <= 0) + return; +- ret = get_target_port_group(pp->fd); ++ ret = get_target_port_group(pp->fd, NULL); + if (ret < 0) + return; +- if (get_asymmetric_access_state(pp->fd, ret) < 0) ++ if (get_asymmetric_access_state(pp->fd, ret, NULL) < 0) + return; + prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS); + } +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -700,20 +700,23 @@ static int + uev_update_path (struct uevent *uev, struct vectors * vecs) + { + int ro, retval = 0; ++ struct path * pp; ++ ++ pp = find_path_by_dev(vecs->pathvec, uev->kernel); ++ if (!pp) { ++ condlog(0, "%s: spurious uevent, path not found", ++ uev->kernel); ++ return 1; ++ } ++ /* reinit the prio values on change event, in case something is ++ * different */ ++ prio_init(&pp->prio); + + ro = uevent_get_disk_ro(uev); + + if (ro >= 0) { +- struct path * pp; +- + condlog(2, "%s: update path write_protect to '%d' (uevent)", + uev->kernel, ro); +- pp = find_path_by_dev(vecs->pathvec, uev->kernel); +- if (!pp) { +- condlog(0, "%s: spurious uevent, path not found", +- uev->kernel); +- return 1; +- } + if (pp->mpp) { + retval = reload_map(vecs, pp->mpp, 0); + +@@ -1218,6 +1221,11 @@ check_path (struct vectors * vecs, struc + } + + if(newstate == PATH_UP || newstate == PATH_GHOST){ ++ /* ++ * Reinitialize the prioritizer, in case something ++ * changed. ++ */ ++ prio_init(&pp->prio); + if ( pp->mpp && pp->mpp->prflag ){ + /* + * Check Persistent Reservation. diff --git a/SOURCES/0120-RHBZ-1043093-realloc-fix.patch b/SOURCES/0120-RHBZ-1043093-realloc-fix.patch new file mode 100644 index 0000000..96b812a --- /dev/null +++ b/SOURCES/0120-RHBZ-1043093-realloc-fix.patch @@ -0,0 +1,195 @@ +--- + libmultipath/dmparser.c | 6 ++++-- + libmultipath/regex.c | 9 ++++++++- + multipath/main.c | 9 ++++++--- + multipathd/cli_handlers.c | 41 ++++++++++++----------------------------- + multipathd/uxlsnr.c | 13 ++++++++++++- + 5 files changed, 42 insertions(+), 36 deletions(-) + +Index: multipath-tools-130222/libmultipath/dmparser.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dmparser.c ++++ multipath-tools-130222/libmultipath/dmparser.c +@@ -20,14 +20,16 @@ + static int + merge_words (char ** dst, char * word, int space) + { +- char * p; ++ char * p = *dst; + int len; + + len = strlen(*dst) + strlen(word) + space; + *dst = REALLOC(*dst, len + 1); + +- if (!*dst) ++ if (!*dst) { ++ free(p); + return 1; ++ } + + p = *dst; + +Index: multipath-tools-130222/libmultipath/regex.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/regex.c ++++ multipath-tools-130222/libmultipath/regex.c +@@ -123,7 +123,14 @@ static void init_syntax_once(void) + + /* (Re)Allocate N items of type T using malloc, or fail. */ + #define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +-#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) ++#define RETALLOC(addr, n, t) \ ++do { \ ++ t *tmp = (t *) realloc (addr, (n) * sizeof (t)); \ ++ if (!tmp) \ ++ free(addr); \ ++ (addr) = tmp; \ ++} while(0) ++ + #define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) + + #define BYTEWIDTH 8 /* In bits. */ +Index: multipath-tools-130222/multipath/main.c +=================================================================== +--- multipath-tools-130222.orig/multipath/main.c ++++ multipath-tools-130222/multipath/main.c +@@ -394,7 +394,7 @@ out: + static int + dump_config (void) + { +- char * c; ++ char * c, * tmp = NULL; + char * reply; + unsigned int maxlen = 256; + int again = 1; +@@ -402,9 +402,12 @@ dump_config (void) + reply = MALLOC(maxlen); + + while (again) { +- if (!reply) ++ if (!reply) { ++ if (tmp) ++ free(tmp); + return 1; +- c = reply; ++ } ++ c = tmp = reply; + c += snprint_defaults(c, reply + maxlen - c); + again = ((c - reply) == maxlen); + if (again) { +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -26,11 +26,14 @@ + #define REALLOC_REPLY(r, a, m) \ + do { \ + if ((a)) { \ ++ char *tmp = (r); \ + (r) = REALLOC((r), (m) * 2); \ + if ((r)) { \ + memset((r) + (m), 0, (m)); \ + (m) *= 2; \ + } \ ++ else \ ++ free(tmp); \ + } \ + } while (0) + +@@ -144,7 +147,7 @@ show_config (char ** r, int * len) + unsigned int maxlen = INITIAL_REPLY_LEN; + int again = 1; + +- reply = MALLOC(maxlen); ++ c = reply = MALLOC(maxlen); + + while (again) { + if (!reply) +@@ -152,44 +155,24 @@ show_config (char ** r, int * len) + c = reply; + c += snprint_defaults(c, reply + maxlen - c); + again = ((c - reply) == maxlen); +- if (again) { +- reply = REALLOC(reply, maxlen * 2); +- if (!reply) +- return 1; +- memset(reply + maxlen, 0, maxlen); +- maxlen *= 2; ++ REALLOC_REPLY(reply, again, maxlen); ++ if (again) + continue; +- } + c += snprint_blacklist(c, reply + maxlen - c); + again = ((c - reply) == maxlen); +- if (again) { +- reply = REALLOC(reply, maxlen * 2); +- if (!reply) +- return 1; +- memset(reply + maxlen, 0, maxlen); +- maxlen *= 2; ++ REALLOC_REPLY(reply, again, maxlen); ++ if (again) + continue; +- } + c += snprint_blacklist_except(c, reply + maxlen - c); + again = ((c - reply) == maxlen); +- if (again) { +- reply = REALLOC(reply, maxlen * 2); +- if (!reply) +- return 1; +- memset(reply + maxlen, 0, maxlen); +- maxlen *= 2; ++ REALLOC_REPLY(reply, again, maxlen); ++ if (again) + continue; +- } + c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable); + again = ((c - reply) == maxlen); +- if (again) { +- reply = REALLOC(reply, maxlen * 2); +- if (!reply) +- return 1; +- memset(reply + maxlen, 0, maxlen); +- maxlen *= 2; ++ REALLOC_REPLY(reply, again, maxlen); ++ if (again) + continue; +- } + c += snprint_mptable(c, reply + maxlen - c, conf->mptable); + again = ((c - reply) == maxlen); + REALLOC_REPLY(reply, again, maxlen); +Index: multipath-tools-130222/multipathd/uxlsnr.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/uxlsnr.c ++++ multipath-tools-130222/multipathd/uxlsnr.c +@@ -64,6 +64,10 @@ static void new_client(int ux_sock) + + /* put it in our linked list */ + c = (struct client *)MALLOC(sizeof(*c)); ++ if (!c) { ++ close(fd); ++ return; ++ } + memset(c, 0, sizeof(*c)); + c->fd = fd; + c->next = clients; +@@ -124,11 +128,18 @@ void * uxsock_listen(int (*uxsock_trigge + sigdelset(&mask, SIGHUP); + sigdelset(&mask, SIGUSR1); + while (1) { ++ struct pollfd *tmp; + struct client *c; + int i, poll_count; + + /* setup for a poll */ +- polls = REALLOC(polls, (1+num_clients) * sizeof(*polls)); ++ tmp = REALLOC(polls, (1+num_clients) * sizeof(*polls)); ++ /* If we can't allocate poliing space for the new client, ++ * close it */ ++ if (!tmp) ++ dead_client(clients); ++ else ++ polls = tmp; + polls[0].fd = ux_sock; + polls[0].events = POLLIN; + diff --git a/SOURCES/0121-RHBZ-1197234-rules-fix.patch b/SOURCES/0121-RHBZ-1197234-rules-fix.patch new file mode 100644 index 0000000..41d672b --- /dev/null +++ b/SOURCES/0121-RHBZ-1197234-rules-fix.patch @@ -0,0 +1,28 @@ +--- + multipath/multipath.rules | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/multipath/multipath.rules +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.rules ++++ multipath-tools-130222/multipath/multipath.rules +@@ -21,6 +21,7 @@ ACTION!="change", GOTO="update_timestamp + IMPORT{db}="DM_MULTIPATH_TIMESTAMP" + IMPORT{db}="DM_MULTIPATH_DEVICE_PATH" + IMPORT{db}="DM_MULTIPATH_WIPE_PARTS" ++IMPORT{db}="DM_MULTIPATH_NEED_KPARTX" + # Check if the device is part of a multipath device. the -T option just keeps + # the old result if the timestamp hasn't changed. + PROGRAM=="$env{MPATH_SBIN_PATH}/multipath -T $env{DM_MULTIPATH_TIMESTAMP}:$env{DM_MULTIPATH_DEVICE_PATH} -c $env{DEVNAME}", \ +@@ -43,7 +44,10 @@ KERNEL!="dm-*", GOTO="end_mpath" + ENV{DM_UUID}=="mpath-?*|part[0-9]*-mpath-?*", OPTIONS+="link_priority=10" + ACTION!="change", GOTO="end_mpath" + ENV{DM_UUID}!="mpath-?*", GOTO="end_mpath" ++ENV{DM_ACTIVATION}=="1", ENV{DM_MULTIPATH_NEED_KPARTX}="1" + ENV{DM_SUSPENDED}=="1", GOTO="end_mpath" + ENV{DM_ACTION}=="PATH_FAILED", GOTO="end_mpath" +-ENV{DM_ACTIVATION}=="1", RUN+="$env{MPATH_SBIN_PATH}/kpartx -u $tempnode" ++ENV{DM_ACTIVATION}!="1", ENV{DM_MULTIPATH_NEED_KPARTX}!="1", GOTO="end_mpath" ++RUN+="$env{MPATH_SBIN_PATH}/kpartx -a $tempnode", \ ++ ENV{DM_MULTIPATH_NEED_KPARTX}="" + LABEL="end_mpath" diff --git a/SOURCES/0122-RHBZ-1212590-dont-use-var.patch b/SOURCES/0122-RHBZ-1212590-dont-use-var.patch new file mode 100644 index 0000000..52d743a --- /dev/null +++ b/SOURCES/0122-RHBZ-1212590-dont-use-var.patch @@ -0,0 +1,33 @@ +--- + libmultipath/defaults.h | 4 ++-- + multipathd/multipathd.service | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -26,8 +26,8 @@ + #define MAX_CHECKINT(a) (a << 2) + + #define MAX_DEV_LOSS_TMO 0x7FFFFFFF +-#define DEFAULT_PIDFILE "/var/run/multipathd/multipathd.pid" +-#define DEFAULT_TIMESTAMP_FILE "/var/run/multipathd/timestamp" ++#define DEFAULT_PIDFILE "/run/multipathd/multipathd.pid" ++#define DEFAULT_TIMESTAMP_FILE "/run/multipathd/timestamp" + #define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd" + #define DEFAULT_CONFIGFILE "/etc/multipath.conf" + #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings" +Index: multipath-tools-130222/multipathd/multipathd.service +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.service ++++ multipath-tools-130222/multipathd/multipathd.service +@@ -9,7 +9,7 @@ Conflicts=shutdown.target + + [Service] + Type=forking +-PIDFile=/var/run/multipathd/multipathd.pid ++PIDFile=/run/multipathd/multipathd.pid + ExecStartPre=/sbin/modprobe dm-multipath + ExecStartPre=-/sbin/multipath -A + ExecStart=/sbin/multipathd diff --git a/SOURCES/0123-UPBZ-1166072-fix-path-offline.patch b/SOURCES/0123-UPBZ-1166072-fix-path-offline.patch new file mode 100644 index 0000000..0f1a912 --- /dev/null +++ b/SOURCES/0123-UPBZ-1166072-fix-path-offline.patch @@ -0,0 +1,19 @@ +--- + libmultipath/discovery.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -946,9 +946,7 @@ path_offline (struct path * pp) + + condlog(3, "%s: path state = %s", pp->dev, buff); + +- if (!strncmp(buff, "offline", 7) || +- !strncmp(buff, "quiesce", 7) || +- !strncmp(buff, "transport-offline", 17)) { ++ if (!strncmp(buff, "offline", 7)) { + pp->offline = 1; + return PATH_DOWN; + } diff --git a/SOURCES/0124-RHBZ-1209275-retrigger-uevents.patch b/SOURCES/0124-RHBZ-1209275-retrigger-uevents.patch new file mode 100644 index 0000000..e0b1886 --- /dev/null +++ b/SOURCES/0124-RHBZ-1209275-retrigger-uevents.patch @@ -0,0 +1,214 @@ +--- + libmultipath/config.c | 2 ++ + libmultipath/config.h | 2 ++ + libmultipath/defaults.h | 2 ++ + libmultipath/dict.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + libmultipath/discovery.c | 8 +++++--- + libmultipath/structs.h | 8 ++++++++ + multipathd/main.c | 15 ++++++++++++++- + 7 files changed, 79 insertions(+), 4 deletions(-) + +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -673,6 +673,8 @@ load_config (char * file, struct udev *u + conf->force_sync = 0; + conf->ignore_new_boot_devs = 0; + conf->processed_main_config = 0; ++ conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; ++ conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; + + /* + * preload default hwtable +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -139,6 +139,8 @@ struct config { + int processed_main_config; + int delay_watch_checks; + int delay_wait_checks; ++ int retrigger_tries; ++ int retrigger_delay; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -21,6 +21,8 @@ + #define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF + #define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF + #define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF ++#define DEFAULT_RETRIGGER_DELAY 10 ++#define DEFAULT_RETRIGGER_TRIES 3 + + #define DEFAULT_CHECKINT 5 + #define MAX_CHECKINT(a) (a << 2) +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -839,6 +839,38 @@ def_delay_wait_checks_handler(vector str + return 0; + } + ++static int ++def_retrigger_tries_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ conf->retrigger_tries = atoi(buff); ++ FREE(buff); ++ ++ return 0; ++} ++ ++static int ++def_retrigger_delay_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ conf->retrigger_delay = atoi(buff); ++ FREE(buff); ++ ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -3194,6 +3226,18 @@ snprint_def_delay_wait_checks(char * buf + } + + static int ++snprint_def_retrigger_tries (char * buff, int len, void * data) ++{ ++ return snprintf(buff, len, "%i", conf->retrigger_tries); ++} ++ ++static int ++snprint_def_retrigger_delay (char * buff, int len, void * data) ++{ ++ return snprintf(buff, len, "%i", conf->retrigger_delay); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -3267,6 +3311,8 @@ init_keywords(void) + install_keyword("config_dir", &def_config_dir_handler, &snprint_def_config_dir); + install_keyword("delay_watch_checks", &def_delay_watch_checks_handler, &snprint_def_delay_watch_checks); + install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks); ++ install_keyword("retrigger_tries", &def_retrigger_tries_handler, &snprint_def_retrigger_tries); ++ install_keyword("retrigger_delay", &def_retrigger_delay_handler, &snprint_def_retrigger_delay); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -1111,9 +1111,13 @@ get_uid (struct path * pp) + len = strlen(value); + } + strncpy(pp->wwid, value, len); ++ pp->missing_udev_info = INFO_OK; ++ pp->tick = 0; + } else { + condlog(3, "%s: no %s attribute", pp->dev, + pp->uid_attribute); ++ pp->missing_udev_info = INFO_MISSING; ++ pp->tick = conf->retrigger_delay; + } + + /* Strip any trailing blanks */ +@@ -1201,10 +1205,8 @@ pathinfo (struct path *pp, vector hwtabl + * Retrieve path priority, even for PATH_DOWN paths if it has never + * been successfully obtained before. + */ +- if ((mask & DI_PRIO) && path_state == PATH_UP) { ++ if ((mask & DI_PRIO) && path_state == PATH_UP && strlen(pp->wwid)) { + if (pp->state != PATH_DOWN || pp->priority == PRIO_UNDEF) { +- if (!strlen(pp->wwid)) +- get_uid(pp); + get_prio(pp); + } + } +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -139,6 +139,12 @@ enum delay_checks_states { + DELAY_CHECKS_UNDEF = 0, + }; + ++enum missing_udev_info_states { ++ INFO_OK, ++ INFO_MISSING, ++ INFO_REQUESTED, ++}; ++ + struct sg_id { + int host_no; + int channel; +@@ -193,6 +199,8 @@ struct path { + struct checker checker; + struct multipath * mpp; + int fd; ++ int missing_udev_info; ++ int retriggers; + + /* configlet pointers */ + struct hwentry * hwe; +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -708,6 +708,10 @@ uev_update_path (struct uevent *uev, str + uev->kernel); + return 1; + } ++ ++ if (pp->missing_udev_info == INFO_REQUESTED) ++ return uev_add_path(uev, vecs); ++ + /* reinit the prio values on change event, in case something is + * different */ + prio_init(&pp->prio); +@@ -1133,12 +1137,21 @@ check_path (struct vectors * vecs, struc + int chkr_new_path_up = 0; + int oldchkrstate = pp->chkrstate; + +- if (!pp->mpp) ++ if (!pp->mpp && (pp->missing_udev_info != INFO_MISSING || ++ pp->retriggers >= conf->retrigger_tries)) + return; + + if (pp->tick && --pp->tick) + return; /* don't check this path yet */ + ++ if (!pp->mpp) { ++ pp->missing_udev_info = INFO_REQUESTED; ++ pp->retriggers++; ++ sysfs_attr_set_value(pp->udev, "uevent", "change", ++ strlen("change")); ++ return; ++ } ++ + /* + * provision a next check soonest, + * in case we exit abnormaly from here diff --git a/SOURCES/0125-RHBZ-1153832-kpartx-delete.patch b/SOURCES/0125-RHBZ-1153832-kpartx-delete.patch new file mode 100644 index 0000000..329bc44 --- /dev/null +++ b/SOURCES/0125-RHBZ-1153832-kpartx-delete.patch @@ -0,0 +1,26 @@ +--- + kpartx/kpartx.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: multipath-tools-130222/kpartx/kpartx.c +=================================================================== +--- multipath-tools-130222.orig/kpartx/kpartx.c ++++ multipath-tools-130222/kpartx/kpartx.c +@@ -409,7 +409,7 @@ main(int argc, char **argv){ + break; + + case DELETE: +- for (j = n-1; j >= 0; j--) { ++ for (j = MAXSLICES-1; j >= 0; j--) { + if (safe_sprintf(partname, "%s%s%d", + mapname, delim, j+1)) { + fprintf(stderr, "partname too small\n"); +@@ -417,7 +417,7 @@ main(int argc, char **argv){ + } + strip_slash(partname); + +- if (!slices[j].size || !dm_map_present(partname)) ++ if (!dm_map_present(partname)) + continue; + + if (!dm_simplecmd(DM_DEVICE_REMOVE, partname, diff --git a/SOURCES/0126-RHBZ-1211383-alias-collision.patch b/SOURCES/0126-RHBZ-1211383-alias-collision.patch new file mode 100644 index 0000000..965bf53 --- /dev/null +++ b/SOURCES/0126-RHBZ-1211383-alias-collision.patch @@ -0,0 +1,113 @@ +--- + libmultipath/config.c | 4 ++++ + libmultipath/config.h | 1 + + libmultipath/configure.c | 3 +++ + libmultipath/dict.c | 33 +++++++++++++++++++++++++++++++++ + 4 files changed, 41 insertions(+) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -422,6 +422,9 @@ select_action (struct multipath * mpp, v + condlog(2, "%s: unable to rename %s to %s (%s is used by %s)", + mpp->wwid, cmpp->alias, mpp->alias, + mpp->alias, cmpp_by_name->wwid); ++ /* reset alias to existing alias */ ++ FREE(mpp->alias); ++ mpp->alias = STRDUP(cmpp->alias); + mpp->action = ACT_NOTHING; + return; + } +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -675,6 +675,7 @@ load_config (char * file, struct udev *u + conf->processed_main_config = 0; + conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; + conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; ++ conf->new_bindings_in_boot = 0; + + /* + * preload default hwtable +@@ -794,6 +795,9 @@ load_config (char * file, struct udev *u + if (conf->ignore_new_boot_devs) + in_initrd(); + ++ if (conf->new_bindings_in_boot == 0 && in_initrd()) ++ conf->bindings_read_only = 1; ++ + return 0; + out: + free_config(conf); +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -141,6 +141,7 @@ struct config { + int delay_wait_checks; + int retrigger_tries; + int retrigger_delay; ++ int new_bindings_in_boot; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -871,6 +871,29 @@ def_retrigger_delay_handler(vector strve + return 0; + } + ++static int ++def_new_bindings_in_boot_handler(vector strvec) ++{ ++ char * buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) || ++ (strlen(buff) == 1 && !strcmp(buff, "0"))) ++ conf->new_bindings_in_boot = 0; ++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) || ++ (strlen(buff) == 1 && !strcmp(buff, "1"))) ++ conf->new_bindings_in_boot = 1; ++ else ++ conf->new_bindings_in_boot = 0; ++ ++ FREE(buff); ++ return 0; ++} ++ + /* + * blacklist block handlers + */ +@@ -3238,6 +3261,15 @@ snprint_def_retrigger_delay (char * buff + } + + static int ++snprint_def_new_bindings_in_boot(char * buff, int len, void * data) ++{ ++ if (conf->new_bindings_in_boot == 1) ++ return snprintf(buff, len, "yes"); ++ else ++ return snprintf(buff, len, "no"); ++} ++ ++static int + snprint_ble_simple (char * buff, int len, void * data) + { + struct blentry * ble = (struct blentry *)data; +@@ -3313,6 +3345,7 @@ init_keywords(void) + install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks); + install_keyword("retrigger_tries", &def_retrigger_tries_handler, &snprint_def_retrigger_tries); + install_keyword("retrigger_delay", &def_retrigger_delay_handler, &snprint_def_retrigger_delay); ++ install_keyword("new_bindings_in_boot", &def_new_bindings_in_boot_handler, &snprint_def_new_bindings_in_boot); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); + __deprecated install_keyword("default_uid_attribute", &def_uid_attribute_handler, NULL); diff --git a/SOURCES/0127-RHBZ-1201030-use-blk-availability.patch b/SOURCES/0127-RHBZ-1201030-use-blk-availability.patch new file mode 100644 index 0000000..b2cd7cf --- /dev/null +++ b/SOURCES/0127-RHBZ-1201030-use-blk-availability.patch @@ -0,0 +1,15 @@ +--- + multipathd/multipathd.service | 1 + + 1 file changed, 1 insertion(+) + +Index: multipath-tools-130222/multipathd/multipathd.service +=================================================================== +--- multipath-tools-130222.orig/multipathd/multipathd.service ++++ multipath-tools-130222/multipathd/multipathd.service +@@ -1,5 +1,6 @@ + [Unit] + Description=Device-Mapper Multipath Device Controller ++Requires=blk-availability.service + Before=iscsi.service iscsid.service lvm2-activation-early.service + After=syslog.target + ConditionPathExists=/etc/multipath.conf diff --git a/SOURCES/0128-RHBZ-1222123-mpathconf-allow.patch b/SOURCES/0128-RHBZ-1222123-mpathconf-allow.patch new file mode 100644 index 0000000..a48d8ae --- /dev/null +++ b/SOURCES/0128-RHBZ-1222123-mpathconf-allow.patch @@ -0,0 +1,240 @@ +--- + multipath/mpathconf | 135 +++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 124 insertions(+), 11 deletions(-) + +Index: multipath-tools-130222/multipath/mpathconf +=================================================================== +--- multipath-tools-130222.orig/multipath/mpathconf ++++ multipath-tools-130222/multipath/mpathconf +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!/bin/bash + # + # Copyright (C) 2010 Red Hat, Inc. All rights reserved. + # +@@ -17,12 +17,14 @@ + # This program was largely ripped off from lvmconf + # + +-unset ENABLE FIND FRIENDLY MODULE MULTIPATHD HAVE_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_DEFAULTS HAVE_FRIENDLY HAVE_MULTIPATHD HAVE_MODULE SHOW_STATUS CHANGED_CONFIG ++unset ENABLE FIND FRIENDLY MODULE MULTIPATHD HAVE_DISABLE HAVE_WWID_DISABLE HAVE_FIND HAVE_BLACKLIST HAVE_EXCEPTIONS HAVE_DEFAULTS HAVE_FRIENDLY HAVE_MULTIPATHD HAVE_MODULE HAVE_OUTFILE SHOW_STATUS CHANGED_CONFIG WWID_LIST + + DEFAULT_CONFIGFILE="/usr/share/doc/device-mapper-multipath-0.4.9/multipath.conf" + CONFIGFILE="/etc/multipath.conf" ++OUTPUTFILE="/etc/multipath.conf" + MULTIPATHDIR="/etc/multipath" + TMPFILE=/etc/multipath/.multipath.conf.tmp ++WWIDS=0 + + function usage + { +@@ -31,13 +33,60 @@ function usage + echo "Commands:" + echo "Enable: --enable " + echo "Disable: --disable" ++ echo "Only allow certain wwids (instead of enable): --allow " + echo "Set user_friendly_names (Default y): --user_friendly_names " + echo "Set find_multipaths (Default y): --find_multipaths " + echo "Load the dm-multipath modules on enable (Default y): --with_module " + echo "start/stop/reload multipathd (Default n): --with_multipathd " ++ echo "select output file (Default /etc/multipath.conf): --outfile " + echo "" + } + ++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 ++ WWID_LIST[$WWIDS]="${1##part*-mpath-}" ++ ((WWIDS++)) ++ elif [[ "$1" =~ ^mpath- ]] ; then ++ WWID_LIST[$WWIDS]="${1##mpath-}" ++ ((WWIDS++)) ++ 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 ++ WWID_LIST[$WWIDS]="$1" ++ ((WWIDS++)) ++ fi ++} ++ + function parse_args + { + while [ -n "$1" ]; do +@@ -50,6 +99,16 @@ function parse_args + 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 +@@ -86,6 +145,16 @@ function parse_args + exit 1 + fi + ;; ++ --outfile) ++ if [ -n "$2" ]; then ++ OUTPUTFILE=$2 ++ HAVE_OUTFILE=1 ++ shift 2 ++ else ++ usage ++ exit 1 ++ fi ++ ;; + *) + usage + exit +@@ -120,6 +189,22 @@ function validate_args + 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 ++{ ++ echo "blacklist_exceptions {" >> $TMPFILE ++ INDEX=0 ++ while [ "$INDEX" -lt "$WWIDS" ] ; do ++ echo " wwid \"${WWID_LIST[$INDEX]}\"" >> $TMPFILE ++ ((INDEX++)) ++ done ++ echo "}" >> $TMPFILE + } + + umask 0077 +@@ -146,6 +231,10 @@ if grep -q "^blacklist[[:space:]]*{" $TM + 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 +@@ -169,11 +258,19 @@ 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 ++ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*devnode \"\.\?\*\"" ; then + HAVE_DISABLE=0 + fi + fi + ++if [ "$HAVE_BLACKLIST" = "1" ]; then ++ if sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*wwid \"\.\?\*\"" ; then ++ HAVE_WWID_DISABLE=1 ++ elif sed -n '/^blacklist[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*#[[:space:]]*wwid \"\.\?\*\"" ; then ++ HAVE_WWID_DISABLE=0 ++ fi ++fi ++ + if [ "$HAVE_DEFAULTS" = "1" ]; then + if sed -n '/^defaults[[:space:]]*{/,/^}/ p' $TMPFILE | grep -q "^[[:space:]]*find_multipaths[[:space:]]*\(yes\|1\)" ; then + HAVE_FIND=1 +@@ -241,17 +338,33 @@ defaults { + _EOF_ + fi + +-if [ "$ENABLE" = 1 ]; then ++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:]]*{/,/^}/d' $TMPFILE ++ fi ++ echo $HAVE_WWID_DISABLE ++ 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 "*" ++ 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 \"\.\?\*\"/ devnode ".*"/' $TMPFILE + fi + fi + +@@ -289,17 +402,17 @@ elif [ "$FRIENDLY" = "y" ]; then + fi + fi + +-if [ -f "$CONFIGFILE" ]; then +- cp $CONFIGFILE $CONFIGFILE.old ++if [ -f "$OUTPUTFILE" ]; then ++ cp $OUTPUTFILE $OUTPUTFILE.old + if [ $? != 0 ]; then +- echo "failed to backup old config file, $CONFIGFILE not updated" ++ echo "failed to backup old config file, $OUTPUTFILE not updated" + exit 1 + fi + fi + +-cp $TMPFILE $CONFIGFILE ++cp $TMPFILE $OUTPUTFILE + if [ $? != 0 ]; then +- echo "failed to copy new config file into place, check $CONFIGFILE is still OK" ++ echo "failed to copy new config file into place, check $OUTPUTFILE is still OK" + exit 1 + fi + diff --git a/SOURCES/0129-UPBZ-1254292-iscsi-targetname.patch b/SOURCES/0129-UPBZ-1254292-iscsi-targetname.patch new file mode 100644 index 0000000..26a6831 --- /dev/null +++ b/SOURCES/0129-UPBZ-1254292-iscsi-targetname.patch @@ -0,0 +1,17 @@ +--- + libmultipath/discovery.c | 2 ++ + 1 file changed, 2 insertions(+) + +Index: multipath-tools-130222/libmultipath/discovery.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/discovery.c ++++ multipath-tools-130222/libmultipath/discovery.c +@@ -280,6 +280,8 @@ sysfs_get_tgt_nodename (struct path *pp, + const char *value; + + value = udev_device_get_sysattr_value(tgtdev, "tgtname"); ++ if (!value) ++ value = udev_device_get_sysattr_value(tgtdev, "targetname"); + if (value) { + pp->sg_id.proto_id = SCSI_PROTOCOL_ISCSI; + pp->sg_id.transport_id = tgtid; diff --git a/SOURCES/0130-RHBZ-1259523-host_name_len.patch b/SOURCES/0130-RHBZ-1259523-host_name_len.patch new file mode 100644 index 0000000..1460550 --- /dev/null +++ b/SOURCES/0130-RHBZ-1259523-host_name_len.patch @@ -0,0 +1,17 @@ +--- + libmultipath/structs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -15,7 +15,7 @@ + #define BLK_DEV_SIZE 33 + #define PATH_SIZE 512 + #define NAME_SIZE 512 +-#define HOST_NAME_LEN 8 ++#define HOST_NAME_LEN 16 + #define SLOT_NAME_SIZE 40 + + #define SCSI_VENDOR_SIZE 9 diff --git a/SOURCES/0131-UPBZ-1259831-lock-retry.patch b/SOURCES/0131-UPBZ-1259831-lock-retry.patch new file mode 100644 index 0000000..3f5bd4d --- /dev/null +++ b/SOURCES/0131-UPBZ-1259831-lock-retry.patch @@ -0,0 +1,33 @@ +--- + multipathd/main.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -462,6 +462,7 @@ ev_add_path (struct path * pp, struct ve + char params[PARAMS_SIZE] = {0}; + int retries = 3; + int start_waiter = 0; ++ int ret; + + /* + * need path UID to go any further +@@ -540,7 +541,15 @@ rescan: + /* + * reload the map for the multipath mapped device + */ +- if (domap(mpp, params) <= 0) { ++retry: ++ ret = domap(mpp, params); ++ if (ret <= 0) { ++ if (ret < 0 && retries-- > 0) { ++ condlog(0, "%s: retry domap for addition of new " ++ "path %s", mpp->alias, pp->dev); ++ sleep(1); ++ goto retry; ++ } + condlog(0, "%s: failed in domap for addition of new " + "path %s", mpp->alias, pp->dev); + /* diff --git a/SOURCES/0132-RHBZ-1296979-fix-define.patch b/SOURCES/0132-RHBZ-1296979-fix-define.patch new file mode 100644 index 0000000..cc50722 --- /dev/null +++ b/SOURCES/0132-RHBZ-1296979-fix-define.patch @@ -0,0 +1,17 @@ +--- + libmultipath/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: multipath-bz1296979/libmultipath/Makefile +=================================================================== +--- multipath-bz1296979.orig/libmultipath/Makefile ++++ multipath-bz1296979/libmultipath/Makefile +@@ -30,7 +30,7 @@ ifneq ($(strip $(LIBDM_API_COOKIE)),0) + CFLAGS += -DLIBDM_API_COOKIE + endif + +-LIBUDEV_API_RECVBUF = $(shell grep -Ecs '^[a-z]*[[:space:]]+udev_monitor_set_resolve_buffer_size' /usr/include/libudev.h) ++LIBUDEV_API_RECVBUF = $(shell grep -Ecs '^[a-z]*[[:space:]]+udev_monitor_set_receive_buffer_size' /usr/include/libudev.h) + + ifneq ($(strip $(LIBUDEV_API_RECVBUF)),0) + CFLAGS += -DLIBUDEV_API_RECVBUF diff --git a/SOURCES/0133-RHBZ-1321019-wait-for-map-add.patch b/SOURCES/0133-RHBZ-1321019-wait-for-map-add.patch new file mode 100644 index 0000000..3ac3f77 --- /dev/null +++ b/SOURCES/0133-RHBZ-1321019-wait-for-map-add.patch @@ -0,0 +1,495 @@ +--- + libmultipath/config.c | 1 + libmultipath/config.h | 2 + libmultipath/configure.c | 4 + + libmultipath/defaults.h | 1 + libmultipath/dict.c | 25 +++++++++ + libmultipath/structs.h | 2 + multipath.conf.defaults | 1 + multipath/multipath.conf.5 | 8 +++ + multipathd/cli_handlers.c | 65 ++++++++++++++++++++---- + multipathd/main.c | 119 +++++++++++++++++++++++++++++++++++++++++++-- + multipathd/main.h | 1 + 11 files changed, 216 insertions(+), 13 deletions(-) + +Index: multipath-tools-130222/libmultipath/configure.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/configure.c ++++ multipath-tools-130222/libmultipath/configure.c +@@ -675,6 +675,10 @@ domap (struct multipath * mpp, char * pa + */ + if (mpp->action != ACT_CREATE) + mpp->action = ACT_NOTHING; ++ else { ++ mpp->wait_for_udev = 1; ++ mpp->uev_msg_tick = conf->uev_msg_delay; ++ } + } + dm_setgeometry(mpp); + return DOMAP_OK; +Index: multipath-tools-130222/libmultipath/structs.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/structs.h ++++ multipath-tools-130222/libmultipath/structs.h +@@ -217,6 +217,8 @@ struct multipath { + int bestpg; + int queuedio; + int action; ++ int wait_for_udev; ++ int uev_msg_tick; + int pgfailback; + int failback_tick; + int rr_weight; +Index: multipath-tools-130222/multipathd/cli_handlers.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/cli_handlers.c ++++ multipath-tools-130222/multipathd/cli_handlers.c +@@ -548,6 +548,11 @@ cli_reload(void *v, char **reply, int *l + condlog(0, "%s: invalid map name. cannot reload", mapname); + return 1; + } ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing reload", ++ mpp->alias); ++ return 1; ++ } + + return reload_map(vecs, mpp, 0); + } +@@ -592,6 +597,12 @@ cli_resize(void *v, char **reply, int *l + return 1; + } + ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing resize", ++ mpp->alias); ++ return 1; ++ } ++ + pgp = VECTOR_SLOT(mpp->pg, 0); + + if (!pgp){ +@@ -756,6 +767,12 @@ cli_reconfigure(void * v, char ** reply, + { + struct vectors * vecs = (struct vectors *)data; + ++ if (need_to_delay_reconfig(vecs)) { ++ conf->delayed_reconfig = 1; ++ condlog(2, "delaying reconfigure (operator)"); ++ return 0; ++ } ++ + condlog(2, "reconfigure (operator)"); + + return reconfigure(vecs); +@@ -766,17 +783,25 @@ cli_suspend(void * v, char ** reply, int + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); +- int r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0); ++ int r; ++ struct multipath * mpp; + + param = convert_dev(param, 0); +- condlog(2, "%s: suspend (operator)", param); ++ mpp = find_mp_by_alias(vecs->mpvec, param); ++ if (!mpp) ++ return 1; + +- if (!r) /* error */ ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing suspend", ++ mpp->alias); + return 1; ++ } + +- struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); ++ r = dm_simplecmd_noflush(DM_DEVICE_SUSPEND, param, 0); + +- if (!mpp) ++ condlog(2, "%s: suspend (operator)", param); ++ ++ if (!r) /* error */ + return 1; + + dm_get_info(param, &mpp->dmi); +@@ -788,17 +813,25 @@ cli_resume(void * v, char ** reply, int + { + struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); +- int r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); ++ int r; ++ struct multipath * mpp; + + param = convert_dev(param, 0); +- condlog(2, "%s: resume (operator)", param); ++ mpp = find_mp_by_alias(vecs->mpvec, param); ++ if (!mpp) ++ return 1; + +- if (!r) /* error */ ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing resume", ++ mpp->alias); + return 1; ++ } + +- struct multipath * mpp = find_mp_by_alias(vecs->mpvec, param); ++ r = dm_simplecmd_noflush(DM_DEVICE_RESUME, param, 0); + +- if (!mpp) ++ condlog(2, "%s: resume (operator)", param); ++ ++ if (!r) /* error */ + return 1; + + dm_get_info(param, &mpp->dmi); +@@ -831,9 +864,21 @@ cli_reinstate(void * v, char ** reply, i + int + cli_reassign (void * v, char ** reply, int * len, void * data) + { ++ struct vectors * vecs = (struct vectors *)data; + char * param = get_keyparam(v, MAP); ++ struct multipath *mpp; + + param = convert_dev(param, 0); ++ mpp = find_mp_by_alias(vecs->mpvec, param); ++ if (!mpp) ++ return 1; ++ ++ if (mpp->wait_for_udev) { ++ condlog(2, "%s: device not fully created, failing reassign", ++ mpp->alias); ++ return 1; ++ } ++ + condlog(3, "%s: reset devices (operator)", param); + + dm_reassign(param); +Index: multipath-tools-130222/libmultipath/config.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.h ++++ multipath-tools-130222/libmultipath/config.h +@@ -142,6 +142,8 @@ struct config { + int retrigger_tries; + int retrigger_delay; + int new_bindings_in_boot; ++ int delayed_reconfig; ++ int uev_msg_delay; + unsigned int version[3]; + + char * dev; +Index: multipath-tools-130222/multipathd/main.c +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.c ++++ multipath-tools-130222/multipathd/main.c +@@ -251,6 +251,47 @@ flush_map(struct multipath * mpp, struct + return 0; + } + ++int ++update_map (struct multipath *mpp, struct vectors *vecs) ++{ ++ int retries = 3; ++ char params[PARAMS_SIZE] = {0}; ++ ++retry: ++ condlog(4, "%s: updating new map", mpp->alias); ++ if (adopt_paths(vecs->pathvec, mpp, 1)) { ++ condlog(0, "%s: failed to adopt paths for new map update", ++ mpp->alias); ++ retries = -1; ++ goto fail; ++ } ++ verify_paths(mpp, vecs, NULL); ++ mpp->flush_on_last_del = FLUSH_UNDEF; ++ mpp->action = ACT_RELOAD; ++ ++ if (setup_map(mpp, params, PARAMS_SIZE)) { ++ condlog(0, "%s: failed to setup new map in update", mpp->alias); ++ retries = -1; ++ goto fail; ++ } ++ if (domap(mpp, params) <= 0 && retries-- > 0) { ++ condlog(0, "%s: map_udate sleep", mpp->alias); ++ sleep(1); ++ goto retry; ++ } ++ dm_lib_release(); ++ ++fail: ++ if (setup_multipath(vecs, mpp)) ++ return 1; ++ ++ sync_map_state(mpp); ++ ++ if (retries < 0) ++ condlog(0, "%s: failed reload in new map update", mpp->alias); ++ return 0; ++} ++ + static int + uev_add_map (struct uevent * uev, struct vectors * vecs) + { +@@ -293,6 +334,20 @@ ev_add_map (char * dev, char * alias, st + mpp = find_mp_by_alias(vecs->mpvec, alias); + + if (mpp) { ++ if (mpp->wait_for_udev > 1) { ++ if (update_map(mpp, vecs)) ++ /* setup multipathd removed the map */ ++ return 1; ++ } ++ if (mpp->wait_for_udev) { ++ mpp->wait_for_udev = 0; ++ if (conf->delayed_reconfig && ++ !need_to_delay_reconfig(vecs)) { ++ condlog(2, "reconfigure (delayed)"); ++ reconfigure(vecs); ++ return 0; ++ } ++ } + /* + * Not really an error -- we generate our own uevent + * if we create a multipath mapped device as a result +@@ -471,7 +526,14 @@ ev_add_path (struct path * pp, struct ve + condlog(0, "%s: failed to get path uid", pp->dev); + goto fail; /* leave path added to pathvec */ + } +- mpp = pp->mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); ++ mpp = find_mp_by_wwid(vecs->mpvec, pp->wwid); ++ if (mpp && mpp->wait_for_udev) { ++ mpp->wait_for_udev = 2; ++ orphan_path(pp); ++ return 0; ++ } ++ ++ pp->mpp = mpp; + rescan: + if (mpp) { + if ((!pp->size) || (mpp->size != pp->size)) { +@@ -670,6 +732,12 @@ ev_remove_path (struct path *pp, struct + " removal of path %s", mpp->alias, pp->dev); + goto fail; + } ++ ++ if (mpp->wait_for_udev) { ++ mpp->wait_for_udev = 2; ++ goto out; ++ } ++ + /* + * reload the map + */ +@@ -731,6 +799,11 @@ uev_update_path (struct uevent *uev, str + condlog(2, "%s: update path write_protect to '%d' (uevent)", + uev->kernel, ro); + if (pp->mpp) { ++ if (pp->mpp->wait_for_udev) { ++ pp->mpp->wait_for_udev = 2; ++ return 0; ++ } ++ + retval = reload_map(vecs, pp->mpp, 0); + + condlog(2, "%s: map %s reloaded (retval %d)", +@@ -1063,6 +1136,20 @@ followover_should_failback(struct path * + } + + static void ++missing_uev_message_tick(vector mpvec) ++{ ++ struct multipath * mpp; ++ unsigned int i; ++ ++ vector_foreach_slot (mpvec, mpp, i) { ++ if (mpp->wait_for_udev && --mpp->uev_msg_tick <= 0) { ++ condlog(0, "%s: startup incomplete. Still waiting on udev", mpp->alias); ++ mpp->uev_msg_tick = conf->uev_msg_delay; ++ } ++ } ++} ++ ++static void + defered_failback_tick (vector mpvec) + { + struct multipath * mpp; +@@ -1316,6 +1403,9 @@ check_path (struct vectors * vecs, struc + + pp->state = newstate; + ++ ++ if (pp->mpp->wait_for_udev) ++ return; + /* + * path prio refreshing + */ +@@ -1369,6 +1459,7 @@ checkerloop (void *ap) + if (vecs->mpvec) { + defered_failback_tick(vecs->mpvec); + retry_count_tick(vecs->mpvec); ++ missing_uev_message_tick(vecs->mpvec); + } + if (count) + count--; +@@ -1464,6 +1555,22 @@ configure (struct vectors * vecs, int st + } + + int ++need_to_delay_reconfig(struct vectors * vecs) ++{ ++ struct multipath *mpp; ++ int i; ++ ++ if (!VECTOR_SIZE(vecs->mpvec)) ++ return 0; ++ ++ vector_foreach_slot(vecs->mpvec, mpp, i) { ++ if (mpp->wait_for_udev) ++ return 1; ++ } ++ return 0; ++} ++ ++int + reconfigure (struct vectors * vecs) + { + struct config * old = conf; +@@ -1543,12 +1650,18 @@ void + handle_signals(void) + { + if (reconfig_sig && running_state == DAEMON_RUNNING) { +- condlog(2, "reconfigure (signal)"); + pthread_cleanup_push(cleanup_lock, + &gvecs->lock); + lock(gvecs->lock); + pthread_testcancel(); +- reconfigure(gvecs); ++ if (need_to_delay_reconfig(gvecs)) { ++ conf->delayed_reconfig = 1; ++ condlog(2, "delaying reconfigure (signal)"); ++ } ++ else { ++ condlog(2, "reconfigure (signal)"); ++ reconfigure(gvecs); ++ } + lock_cleanup_pop(gvecs->lock); + } + if (log_reset_sig) { +Index: multipath-tools-130222/multipathd/main.h +=================================================================== +--- multipath-tools-130222.orig/multipathd/main.h ++++ multipath-tools-130222/multipathd/main.h +@@ -18,6 +18,7 @@ extern pid_t daemon_pid; + + void exit_daemon(void); + const char * daemon_status(void); ++int need_to_delay_reconfig (struct vectors *); + int reconfigure (struct vectors *); + int ev_add_path (struct path *, struct vectors *); + int ev_remove_path (struct path *, struct vectors *); +Index: multipath-tools-130222/libmultipath/config.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/config.c ++++ multipath-tools-130222/libmultipath/config.c +@@ -676,6 +676,7 @@ load_config (char * file, struct udev *u + conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES; + conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY; + conf->new_bindings_in_boot = 0; ++ conf->uev_msg_delay = DEFAULT_UEV_MSG_DELAY; + + /* + * preload default hwtable +Index: multipath-tools-130222/libmultipath/defaults.h +=================================================================== +--- multipath-tools-130222.orig/libmultipath/defaults.h ++++ multipath-tools-130222/libmultipath/defaults.h +@@ -23,6 +23,7 @@ + #define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF + #define DEFAULT_RETRIGGER_DELAY 10 + #define DEFAULT_RETRIGGER_TRIES 3 ++#define DEFAULT_UEV_MSG_DELAY 30 + + #define DEFAULT_CHECKINT 5 + #define MAX_CHECKINT(a) (a << 2) +Index: multipath-tools-130222/libmultipath/dict.c +=================================================================== +--- multipath-tools-130222.orig/libmultipath/dict.c ++++ multipath-tools-130222/libmultipath/dict.c +@@ -872,6 +872,24 @@ def_retrigger_delay_handler(vector strve + } + + static int ++def_uev_msg_delay_handler(vector strvec) ++{ ++ char *buff; ++ ++ buff = set_value(strvec); ++ ++ if (!buff) ++ return 1; ++ ++ conf->uev_msg_delay = atoi(buff); ++ if (conf->uev_msg_delay <= 0) ++ conf->uev_msg_delay = DEFAULT_UEV_MSG_DELAY; ++ FREE(buff); ++ ++ return 0; ++} ++ ++static int + def_new_bindings_in_boot_handler(vector strvec) + { + char * buff; +@@ -3261,6 +3279,12 @@ snprint_def_retrigger_delay (char * buff + } + + static int ++snprint_def_uev_msg_delay (char * buff, int len, void * data) ++{ ++ return snprintf(buff, len, "%i", conf->uev_msg_delay); ++} ++ ++static int + snprint_def_new_bindings_in_boot(char * buff, int len, void * data) + { + if (conf->new_bindings_in_boot == 1) +@@ -3345,6 +3369,7 @@ init_keywords(void) + install_keyword("delay_wait_checks", &def_delay_wait_checks_handler, &snprint_def_delay_wait_checks); + install_keyword("retrigger_tries", &def_retrigger_tries_handler, &snprint_def_retrigger_tries); + install_keyword("retrigger_delay", &def_retrigger_delay_handler, &snprint_def_retrigger_delay); ++ install_keyword("missing_uev_msg_delay", &def_uev_msg_delay_handler, &snprint_def_uev_msg_delay); + install_keyword("new_bindings_in_boot", &def_new_bindings_in_boot_handler, &snprint_def_new_bindings_in_boot); + __deprecated install_keyword("default_selector", &def_selector_handler, NULL); + __deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL); +Index: multipath-tools-130222/multipath.conf.defaults +=================================================================== +--- multipath-tools-130222.orig/multipath.conf.defaults ++++ multipath-tools-130222/multipath.conf.defaults +@@ -29,6 +29,7 @@ + # config_dir "/etc/multipath/conf.d" + # delay_watch_checks no + # delay_wait_checks no ++# missing_uev_msg_delay 30 + #} + #blacklist { + # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*" +Index: multipath-tools-130222/multipath/multipath.conf.5 +=================================================================== +--- multipath-tools-130222.orig/multipath/multipath.conf.5 ++++ multipath-tools-130222/multipath/multipath.conf.5 +@@ -478,6 +478,14 @@ used until it has passed + .I delay_wait_checks + checks. Default is + .I no ++.TP ++.B missing_uev_msg_delay ++Controls how long multipathd will wait, after a new multipath device is created, ++to receive a change event from udev for the device, before printing a warning ++message. This warning message will print every ++.I missing_uev_msg_delay ++seconds until the uevent is received. the default is ++.I 30 + . + .SH "blacklist section" + The diff --git a/SOURCES/multipath.conf b/SOURCES/multipath.conf new file mode 100644 index 0000000..32589c3 --- /dev/null +++ b/SOURCES/multipath.conf @@ -0,0 +1,92 @@ +# 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 { +# polling_interval 10 +# path_selector "round-robin 0" +# path_grouping_policy multibus +# uid_attribute ID_SERIAL +# 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_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 +# } +#} diff --git a/SPECS/device-mapper-multipath.spec b/SPECS/device-mapper-multipath.spec new file mode 100644 index 0000000..74b7ea1 --- /dev/null +++ b/SPECS/device-mapper-multipath.spec @@ -0,0 +1,1373 @@ +Summary: Tools to manage multipath devices using device-mapper +Name: device-mapper-multipath +Version: 0.4.9 +Release: 85%{?dist}.2 +License: GPL+ +Group: System Environment/Base +URL: http://christophe.varoqui.free.fr/ + +Source0: multipath-tools-130222.tgz +Source1: multipath.conf +Patch0001: 0001-RH-dont_start_with_no_config.patch +Patch0002: 0002-RH-multipath.rules.patch +Patch0003: 0003-RH-Make-build-system-RH-Fedora-friendly.patch +Patch0004: 0004-RH-multipathd-blacklist-all-by-default.patch +Patch0005: 0005-RH-add-mpathconf.patch +Patch0006: 0006-RH-add-find-multipaths.patch +Patch0007: 0007-RH-add-hp_tur-checker.patch +Patch0008: 0008-RH-revert-partition-changes.patch +Patch0009: 0009-RH-RHEL5-style-partitions.patch +Patch0010: 0010-RH-dont-remove-map-on-enomem.patch +Patch0011: 0011-RH-deprecate-uid-gid-mode.patch +Patch0012: 0012-RH-kpartx-msg.patch +Patch0013: 0013-RHBZ-883981-cleanup-rpmdiff-issues.patch +Patch0014: 0014-RH-handle-other-sector-sizes.patch +Patch0015: 0015-RH-fix-output-buffer.patch +Patch0016: 0016-RH-dont-print-ghost-messages.patch +#Patch0017: 0017-RH-fix-sigusr1.patch +Patch0018: 0018-RH-fix-factorize.patch +Patch0019: 0019-RH-fix-sockets.patch +Patch0020: 0020-RHBZ-907360-static-pthread-init.patch +Patch0021: 0021-RHBZ-919119-respect-kernel-cmdline.patch +Patch0022: 0022-RH-multipathd-check-wwids.patch +Patch0023: 0023-RH-multipath-wipe-wwid.patch +Patch0024: 0024-RH-multipath-wipe-wwids.patch +Patch0025: 0025-UPBZ-916668_add_maj_min.patch +Patch0026: 0026-fix-checker-time.patch +Patch0027: 0027-RH-get-wwid.patch +Patch0028: 0028-RHBZ-929078-refresh-udev-dev.patch +Patch0029: 0029-RH-no-prio-put-msg.patch +Patch0030: 0030-RHBZ-916528-override-queue-no-daemon.patch +Patch0031: 0031-RHBZ-957188-kpartx-use-dm-name.patch +Patch0032: 0032-RHBZ-956464-mpathconf-defaults.patch +Patch0033: 0033-RHBZ-829963-e-series-conf.patch +Patch0034: 0034-RHBZ-851416-mpathconf-display.patch +Patch0035: 0035-RHBZ-891921-list-mpp.patch +Patch0036: 0036-RHBZ-949239-load-multipath-module.patch +Patch0037: 0037-RHBZ-768873-fix-rename.patch +Patch0038: 0038-RHBZ-799860-netapp-config.patch +Patch0039: 0039-RH-detect-prio-fix.patch +Patch0040: 0040-RH-bindings-fix.patch +Patch0041: 0041-RH-check-for-erofs.patch +Patch0042: 0042-UP-fix-signal-handling.patch +Patch0043: 0043-RH-signal-waiter.patch +Patch0044: 0044-RHBZ-976688-fix-wipe-wwids.patch +Patch0045: 0045-RHBZ-977297-man-page-fix.patch +Patch0046: 0046-RHBZ-883981-move-udev-rules.patch +Patch0047: 0047-RHBZ-kpartx-read-only-loop-devs.patch +Patch0048: 0048-RH-print-defaults.patch +Patch0049: 0049-RH-remove-ID_FS_TYPE.patch +Patch0050: 0050-RH-listing-speedup.patch +Patch0051: 0051-UP-fix-cli-resize.patch +Patch0052: 0052-RH-fix-bad-derefs.patch +Patch0053: 0053-UP-fix-failback.patch +Patch0054: 0054-UP-keep-udev-ref.patch +Patch0055: 0055-UP-handle-quiesced-paths.patch +Patch0056: 0056-UP-alua-prio-fix.patch +Patch0057: 0057-UP-fix-tmo.patch +Patch0058: 0058-UP-fix-failback.patch +Patch0059: 0059-UP-flush-failure-queueing.patch +Patch0060: 0060-UP-uevent-loop-udev.patch +Patch0061: 0061-RH-display-find-mpaths.patch +Patch0062: 0062-RH-dont-free-vecs.patch +Patch0063: 0063-RH-fix-warning.patch +Patch0064: 0064-RHBZ-1010040-fix-ID_FS-attrs.patch +Patch0065: 0065-UPBZ-995538-fail-rdac-on-unavailable.patch +Patch0066: 0066-UP-dos-4k-partition-fix.patch +Patch0067: 0067-RHBZ-1022899-fix-udev-partition-handling.patch +Patch0068: 0068-RHBZ-1034578-label-partition-devices.patch +Patch0069: 0069-UPBZ-1033791-improve-rdac-checker.patch +Patch0070: 0070-RHBZ-1036503-blacklist-td-devs.patch +Patch0071: 0071-RHBZ-1031546-strip-dev.patch +Patch0072: 0072-RHBZ-1039199-check-loop-control.patch +Patch0073: 0073-RH-update-build-flags.patch +Patch0074: 0074-RHBZ-1056976-dm-mpath-rules.patch +Patch0075: 0075-RHBZ-1056976-reload-flag.patch +Patch0076: 0076-RHBZ-1056686-add-hw_str_match.patch +Patch0077: 0077-RHBZ-1054806-mpathconf-always-reload.patch +Patch0078: 0078-RHBZ-1054044-fix-mpathconf-manpage.patch +Patch0079: 0079-RHBZ-1070581-add-wwid-option.patch +Patch0080: 0080-RHBZ-1075796-cmdline-wwid.patch +Patch0081: 0081-RHBZ-1066264-check-prefix-on-rename.patch +Patch0082: 0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch +Patch0083: 0083-RHBZ-1080055-orphan-paths-on-reload.patch +Patch0084: 0084-RHBZ-1110000-multipath-man.patch +Patch0085: 0085-UPBZ-1110006-datacore-config.patch +Patch0086: 0086-RHBZ-1110007-orphan-path-on-failed-add.patch +Patch0087: 0087-RHBZ-1110013-config-error-checking.patch +Patch0088: 0088-RHBZ-1069811-configurable-prio-timeout.patch +Patch0089: 0089-RHBZ-1110016-add-noasync-option.patch +Patch0090: 0090-UPBZ-1080038-reorder-paths-for-round-robin.patch +Patch0091: 0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch +Patch0092: 0092-UPBZ-1104605-reload-on-rename.patch +Patch0093: 0093-UPBZ-1086825-user-friendly-name-remap.patch +Patch0094: 0094-RHBZ-1086825-cleanup-remap.patch +Patch0095: 0095-RHBZ-1127944-xtremIO-config.patch +Patch0096: 0096-RHBZ-979474-new-wildcards.patch +Patch0097: 0097-RH-fix-coverity-errors.patch +Patch0098: 0098-UPBZ-1067171-mutipath-i.patch +Patch0099: 0099-RH-add-all-devs.patch +Patch0100: 0100-RHBZ-1067171-multipath-i-update.patch +Patch0101: 0101-RH-cleanup-partmaps-code.patch +Patch0102: 0102-RHBZ-631009-deferred-remove.patch +Patch0103: 0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch +Patch0104: 0104-RHBZ-1159337-fix-double-free.patch +Patch0105: 0105-RHBZ-1180032-find-multipaths-man.patch +Patch0106: 0106-RHBZ-1169935-no-new-devs.patch +Patch0107: 0107-RH-adapter-name-wildcard.patch +Patch0108: 0108-RHBZ-1153832-kpartx-remove-devs.patch +Patch0109: 0109-RH-read-only-bindings.patch +Patch0110: 0110-RHBZ-blacklist-vd-devs.patch +Patch0111: 0111-RH-dont-show-pg-timeout.patch +Patch0112: 0112-RHBZ-1194917-add-config_dir-option.patch +Patch0113: 0113-RHBZ-1194917-cleanup.patch +Patch0114: 0114-RHBZ-1196394-delayed-reintegration.patch +Patch0115: 0115-RHBZ-1198418-fix-double-free.patch +Patch0116: 0116-UPBZ-1188179-dell-36xxi.patch +Patch0117: 0117-RHBZ-1198424-autodetect-clariion-alua.patch +Patch0118: 0118-UPBZ-1200738-update-eternus-config.patch +Patch0119: 0119-RHBZ-1081397-save-alua-info.patch +Patch0120: 0120-RHBZ-1043093-realloc-fix.patch +Patch0121: 0121-RHBZ-1197234-rules-fix.patch +Patch0122: 0122-RHBZ-1212590-dont-use-var.patch +Patch0123: 0123-UPBZ-1166072-fix-path-offline.patch +Patch0124: 0124-RHBZ-1209275-retrigger-uevents.patch +Patch0125: 0125-RHBZ-1153832-kpartx-delete.patch +Patch0126: 0126-RHBZ-1211383-alias-collision.patch +Patch0127: 0127-RHBZ-1201030-use-blk-availability.patch +Patch0128: 0128-RHBZ-1222123-mpathconf-allow.patch +Patch0129: 0129-UPBZ-1254292-iscsi-targetname.patch +Patch0130: 0130-RHBZ-1259523-host_name_len.patch +Patch0131: 0131-UPBZ-1259831-lock-retry.patch +Patch0132: 0132-RHBZ-1296979-fix-define.patch +Patch0133: 0133-RHBZ-1321019-wait-for-map-add.patch + +# runtime +Requires: %{name}-libs = %{version}-%{release} +Requires: kpartx = %{version}-%{release} +Requires: device-mapper >= 7:1.02.96 +Requires: initscripts +Requires(post): systemd-units systemd-sysv chkconfig +Requires(preun): systemd-units +Requires(postun): systemd-units + +# build/setup +BuildRequires: libaio-devel, device-mapper-devel >= 1.02.89 +BuildRequires: libselinux-devel, libsepol-devel +BuildRequires: readline-devel, ncurses-devel +BuildRequires: systemd-units, systemd-devel + +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) + +%description +%{name} provides tools to manage multipath devices by +instructing the device-mapper multipath kernel module what to do. +The tools are : +* multipath - Scan the system for multipath devices and assemble them. +* multipathd - Detects when paths fail and execs multipath to update things. + +%package libs +Summary: The %{name} modules and shared library +License: GPL+ +Group: System Environment/Libraries + +%description libs +The %{name}-libs provides the path checker +and prioritizer modules. It also contains the multipath shared library, +libmultipath. + +%package sysvinit +Summary: SysV init script for device-mapper-multipath +Group: System Environment/Libraries + +%description sysvinit +SysV style init script for device-mapper-multipth. It needs to be +installed only if systemd is not used as the system init process. + +%package -n kpartx +Summary: Partition device manager for device-mapper devices +Group: System Environment/Base + +%description -n kpartx +kpartx manages partition creation and removal for device-mapper devices. + +%prep +%setup -q -n multipath-tools-130222 +%patch0001 -p1 +%patch0002 -p1 +%patch0003 -p1 +%patch0004 -p1 +%patch0005 -p1 +%patch0006 -p1 +%patch0007 -p1 +%patch0008 -p1 +%patch0009 -p1 +%patch0010 -p1 +%patch0011 -p1 +%patch0012 -p1 +%patch0013 -p1 +%patch0014 -p1 +%patch0015 -p1 +%patch0016 -p1 +# %%patch0017 -p1 +%patch0018 -p1 +%patch0019 -p1 +%patch0020 -p1 +%patch0021 -p1 +%patch0022 -p1 +%patch0023 -p1 +%patch0024 -p1 +%patch0025 -p1 +%patch0026 -p1 +%patch0027 -p1 +%patch0028 -p1 +%patch0029 -p1 +%patch0030 -p1 +%patch0031 -p1 +%patch0032 -p1 +%patch0033 -p1 +%patch0034 -p1 +%patch0035 -p1 +%patch0036 -p1 +%patch0037 -p1 +%patch0038 -p1 +%patch0039 -p1 +%patch0040 -p1 +%patch0041 -p1 +%patch0042 -p1 +%patch0043 -p1 +%patch0044 -p1 +%patch0045 -p1 +%patch0046 -p1 +%patch0047 -p1 +%patch0048 -p1 +%patch0049 -p1 +%patch0050 -p1 +%patch0051 -p1 +%patch0052 -p1 +%patch0053 -p1 +%patch0054 -p1 +%patch0055 -p1 +%patch0056 -p1 +%patch0057 -p1 +%patch0058 -p1 +%patch0059 -p1 +%patch0060 -p1 +%patch0061 -p1 +%patch0062 -p1 +%patch0063 -p1 +%patch0064 -p1 +%patch0065 -p1 +%patch0066 -p1 +%patch0067 -p1 +%patch0068 -p1 +%patch0069 -p1 +%patch0070 -p1 +%patch0071 -p1 +%patch0072 -p1 +%patch0073 -p1 +%patch0074 -p1 +%patch0075 -p1 +%patch0076 -p1 +%patch0077 -p1 +%patch0078 -p1 +%patch0079 -p1 +%patch0080 -p1 +%patch0081 -p1 +%patch0082 -p1 +%patch0083 -p1 +%patch0084 -p1 +%patch0085 -p1 +%patch0086 -p1 +%patch0087 -p1 +%patch0088 -p1 +%patch0089 -p1 +%patch0090 -p1 +%patch0091 -p1 +%patch0092 -p1 +%patch0093 -p1 +%patch0094 -p1 +%patch0095 -p1 +%patch0096 -p1 +%patch0097 -p1 +%patch0098 -p1 +%patch0099 -p1 +%patch0100 -p1 +%patch0101 -p1 +%patch0102 -p1 +%patch0103 -p1 +%patch0104 -p1 +%patch0105 -p1 +%patch0106 -p1 +%patch0107 -p1 +%patch0108 -p1 +%patch0109 -p1 +%patch0110 -p1 +%patch0111 -p1 +%patch0112 -p1 +%patch0113 -p1 +%patch0114 -p1 +%patch0115 -p1 +%patch0116 -p1 +%patch0117 -p1 +%patch0118 -p1 +%patch0119 -p1 +%patch0120 -p1 +%patch0121 -p1 +%patch0122 -p1 +%patch0123 -p1 +%patch0124 -p1 +%patch0125 -p1 +%patch0126 -p1 +%patch0127 -p1 +%patch0128 -p1 +%patch0129 -p1 +%patch0130 -p1 +%patch0131 -p1 +%patch0132 -p1 +%patch0133 -p1 +cp %{SOURCE1} . + +%build +%define _sbindir /usr/sbin +%define _libdir /usr/%{_lib} +%define _libmpathdir %{_libdir}/multipath +make %{?_smp_mflags} LIB=%{_lib} + +%install +rm -rf %{buildroot} + +make install \ + DESTDIR=%{buildroot} \ + bindir=%{_sbindir} \ + syslibdir=%{_libdir} \ + libdir=%{_libmpathdir} \ + rcdir=%{_initrddir} \ + unitdir=%{_unitdir} + +# tree fix up +install -d %{buildroot}/etc/multipath + +%clean +rm -rf %{buildroot} + +%post +%systemd_post multipathd.service + +%preun +%systemd_preun multipathd.service + +%postun +if [ $1 -ge 1 ] ; then + /sbin/multipathd forcequeueing daemon > /dev/null 2>&1 || : +fi +%systemd_postun_with_restart multipathd.service + +%triggerun -- %{name} < 0.4.9-37 +# make sure old systemd symlinks are removed after changing the [Install] +# section in multipathd.service from multi-user.target to sysinit.target +/bin/systemctl --quiet is-enabled multipathd.service >/dev/null 2>&1 && /bin/systemctl reenable multipathd.service ||: + +%triggerun -- %{name} < 0.4.9-16 +%{_bindir}/systemd-sysv-convert --save multipathd >/dev/null 2>&1 ||: +bin/systemctl --no-reload enable multipathd.service >/dev/null 2>&1 ||: +/sbin/chkconfig --del multipathd >/dev/null 2>&1 || : +/bin/systemctl try-restart multipathd.service >/dev/null 2>&1 || : + +%triggerpostun -n %{name}-sysvinit -- %{name} < 0.4.9-16 +/sbin/chkconfig --add mdmonitor >/dev/null 2>&1 || : + +%files +%defattr(-,root,root,-) +%{_sbindir}/multipath +%{_sbindir}/multipathd +%{_sbindir}/mpathconf +%{_sbindir}/mpathpersist +%{_unitdir}/multipathd.service +%{_mandir}/man3/mpath_persistent_reserve_in.3.gz +%{_mandir}/man3/mpath_persistent_reserve_out.3.gz +%{_mandir}/man5/multipath.conf.5.gz +%{_mandir}/man8/multipath.8.gz +%{_mandir}/man8/multipathd.8.gz +%{_mandir}/man8/mpathconf.8.gz +%{_mandir}/man8/mpathpersist.8.gz +%config /usr/lib/udev/rules.d/62-multipath.rules +%config /usr/lib/udev/rules.d/11-dm-mpath.rules +%doc AUTHOR COPYING FAQ +%doc multipath.conf +%dir /etc/multipath + +%files libs +%defattr(-,root,root,-) +%doc AUTHOR COPYING +%{_libdir}/libmultipath.so +%{_libdir}/libmultipath.so.* +%{_libdir}/libmpathpersist.so +%{_libdir}/libmpathpersist.so.* +%dir %{_libmpathdir} +%{_libmpathdir}/* + +%post libs -p /sbin/ldconfig + +%postun libs -p /sbin/ldconfig + +%files sysvinit +%{_initrddir}/multipathd + +%files -n kpartx +%defattr(-,root,root,-) +%{_sbindir}/kpartx +%{_mandir}/man8/kpartx.8.gz + +%changelog +* Mon Mar 28 2016 Benjamin Marzinski 0.4.9-85.2 +- Add 0133-RHBZ-1321019-wait-for-map-add.patch + * wait for the device to finish being added before reloading it. +- Resolves: bz #1321019 + +* Mon Feb 01 2016 Benjamin Marzinski 0.4.9-85.1 +- Add 0132-RHBZ-1296979-fix-define.patch + * look for the correct libudev function to set define +- Resolves: bz #1303623 + +* Thu Sep 17 2015 Benjamin Marzinski 0.4.9-85 +- Fix device-mapper Requires line in spec file +- Resolves: bz# 1260728 + +* Mon Sep 14 2015 Benjamin Marzinski 0.4.9-84 +- 0131-UPBZ-1259831-lock-retry.patch + * retry locking when creating multipath devices +- Resolves: bz# 1259831 + +* Tue Sep 8 2015 Benjmain Marzinski 0.4.9-83 +- Add 0130-RHBZ-1259523-host_name_len.patch + * increase size of host string +- Resolves: bz# 1259523 + +* Wed Aug 19 2015 Benjmain Marzinski 0.4.9-82 +- Add 0129-UPBZ-1254292-iscsi-targetname.patch + * check for targetname iscsi sysfs value +- Resolves: bz #1254292 + +* Wed Jul 8 2015 Benjamin Marzinski 0.4.9-81 +- Modify 0128-RHBZ-1222123-mpathconf-allow.patch + * Fix up covscan complaints. +- Related: bz #1222123 + +* Tue Jul 7 2015 Benjamin Marzinski 0.4.9-80 +- Add 0127-RHBZ-1201030-use-blk-availability.patch + * Make multipath use blk-availability.service +- Add 0128-RHBZ-1222123-mpathconf-allow.patch + * Add mpathconf --allow for creating specialized config files. +- Resolves: bz #1201030, #1222123 + +* Fri Jun 5 2015 Benjamin Marzinski 0.4.9-79 +- Add 0124-RHBZ-1209275-retrigger-uevents.patch + * Make multipathd retrigger uevents when paths haven't successfully had + their udev_attribute environment variable set by udev and add + "retrigger_ties" and "retrigger_delay" to control this +- Add 0125-RHBZ-1153832-kpartx-delete.patch + * Delete all partition devices with -d (not just the ones in the partition + table) +- Add 0126-RHBZ-1211383-alias-collision.patch + * make multipathd use the old alias, if rename failed and add + "new_bindings_in_boot" to determine if new bindings can be added to + the bindings file in the initramfs +- Resolves: bz #1153832, #1209275, #1211383 + +* Thu May 7 2015 Benjamin Marzinski 0.4.9-78 +- Modify 0102-RHBZ-631009-deferred-remove.patch + * Code refactor and minor fix. +- Add 0106-RHBZ-1169935-no-new-devs.patch + * add new configuration option "ignore_new_boot_devs" +- Add 0107-RH-adapter-name-wildcard.patch + * add new paths wildcard to show the host adapter +- Add 0108-RHBZ-1153832-kpartx-remove-devs.patch + * switch to kpartx -u in 62-multipath.rules to delete removed partitions +- Add 0109-RH-read-only-bindings.patch + * add -B support to multipathd +- Add 0110-RHBZ-blacklist-vd-devs.patch + * virtio-blk devices don't report a WWID so multipath can't use them +- Add 0111-RH-dont-show-pg-timeout.patch + * remove pg_timeout setting and displaying code +- Add 0112-RHBZ-1194917-add-config_dir-option.patch + * add new configuration option "config_dir" +- Add 0113-RHBZ-1194917-cleanup.patch + * code refactoring +- Add 0114-RHBZ-1196394-delayed-reintegration.patch + * add new configuration options "delay_watch_checks" and + "delay_wait_checks" +- Add 0115-RHBZ-1198418-fix-double-free.patch + * fix crash when multipath fails adding a multipath device +- Add 0116-UPBZ-1188179-dell-36xxi.patch + * New builtin config +- Add 0117-RHBZ-1198424-autodetect-clariion-alua.patch + * update default config +- Add 0118-UPBZ-1200738-update-eternus-config.patch + * update default config +- Add 0119-RHBZ-1081397-save-alua-info.patch + * make prioritizers save information between calls to speed them up. +- Add 0120-RHBZ-1043093-realloc-fix.patch + * free old memory if realloc fails. +- Add 0121-RHBZ-1197234-rules-fix.patch + * make sure kpartx runs after an DM_ACTIVATION event occurs. +- Add 0122-RHBZ-1212590-dont-use-var.patch + * use /run instead of /var/run +- Add 0123-UPBZ-1166072-fix-path-offline.patch + * Don't mark quiesce and transport-offline paths as offline +- Modify mulfipth.conf default config file (bz #1194794) +- Related: bz #1153832 +- Resolves: bz #631009, #1043093, #1081397, #1166072, #1169935, #1188179 +- Resolves: bz #1194794, #1194917, #1196394, #1197234, #1198418, #1198424 +- Resolves: bz #1200738, #1212590 + +* Fri Jan 9 2015 Benjamin Marzinski 0.4.9-77 +- Add 0105-RHBZ-1180032-find-multipaths-man.patch + * add find_multipaths to man page +- Modify multipath.conf (bz #1069360) + * add uid_attribute example +- Resolves: bz #1180032 + +* Fri Nov 14 2014 Benjamin Marzinski 0.4.9-76 +- Modify 0102-RHBZ-631009-deferred-remove.patch + * Fixed compiler warning message for builds with old device-mapper versions +- Add 0104-RHBZ-1159337-fix-double-free.patch + * made ev_remove_path exit immediately after failing setup_multipath, since + it handles cleaning up the device +- Resolves: bz #1159337 +- Related: bz #631009 + +* Thu Nov 6 2014 Benjamin Marzinski 0.4.9-75 +- Add 0103-RHBZ-1148979-fix-partition-mapping-creation-race-with-kpartx.patch + * Only run kpartx on device activation +- Resolves: bz #1148979 + +* Tue Oct 28 2014 Benjamin Marzinski 0.4.9-74 +- Respin again to let buildroot catch up. +- Related: bz #631009 + +* Tue Oct 28 2014 Benjamin Marzinski 0.4.9-73 +- Respin to pick up latest lvm2 code +- Related: bz #631009 + +* Tue Oct 28 2014 Benjamin Marzinski 0.4.9-72 +- Add 0101-RH-cleanup-partmaps-code.patch + * code refactoring to prepare for next patch +- Add 0102-RHBZ-631009-deferred-remove.patch + * add deferred_remove option to /etc/multipath.conf +- Resolves: bz #631009 + +* Fri Sep 5 2014 Benjamin Marzinski 0.4.9-71 +- Re-add 0050-RH-listing-speedup.patch +- Modify 0098-UPBZ-1067171-mutipath-i.patch + * add dry_run cleanup code from upstream +- Refresh 0099-RH-add-all-devs.patch +- Add 0100-RHBZ-1067171-multipath-i-update.patch + * make -i work correctly with find_multipaths +- Resolves: bz #1067171 + +* Wed Sep 3 2014 Benjamin Marzinski 0.4.9-70 +- Modify 0096-RHBZ-979474-new-wildcards.patch + * Fix a faulty check +- Add 0098-UPBZ-1067171-mutipath-i.patch + * Add -i option to ignore wwids file when checking for valid paths +- Add 0099-RH-add-all-devs.patch + * Add new devices config option all_devs. This makes the configuration + overwrite the specified values in all builtin configs +- Related: bz #979474 +- Resolves: bz #1067171 + +* Thu Aug 28 2014 Benjamin Marzinski 0.4.9-69 +- Add 0096-RHBZ-979474-new-wildcards.patch + * Add N, n, R, and r path wildcards to print World Wide ids +- Add 0097-RH-fix-coverity-errors.patch + * Fix a number of unterminated strings and memory leaks on failure + paths. +- Resolves: bz #979474 + +* Tue Aug 12 2014 Benjamin Marzinski 0.4.9-68 +- Add 0091-RHBZ-1069584-fix-empty-values-fast-io-fail-and-dev-loss.patch + * check for null pointers in configuration reading code. +- Add 0092-UPBZ-1104605-reload-on-rename.patch + * Reload table on rename if necessary +- Add 0093-UPBZ-1086825-user-friendly-name-remap.patch + * Keep existing user_friend_name if possible +- Add 0094-RHBZ-1086825-cleanup-remap.patch + * Cleanup issues with upstream patch +- Add 0095-RHBZ-1127944-xtremIO-config.patch + * Add support for EMC ExtremIO devices +- Resolves: bz #1069584, #1104605, #1086825, #1086825, #1127944 + +* Tue Aug 12 2014 Benjamin Marzinski 0.4.9-67 +- Modify multipath.conf (bz #1069360) + * remove getuid_callout example +- Add 0081-RHBZ-1066264-check-prefix-on-rename.patch + * make multipath check the prefix on kpartx partitions during rename, and + copy the existing behaviour +- Add 0082-UPBZ-1109995-no-sync-turs-on-pthread_cancel.patch + * If async tur checker fails on threads, don't retry with the sync version +- Add 0083-RHBZ-1080055-orphan-paths-on-reload.patch + * Fix case where pathlist wasn't getting updated properly +- Add 0084-RHBZ-1110000-multipath-man.patch + * fix errors in multipath man page +- Add 0085-UPBZ-1110006-datacore-config.patch + * Add support for DataCore Virtual Disk +- Add 0086-RHBZ-1110007-orphan-path-on-failed-add.patch + * If multipathd fails to add path correctly, it now fully orphans the path +- Add 0087-RHBZ-1110013-config-error-checking.patch + * Improve multipath.conf error checking. +- Add 0088-RHBZ-1069811-configurable-prio-timeout.patch + * checker_timeout now adjusts the timeouts of the prioritizers as well. +- Add 0089-RHBZ-1110016-add-noasync-option.patch + * Add a new defaults option, "force_sync", that disables the async mode + of the path checkers. This is for cases where to many parallel checkers + hog the CPU +- Add 0090-UPBZ-1080038-reorder-paths-for-round-robin.patch + * make multipathd order paths for better throughput in round-robin mode +- Resolves: bz #1069360, #1066264, #1109995, #1080055, #1110000, #1110006 +- Resolves: bz #1110007, #1110013, #1069811, #1110016, #1080038 + +* Wed Mar 12 2014 Benjamin Marzinski 0.4.9-66 +- Add 0080-RHBZ-1075796-cmdline-wwid.patch + * add multipath option "-A" to add wwids specified by the kernel + command line mapth.wwid options. +- Resolves: bz #1075796 + +* Mon Mar 3 2014 Benjamin Marzinski 0.4.9-65 +- Add 0078-RHBZ-1054044-fix-mpathconf-manpage.patch + * Fix typo +- Add 0079-RHBZ-1070581-add-wwid-option.patch + * add multipath option "-a". To add a device's wwid to the wwids file +- Resolves: bz #1054044, #1070581 + +* Thu Jan 30 2014 Benjamin Marzinski 0.4.9-64 +- Modify 0076-RHBZ-1056686-add-hw_str_match.patch + * Fix memory leak +- Resolves: bz #1056686 + +* Wed Jan 29 2014 Benjamin Marzinski 0.4.9-63 +- Modify 0072-RHBZ-1039199-check-loop-control.patch + * only call close on the /dev/loop-control fd the open succeeds +- Add 0073-RH-update-build-flags.patch + * fix print call to work with -Werror=format-security compile flag, and + change compilation flags for non-rpmbuild compiles +- Add 0074-RHBZ-1056976-dm-mpath-rules.patch + * Add rules to keep from doing work in udev if there are no + active paths, or if the event was for a multipath device + reloading its table due to a path change. +- Add 0075-RHBZ-1056976-reload-flag.patch + * multipath code to identify reloads that the new rules can + ignore +- Add 0076-RHBZ-1056686-add-hw_str_match.patch + * add a new default config paramter, "hw_str_match", to make user + device configs only overwrite builtin device configs if the + identifier strings match exactly, like the default in RHEL6. +- Add 0077-RHBZ-1054806-mpathconf-always-reload.patch + * Make mpathconf always reconfgure multipathd when you run it with + a reconfigure option and --with-multipathd=y, even if the + configuration doesn't change. +- Update Requires and BuildRequires for device-mapper to 1.02.82-2 +- Install new udev rules file /usr/lib/udev/rules.d/11-dm-mpath.rules +- Related: bz #1039199 +- Resolves: bz #1054806, #1056686, #1056976 + +* Fri Jan 24 2014 Daniel Mach - 0.4.9-62 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 0.4.9-61 +- Mass rebuild 2013-12-27 + +* Wed Dec 11 2013 Benjamin Marzinski 0.4.9-60 +- Add 0072-RHBZ-1039199-check-loop-control.patch + * Make kpartx use LOOP_CTL_GET_FREE and loop-control to find a free + loop device. This will autoload the loop module. +- Resolves: bz #1039199 + +* Mon Dec 9 2013 Benjamin Marzinski 0.4.9-59 +- Add 0067-RHBZ-1022899-fix-udev-partition-handling.patch + * Make sure to wipe partition devices on change event if they weren't + wiped on the device add event +- Add 0068-RHBZ-1034578-label-partition-devices.patch + * Make sure that partition devices are labeled like the whole device +- Add 0069-UPBZ-1033791-improve-rdac-checker.patch + * Use RTPG data in RDAC checker +- Add 0070-RHBZ-1036503-blacklist-td-devs.patch +- Add 0071-RHBZ-1031546-strip-dev.patch + * make multipathd interactive commands able to handle /dev/ + instead of just +- Resolves: bz #1022899, #1031546, #1033791, #1034578, #1036503 + +* Thu Oct 24 2013 Benjamin Marzinski 0.4.9-58 +- 0066-UP-dos-4k-partition-fix.patch + * Make kpartx correctly handle 4K sector size devices with dos partitions. +- Resolves: bz #1018439 + +* Fri Sep 27 2013 Benjamin Marzinski 0.4.9-57 +- Add 0065-UPBZ-995538-fail-rdac-on-unavailable.patch + * make rdac checker always mark paths with asymmetric access state of + unavailable as down +- Resolves: bz #995538 + +* Wed Sep 25 2013 Benjamin Marzinski 0.4.9-56 +- Add 0064-RHBZ-1010040-fix-ID_FS-attrs.patch + * make multipath create a timestamp file /run/multipathd/timestamp, and + add -T: option to shortcut processing if the + timestamp hasn't changed +- Resolves: bz #1010040 + +* Fri Sep 6 2013 Benjamin Marzinski 0.4.9-55 +- Add 0061-RH-display-find-mpaths.patch +- Add 0062-RH-dont-free-vecs.patch + * freeing vecs causes a number of races which can crash multipathd on + shutdown. +- Add 0063-RH-fix-warning.patch + +* Thu Jul 25 2013 Benjamin Marzinski 0.4.9-54 +- Modify 0015-RH-fix-output-buffer.patch + * Fix memory leak +- Add 0047-RHBZ-kpartx-read-only-loop-devs.patch + * Fix read only loop device handling +- Add 0048-RH-print-defaults.patch +- Add 0049-RH-remove-ID_FS_TYPE.patch + * remove ID_FS_TYPE udev enviroment variable for multipath devices +- Add 0051-UP-fix-cli-resize.patch + * check before dereferencing variables +- Add 0052-RH-fix-bad-derefs.patch + * setup multipath free the multipath device when it fails, so don't keep + using it. +- Add 0053-UP-fix-failback.patch + * setting failback in the devices section was broken +- Add 0054-UP-keep-udev-ref.patch + * multipathd needs to keep the same udev object across reconfigures +- Add 0055-UP-handle-quiesced-paths.patch + * quiesced paths should be treated as down +- Add 0056-UP-alua-prio-fix.patch + * Don't count the preferred bit for paths that are active/optimized +- Add 0057-UP-fix-tmo.patch + * Cleanup how multipath sets dev_loss_tmo and fast_io_fail_tmo. Also + make multipath get changing values directly from sysfs, instead of + from udev, which caches them. +- Add 0058-UP-fix-failback.patch + * make failback print the default value when you show configs. +- Add 0059-UP-flush-failure-queueing.patch + * If you can't flush a multipath device, restore the queue_if_no_paths + value +- Add 0060-UP-uevent-loop-udev.patch + * make ueventloop grab it's own udev reference, since it is cancelled + asychnrously. + +* Wed Jul 3 2013 Benjamin Marzinski 0.4.9-53 +- Add 0044-RHBZ-976688-fix-wipe-wwids.patch + * Seek back to the start of the file after truncating it +- Add 0045-RHBZ-977297-man-page-fix.patch + * update man page to match actual defaults +- Add 0046-RHBZ-883981-move-udev-rules.patch + * move udev rules file from /lib to /usr/lib +- Resolves: bz #883981, #976688, #977297 + +* Fri Jun 21 2013 Benjamin Marzinski 0.4.9-52 +- Add 0038-RHBZ-799860-netapp-config.patch +- Add 0039-RH-detect-prio-fix.patch + * Don't autodetect ALUA prioritizer unless it actually can get a priority +- Add 0040-RH-bindings-fix.patch + * Do a better job of trying to get the first free user_friendly_name +- Add 0041-RH-check-for-erofs.patch + * Don't create/reload a device read-only unless doing it read/write fails + with EROFS +- Remove 0017-RH-fix-sigusr1.patch + * fix signal handling upstream way instead +- Add 0042-UP-fix-signal-handling.patch + * uxlsnr now handles all the signals sent to multipathd. This makes its + signal handling posix compliant, and harder to mess up. +- Add 0043-RH-signal-waiter.patch + * ioctl isn't a pthread cancellation point. Send a signal to the waiter + thread to break out of waiting in ioctl for a dm event. + +* Fri May 17 2013 Benjamin Marzinski 0.4.9-51 +- Add 0032-RHBZ-956464-mpathconf-defaults.patch + * fix defaults listed in usage +- Add 0033-RHBZ-829963-e-series-conf.patch +- Add 0034-RHBZ-851416-mpathconf-display.patch + * display whether or not multipathd is running in the status +- Add 0035-RHBZ-891921-list-mpp.patch + * add a new path format wilcard to list the multipath device associated + with a path +- Add 0036-RHBZ-949239-load-multipath-module.patch + * load the dm-multipath kernel module when multipathd starts +- Add 0037-RHBZ-768873-fix-rename.patch + * When deciding on a multipth devices name on reload, don't default to + the existing name if there is no config file alias and user_friendly_names + isn't set. Use the wwid. +- Modify multipath.conf +- Resolves: bz #768873, #950252 + +* Tue Apr 30 2013 Benjamin Marzinski 0.4.9-50 +- Add 0031-RHBZ-957188-kpartx-use-dm-name.patch + * use the basename of the devices that will be created to choose the + delimiter instead of using the device name from the command line +- Resolves: bz #957188 + +* Fri Apr 26 2013 Benjamin Marzinski 0.4.9-49 +- Modify 0020-RHBZ-907360-static-pthread-init.patch + * Don't initialize uevent list twice +- Add 0029-RH-no-prio-put-msg.patch +- Add 0030-RHBZ-916528-override-queue-no-daemon.patch + * Default to "queue_without_daemon no" + * Add "forcequeueing daemon" and "restorequeueing daemon" cli commands +- Modify spec file to force queue_without_daemon when restarting + multipathd on upgrades. + +* Thu Apr 4 2013 Benjamin Marzinski 0.4.9-48 +- Add 0026-fix-checker-time.patch + * Once multipathd hit it max checker interval, it was reverting to + to shortest checker interval +- Add 0027-RH-get-wwid.patch + * Multipath wasn't correctly setting the multipath wwid when it read devices + in from the kernel +- Add 0028-RHBZ-929078-refresh-udev-dev.patch + * Make multipath try to get the UID of down devices. Also, on ev_add_path, + make multipathd reinitialize existing devices that weren't fully + initialized before. + +* Mon Apr 1 2013 Benjamin Marzinski 0.4.9-47 +- Add 0021-RHBZ-919119-respect-kernel-cmdline.patch + * keep the multipath.rules udev file from running and multipathd from + starting if nompath is on the kernel command line +- Add 0022-RH-multipathd-check-wwids.patch + * Whenever multipath runs configure, it will check the wwids, and + add any missing ones to the wwids file +- Add 0023-RH-multipath-wipe-wwid.patch + * multipath's -w command will remove a wwid from the wwids file +- Add 0024-RH-multipath-wipe-wwids.patch + * multipath's -W command will set reset the wwids file to just the current + devices +- Add 0025-UPBZ-916668_add_maj_min.patch +- Resolves: bz #919119 + +* Thu Mar 28 2013 Benjamin Marzinski 0.4.9-46 +- Add 0020-RHBZ-907360-static-pthread-init.patch + * statically initialize the uevent pthread structures + +* Sat Mar 2 2013 Benjamin Marzinski 0.4.9-45 +- Updated to latest upstrem 0.4.9 code: multipath-tools-130222 + (git commit id: 67b82ad6fe280caa1770025a6bb8110b633fa136) +- Refresh 0001-RH-dont_start_with_no_config.patch +- Modify 0002-RH-multipath.rules.patch +- Modify 0003-RH-Make-build-system-RH-Fedora-friendly.patch +- Refresh 0004-RH-multipathd-blacklist-all-by-default.patch +- Refresh 0005-RH-add-mpathconf.patch +- Refresh 0006-RH-add-find-multipaths.patch +- Add 0008-RH-revert-partition-changes.patch +- Rename 0008-RH-RHEL5-style-partitions.patch to + 0009-RH-RHEL5-style-partitions.patch +- Rename 0009-RH-dont-remove-map-on-enomem.patch to + 0010-RH-dont-remove-map-on-enomem.patch +- Rename 0010-RH-deprecate-uid-gid-mode.patch to + 0011-RH-deprecate-uid-gid-mode.patch +- Rename 0013-RH-kpartx-msg.patch to 0012-RH-kpartx-msg.patch +- Rename 0035-RHBZ-883981-cleanup-rpmdiff-issues.patch to + 0013-RHBZ-883981-cleanup-rpmdiff-issues.patch +- Rename 0039-RH-handle-other-sector-sizes.patch to + 0014-RH-handle-other-sector-sizes.patch +- Rename 0040-RH-fix-output-buffer.patch to 0015-RH-fix-output-buffer.patch +- Add 0016-RH-dont-print-ghost-messages.patch +- Add 0017-RH-fix-sigusr1.patch + * Actually this fixes a number of issues related to signals +- Rename 0018-RH-remove-config-dups.patch to 0018-RH-fix-factorize.patch + * just the part that isn't upstream +- Add 0019-RH-fix-sockets.patch + * makes abstract multipathd a cli sockets use the correct name. +- Set find_multipaths in the default config + +* Wed Feb 20 2013 Benjamin Marzinski 0.4.9-44 +- Add 0036-UP-fix-state-handling.patch + * handle transport-offline and quiesce sysfs state +- Add 0037-UP-fix-params-size.patch +- Add 0038-RH-fix-multipath.rules.patch + * make sure multipath's link priority gets increased +- Add 0039-RH-handle-other-sector-sizes.patch + * allow gpt partitions on 4k sector size block devices. +- Add 0040-RH-fix-output-buffer.patch + * fix multipath -ll for large configuration. + +* Wed Feb 13 2013 Fedora Release Engineering - 0.4.9-43 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Fri Dec 21 2012 Benjamin Marzinski 0.4.9-42 +- Add 0034-RHBZ-887737-check-for-null-key.patch +- Add 0035-RHBZ-883981-cleanup-rpmdiff-issues.patch + * Compile multipathd with full RELRO and PIE and install to /usr + +* Mon Dec 17 2012 Benjamin Marzinski 0.4.9-41 +- Add 0033-RH-dont-disable-libdm-failback-for-sync-case.patch + * make kpartx -s and multipath use libdm failback device creation, so + that they work in environments without udev + +* Fri Nov 30 2012 Benjamin Marzinski 0.4.9-40 +- Add 0032-RH-make-path-fd-readonly.patch + * revert change made when adding persistent reservations, so that path fds + are again opened O_RDONLY + +* Fri Nov 30 2012 Benjamin Marzinski 0.4.9-39 +- Add 0031-RHBZ-882060-fix-null-strncmp.patch + +* Fri Nov 30 2012 Benjamin Marzinski 0.4.9-38 +- Add 0026-RH-fix-mpathpersist-fns.patch +- Add 0027-RH-default-partition-delimiters.patch + * Only use the -p delimiter when the device name ends in a number +- Add 0028-RH-storagetek-config.patch +- Add 0029-RH-kpartx-retry.patch + * retry delete on busy loop devices +- Add 0030-RH-early-blacklist.patch + * multipath will now blacklist devices by device type and wwid in + store_pathinfo, so that it doesn't do a bunch of unnecessary work + on paths that it would only be removing later on. + +* Sat Nov 03 2012 Peter Rajnoha 0.4.9-37 +- Install multipathd.service for sysinit.target instead of multi-user.target. + +* Thu Nov 01 2012 Peter Rajnoha 0.4.9-36 +- Start multipathd.service systemd unit before LVM units. + +* Wed Oct 24 2012 Benjamin Marzinski 0.4.9-35 +- Add 0022-RHBZ-864368-disable-libdm-failback.patch + * make kpartx and multiapthd disable libdm failback device creation +- Add 0023-RHBZ-866291-update-documentation.patch +- Resolves: bz #864368, #866291 + +* Tue Oct 23 2012 Benjamin Marzinski 0.4.9-34 +- Add 0021-RH-fix-oom-adj.patch + * don't use OOM_ADJUST_MIN unless you're sure it's defined + +* Tue Oct 23 2012 Benjamin Marzinski 0.4.9-33 +- Modify 0016-RH-retain_hwhandler.patch + * Check the dm-multipath module version, and don't enable + retain_attached_hw_handler if the kernel doesn't support it +- Add 0019-RH-detect-prio.patch + * add detect_prio option, to make multipath check if the device + supports the ALUA prio, before defaulting to the configured prio +- Remove 0017-RH-netapp_config.patch +- Add 0020-RH-netapp-config.patch + * new netapp config that uses retain_attached_hw_handler and + detect_prio to autoconfigure ALUA and non-ALUA devices. + +* Tue Oct 2 2012 Benjamin Marzinski 0.4.9-32 +- Modified 0018-RH-remove-config-dups.patch + * Made modified config remove original only if the vendor/product + exactly match + +* Thu Sep 27 2012 Benjamin Marzinski 0.4.9-31 +- Add 0014-RH-dm_reassign.patch + * Fix reassign_maps option +- Add 0015-RH-selector_change.patch + * devices default to using service-time selector +- Add 0016-RH-retain_hwhandler.patch + * add retain_attached_hw_handler option, to let multipath keep an + already attached scsi device handler +- Add 0017-RH-netapp_config.patch +- Add 0018-RH-remove-config-dups.patch + * Clean up duplicates in the devices and blacklist sections + +* Wed Sep 05 2012 Václav Pavlín - 0.4.9-30 +- Scriptlets replaced with new systemd macros (#850088) + +* Tue Aug 21 2012 Benjamin Marzinski 0.4.9-29 +- Updated to latest upstrem 0.4.9 code: multipath-tools-120821.tgz + (git commit id: 050b24b33d3c60e29f7820d2fb75e84a9edde528) + * includes 0001-RH-remove_callout.patch, 0002-RH-add-wwids-file.patch, + 0003-RH-add-followover.patch, 0004-RH-fix-cciss-names.patch +- Add 0013-RH-kpartx-msg.patch +- Modify 0002-RH-multipath.rules.patch + * removed socket call from rules file + +* Wed Jul 18 2012 Fedora Release Engineering - 0.4.9-28 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu Jun 28 2012 Benjamin Marzinski 0.4.9-27 +- Updated to latest upstream 0.4.9 code : multipath-tools-120613.tgz + (git commit id: cb0f7127ba90ab5e8e71fc534a0a16cdbe96a88f) +- Add 0001-RH-remove_callout.patch + * multipath no longer uses the getuid callout. It now gets the + wwid from the udev database or the environment variables +- Add 0004-RH-fix-cciss-names.patch + * convert cciss device names from cciss/cXdY to sysfs style cciss!cXdY +- Split 0009-RH-add-find-multipaths.patch into 0002-RH-add-wwids-file.patch + and 0010-RH-add-find-multipaths.patch +- Add 0016-RH-change-configs.patch + * default fast_io_fail to 5 and don't set the path selector in the + builtin configs. +Resolves: bz #831978 + + +* Thu May 17 2012 Benjamin Marzinski 0.4.9-26 +- Add 0025-RHBZ-822714-update-nodes.patch +- Resolves: bz #822714 + +* Mon Apr 30 2012 Benjamin Marzinski 0.4.9-25 +- Modify 0024-RH-libudev-monitor.patch +- Resolves: bz #805493 + +* Mon Apr 30 2012 Benjamin Marzinski 0.4.9-24 +- Add requirements on libudev to spec file +- Resolves: bz #805493 + +* Mon Apr 30 2012 Benjamin Marzinski 0.4.9-23 +- Add 0024-RH-libudev-monitor.patch + +* Fri Feb 10 2012 Benjamin Marzinski 0.4.9-22 +- Add 0012-RH-update-on-show-topology.patch +- Add 0013-RH-manpage-update.patch +- Add 0014-RH-RHEL5-style-partitions.patch +- Add 0015-RH-add-followover.patch +- Add 0016-RH-dont-remove-map-on-enomem.patch +- Add 0017-RH-fix-shutdown-crash.patch +- Add 0018-RH-warn-on-bad-dev-loss-tmo.patch +- Add 0019-RH-deprecate-uid-gid-mode.patch +- Add 0020-RH-dont-remove-map-twice.patch +- Add 0021-RH-validate-guid-partitions.patch +- Add 0022-RH-adjust-messages.patch +- Add 0023-RH-manpage-update.patch + +* Tue Jan 24 2012 Benjamin Marzinski 0.4.9-21 +- Updated to latest upstream 0.4.9 code : multipath-tools-120123.tgz + (git commit id: 63704387009443bdb37d9deaaafa9ab121d45bfb) +- Add 0001-RH-fix-async-tur.patch +- Add 0002-RH-dont_start_with_no_config.patch +- Add 0003-RH-multipath.rules.patch +- Add 0004-RH-update-init-script.patch +- Add 0005-RH-cciss_id.patch +- Add 0006-RH-Make-build-system-RH-Fedora-friendly.patch +- Add 0007-RH-multipathd-blacklist-all-by-default.patch +- Add 0008-RH-add-mpathconf.patch +- Add 0009-RH-add-find-multipaths.patch +- Add 0010-RH-check-if-multipath-owns-path.patch +- Add 0011-RH-add-hp_tur-checker.patch + +* Fri Jan 13 2012 Fedora Release Engineering - 0.4.9-20 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Sep 20 2011 Benjamin Marzinski -0.4.9-19 +- Modify 0103-add-disable-sync-option.patch +- Add 0104-RHBZ-737989-systemd-unit-fix.patch + * systemd will only start multipathd if /etc/multipath.conf exists +- Add 0105-fix-oom-adj.patch + * first try setting oom_score_adj + +* Mon Aug 15 2011 Kalev Lember - 0.4.9-18 +- Rebuilt for rpm bug #728707 + +* Tue Jul 19 2011 Benjamin Marzinski -0.4.9-17 +- Add 0103-add-disable-sync-option.patch + * add a -n (nosync) option to multipath. This disables synchronous + file creation with udev. + +* Fri Jul 15 2011 Benjamin Marzinski -0.4.9-16 +- Modify 0012-RH-udev-sync-support.patch +- Modify 0021-RHBZ-548874-add-find-multipaths.patch +- Modify 0022-RHBZ-557845-RHEL5-style-partitions.patch +- Add 0025-RHBZ-508827-update-multipathd-manpage.patch through + 0101-RHBZ-631009-disable-udev-disk-rules-on-reload.patch + * sync with current state of RHEL6. Next release should include a updated + source tarball with most of these fixes rolled in. +- Add 0102-RHBZ-690828-systemd-unit-file.patch + * Add Jóhann B. Guðmundsson's unit file for systemd. + * Add sub-package sysvinit for SysV init script. +- Resolves: bz #690828 + +* Tue Feb 08 2011 Fedora Release Engineering - 0.4.9-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Tue Feb 16 2010 Benjamin Marzinski -0.4.9-14 +- Modify 0021-RHBZ-548874-add-find-multipaths.patch + * fix bug where mpathconf wouldn't create a multpath.conf file unless one + already existed. + +* Tue Feb 16 2010 Benjamin Marzinski -0.4.9-13 +- Replace 0012-RH-explicitly-disable-dm-udev-sync-support-in-kpartx.patch + with 0012-RH-udev-sync-support.patch + * Add udev sync support to kpartx and multipath. In kpartx it is disabled + unless you use the -s option. +- Refresh 0013-RH-add-weighted_prio-prioritizer.patch +- Refresh 0021-RHBZ-548874-add-find-multipaths.patch +- Modify 0022-RHBZ-557845-RHEL5-style-partitions.patch + * kpartx now creates a 2 sector large device for dos extended + partitions, just like the kernel does on the regular block devices. +- Add 0023-RHBZ-557810-emc-invista-config.patch +- Add 0024-RHBZ-565933-checker-timeout.patch + * Multipath has a new option checker_timeout. If this is not set, + all path checker functions with explicit timeouts use + /sys/block/sd/device/timeout. If this is set, they use it instead. + +* Fri Jan 22 2010 Benjamin Marzinski -0.4.9-12 +- Refresh 0001-RH-queue-without-daemon.patch +- Refresh 0002-RH-path-checker.patch +- Modify 0010-RH-multipath-rules-udev-changes.patch + * Fix udev rules to use DM_SBIN_PATH when calling kpartx + * install udev rules to /lib/udev/rules.d instead of /etc/udev/rules.d +- Modify 0014-RH-add-hp_tur-checker.patch +- Add 0003-for-upstream-default-configs.patch +- Add 0016-RHBZ-554561-fix-init-error-msg.patch +- Add 0017-RHBZ-554592-man-page-note.patch +- Add 0018-RHBZ-554596-SUN-6540-config.patch +- Add 0019-RHBZ-554598-fix-multipath-locking.patch +- Add 0020-RHBZ-554605-fix-manual-failover.patch +- Add 0021-RHBZ-548874-add-find-multipaths.patch + * Added find_multipaths multipath.conf option + * Added /sbin/mpathconf for simple editting of multipath.conf +- Add 0022-RHBZ-557845-RHEL5-style-partitions.patch + * Make kpartx deal with logical partitions like it did in RHEL5. + Don't create a dm-device for the extended partition itself. + Create the logical partitions on top of the dm-device for the whole disk. + +* Mon Nov 16 2009 Benjamin Marzinski -0.4.9-11 +- Add 0002-for-upstream-add-tmo-config-options.patch + * Add fail_io_fail_tmo and dev_loss_tmo multipath.conf options +- Add 0013-RH-add-weighted_prio-prioritizer.patch +- Add 0014-RH-add-hp_tur-checker.patch +- Add 0015-RH-add-multipathd-count-paths-cmd.patch +- rename multipath.conf.redhat to multipath.conf, and remove the default + blacklist. + +* Tue Oct 27 2009 Fabio M. Di Nitto - 0.4.9-10 +- Updated to latest upstream 0.4.9 code : multipath-tools-091027.tar.gz + (git commit id: a946bd4e2a529e5fba9c9547d03d3f91806618a3) +- Drop unrequired for-upstream patches. +- BuildRequires and Requires new device-mapper version for udev sync support. + +* Tue Oct 20 2009 Fabio M. Di Nitto - 0.4.9-9 +- 0012-RH-explicitly-disable-dm-udev-sync-support-in-kpartx.patch + +* Mon Oct 19 2009 Fabio M. Di Nitto - 0.4.9-8 +- Split patches in "for-upstream" and "RH" series. +- Replace 0011-RH-multipathd-blacklist-all-by-default.patch with + version from Benjamin Marzinski. +- Update udev rules 0010-RH-multipath-rules-udev-changes.patch. +- rpmlint cleanup: + * Drop useless-provides kpartx. + * Cleanup tab vs spaces usage. + * Summary not capitalized. + * Missing docs in libs package. + * Fix init script LSB headers. +- Drop README* files from doc sections (they are empty). + +* Thu Oct 15 2009 Fabio M. Di Nitto - 0.4.9-7 +- Add patch 0010-RH-Set-friendly-defaults.patch: + * set rcdir to fedora default. + * do not install kpartx udev bits. + * install redhat init script. + * Cleanup spec file install target. +- Add patch 0011-RH-multipathd-blacklist-all-by-default.patch: + * Fix BZ#528059 + * Stop installing default config in /etc and move it to the doc dir. + +* Tue Oct 13 2009 Fabio M. Di Nitto - 0.4.9-6 +- Updated to latest upstream 0.4.9 code : multipath-tools-091013.tar.gz + (git commit id: aa0a885e1f19359c41b63151bfcface38ccca176) +- Drop, now upstream, patches: + * fix_missed_uevs.patch. + * log_all_messages.patch. + * uninstall.patch. + * select_lib.patch. + * directio_message_cleanup.patch. + * stop_warnings.patch. +- Drop redhatification.patch in favour of spec file hacks. +- Drop mpath_wait.patch: no longer required. +- Merge multipath_rules.patch and udev_change.patch. +- Rename all patches based on source. +- Add patch 0009-RH-fix-hp-sw-hardware-table-entries.patch to fix + default entry for hp_sw and match current kernel. +- Add multipath.conf.redhat as source instead of patch. +- spec file: + * divide runtime and build/setup bits. + * update BuildRoot. + * update install section to apply all the little hacks here and there, + in favour of patches against upstream. + * move ldconfig invokation to libs package where it belong. + * fix libs package directory ownership and files. + +* Thu Aug 20 2009 Benjamin Marzinski - 0.4.9-5 +- Fixed problem where maps were being added and then removed. +- Changed the udev rules to fix some issues. + +* Thu Jul 30 2009 Benjamin Marzinski - 0.4.9-4 +- Fixed build issue on i686 machines. + +* Wed Jul 29 2009 Benjamin Marzinski - 0.4.9-3 +- Updated to latest upstream 0.4.9 code : multipath-tools-090729.tgz + (git commit id: d678c139719d5631194b50e49f16ca97162ecd0f) +- moved multipath bindings file from /var/lib/multipath to /etc/multipath +- Fixed 354961, 432520 + +* Fri Jul 24 2009 Fedora Release Engineering - 0.4.9-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Wed May 6 2009 Mike Snitzer - 0.4.9-1 +- Updated to latest upstream 0.4.9 code: multipath-tools-090429.tgz + (git commit id: 7395bcda3a218df2eab1617df54628af0dc3456e) +- split the multipath libs out to a device-mapper-multipath-libs package +- if appropriate, install multipath libs in /lib64 and /lib64/multipath + +* Tue Apr 7 2009 Milan Broz - 0.4.8-10 +- Fix insecure permissions on multipathd.sock (CVE-2009-0115) + +* Fri Mar 6 2009 Milan Broz - 0.4.8-9 +- Fix kpartx extended partition handling (475283) + +* Tue Feb 24 2009 Fedora Release Engineering - 0.4.8-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Fri Sep 26 2008 Benjamin Marzinski 0.4.8-7 +- Since libaio is now in /lib, not /usr/lib, multipath no longer needs to + statically link against it. Fixed an error with binding file and WWIDs + that include spaces. Cleaned up the messages from the directio checker + function. Fixed the udev rules. Fixed a regression in multipath.conf + parsing +- Fixed 457530, 457589 + +* Wed Aug 20 2008 Benjamin Marzinski 0.4.8-6 +- Updated to latest upstream 0.4.8 code: multipath-tools-080804.tgz + (git commit id: eb87cbd0df8adf61d1c74c025f7326d833350f78) +- fixed 451817, 456397 (scsi_id_change.patch), 457530 (config_space_fix.patch) + 457589 (static_libaio.patch) + +* Fri Jun 13 2008 Alasdair Kergon - 0.4.8-5 +- Rebuild (rogue vendor tag). (451292) + +* Mon May 19 2008 Benjamin Marzinksi 0.4.8-4 +- Fixed Makefile issues. + +* Mon May 19 2008 Benjamin Marzinksi 0.4.8-3 +- Fixed ownership build error. + +* Mon May 19 2008 Benjamin Marzinksi 0.4.8-2 +- Forgot to commit some patches. + +* Mon May 19 2008 Benjamin Marzinski 0.4.8-1 +- Updated to latest Upstream 0.4.8 code: multipath-tools-080519.tgz + (git commit id: 42704728855376d2f7da2de1967d7bc71bc54a2f) + +* Tue May 06 2008 Alasdair Kergon - 0.4.7-15 +- Remove unnecessary multipath & kpartx static binaries. (bz 234928) + +* Fri Feb 29 2008 Tom "spot" Callaway - 0.4.7-14 +- fix sparc64 +- fix license tag + +* Tue Feb 19 2008 Fedora Release Engineering - 0.4.7-13 +- Autorebuild for GCC 4.3 + +* Wed Nov 14 2007 Benjamin Marzinski - 0.4.7-12 +- Fixed the dist tag so building will work properly. + +* Mon Feb 05 2007 Alasdair Kergon - 0.4.7-11.fc7 +- Add build dependency on new device-mapper-devel package. +- Add dependency on device-mapper. + +* Wed Jan 31 2007 Benjamin Marzinksi - 0.4.7-10.fc7 +- Update BuildRoot and PreReq lines. + +* Mon Jan 15 2007 Benjamin Marzinksi - 0.4.7-9.fc7 +- Fixed spec file. + +* Mon Jan 15 2007 Benjamin Marzinski - 0.4.7-8.fc7 +- Update to latest code (t0_4_7_head2) + +* Wed Dec 13 2006 Benjamin Marzinski - 0.4.7-7.fc7 +- Update to latest code (t0_4_7_head1) + +* Thu Sep 7 2006 Peter Jones - 0.4.7-5 +- Fix kpartx to handle with drives >2TB correctly. + +* Thu Aug 31 2006 Peter Jones - 0.4.7-4.1 +- Split kpartx out into its own package so dmraid can use it without + installing multipathd +- Fix a segfault in kpartx + +* Mon Jul 17 2006 Benjamin Marzinski 0.4.7-4.0 +- Updated to latest source. Fixes bug in default multipath.conf + +* Wed Jul 12 2006 Benjamin Marzinski 0.4.7-3.1 +- Added ncurses-devel to BuildRequires + +* Wed Jul 12 2006 Benjamin Marzinski 0.4.7-3.0 +- Updated to latest source. deals with change in libsysfs API + +* Wed Jul 12 2006 Jesse Keating - 0.4.7-2.2.1 +- rebuild + +* Mon Jul 10 2006 Benjamin Marzinski 0.4.7-2.2 +- fix tagging issue. + +* Mon Jul 10 2006 Benjamin Marzinski 0.4.7-2.1 +- changed BuildRequires from sysfsutils-devel to libsysfs-devel + +* Wed Jun 28 2006 Benjamin Marzinski 0.4.7-2.0 +- Updated to latest upstream source, fixes kpartx udev rule issue + +* Tue Jun 06 2006 Benjamin Marzinski 0.4.7-1.0 +- Updated to Christophe's latest source + +* Mon May 22 2006 Alasdair Kergon - 0.4.5-16.0 +- Newer upstream source (t0_4_5_post59). + +* Mon May 22 2006 Alasdair Kergon - 0.4.5-12.3 +- BuildRequires: libsepol-devel, readline-devel + +* Mon Feb 27 2006 Benjamin Marzinski 0.4.5-12.2 +- Prereq: chkconfig + +* Mon Feb 20 2006 Karsten Hopp 0.4.5-12.1 +- BuildRequires: libselinux-devel + +* Fri Feb 10 2006 Jesse Keating - 0.4.5-12.0.1 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Benjamin Marzinski -0.4.5-12.0 +- Updated to latest upstream source (t0_4_5_post56) + +* Tue Feb 07 2006 Jesse Keating - 0.4.5-9.1.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Mon Dec 19 2005 Benjamin Marzinski - 0.4.5-9.1 +- added patch for fedora changes + +* Fri Dec 16 2005 Benjamin Marzinski - 0.4.5-9.0 +- Updated to latest upstream source (t)_4_5_post52) + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Sun Dec 4 2005 Peter Jones - 0.4.4-2.6 +- rebuild for newer libs + +* Tue Nov 15 2005 Peter Jones - 0.4.4-2.5 +- unsplit kpartx. parted knows how to do this now, so we don't + need this in a separate package. + +* Tue Nov 15 2005 Peter Jones - 0.4.4-2.4 +- split kpartx out into its own package + +* Fri May 06 2005 Bill Nottingham - 0.4.4-2.3 +- Fix last fix. + +* Thu May 05 2005 Alasdair Kergon - 0.4.4-2.2 +- Fix last fix. + +* Wed May 04 2005 Alasdair Kergon - 0.4.4-2.1 +- By default, disable the multipathd service. + +* Tue Apr 19 2005 Alasdair Kergon - 0.4.4-2.0 +- Fix core dump from last build. + +* Tue Apr 19 2005 Alasdair Kergon - 0.4.4-1.0 +- Move cache file into /var/cache/multipath. + +* Fri Apr 08 2005 Alasdair Kergon - 0.4.4-0.pre8.1 +- Remove pp_balance_units. + +* Mon Apr 04 2005 Alasdair Kergon - 0.4.4-0.pre8.0 +- Incorporate numerous upstream fixes. +- Update init script to distribution standards. + +* Tue Mar 01 2005 Alasdair Kergon - 0.4.2-1.0 +- Initial import based on Christophe Varoqui's spec file.