summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2022-01-14 13:50:16 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2022-01-14 13:50:16 +0900
commit49adf6657054f7c3cff8a7c21f93954efa9f88bb (patch)
treeab5b4c2cf18a771469dd2ae25d149924cda529e4
parentc909ffe8ce9605b25a6524b158a8eb6d252ba1b8 (diff)
downloadmultipath-tools-49adf6657054f7c3cff8a7c21f93954efa9f88bb.tar.gz
multipath-tools-49adf6657054f7c3cff8a7c21f93954efa9f88bb.tar.bz2
multipath-tools-49adf6657054f7c3cff8a7c21f93954efa9f88bb.zip
Imported Upstream version 0.6.2upstream/0.6.2
-rw-r--r--.gitignore2
-rw-r--r--AUTHOR1
-rw-r--r--COPYING22
-rw-r--r--FAQ97
-rw-r--r--Makefile11
-rw-r--r--Makefile.inc12
-rw-r--r--README20
-rw-r--r--kpartx/ChangeLog9
-rw-r--r--kpartx/Makefile12
-rw-r--r--kpartx/README9
-rw-r--r--kpartx/crc32.c46
-rw-r--r--kpartx/dasd.c8
-rw-r--r--kpartx/dasd.h104
-rw-r--r--kpartx/devmapper.c25
-rw-r--r--kpartx/dos.c4
-rw-r--r--kpartx/efi.h7
-rw-r--r--kpartx/gpt.c282
-rw-r--r--kpartx/gpt.h19
-rw-r--r--kpartx/kpartx.815
-rw-r--r--kpartx/kpartx.c21
-rw-r--r--kpartx/kpartx.rules2
-rw-r--r--kpartx/lopart.c51
-rw-r--r--kpartx/mac.c4
-rw-r--r--kpartx/mac.h18
-rw-r--r--kpartx/ps3.c7
-rw-r--r--kpartx/solaris.c5
-rw-r--r--kpartx/sun.c1
-rw-r--r--kpartx/unixware.c6
-rw-r--r--libmpathcmd/Makefile14
-rw-r--r--libmpathcmd/mpath_cmd.c2
-rw-r--r--libmpathcmd/mpath_cmd.h67
-rw-r--r--libmpathpersist/Makefile44
-rw-r--r--libmpathpersist/mpath_persist.c82
-rw-r--r--libmpathpersist/mpath_persist.h36
-rw-r--r--libmpathpersist/mpath_persistent_reserve_in.310
-rw-r--r--libmpathpersist/mpath_persistent_reserve_out.314
-rw-r--r--libmpathpersist/mpath_pr_ioctl.c119
-rw-r--r--libmpathpersist/mpath_pr_ioctl.h2
-rw-r--r--libmpathpersist/mpath_updatepr.c20
-rw-r--r--libmpathpersist/mpathpr.h36
-rw-r--r--libmultipath/Makefile8
-rw-r--r--libmultipath/alias.c11
-rw-r--r--libmultipath/alias.h1
-rw-r--r--libmultipath/blacklist.h2
-rw-r--r--libmultipath/callout.c4
-rw-r--r--libmultipath/checkers.c22
-rw-r--r--libmultipath/checkers.h8
-rw-r--r--libmultipath/checkers/Makefile4
-rw-r--r--libmultipath/checkers/cciss.h1
-rw-r--r--libmultipath/checkers/cciss_tur.c6
-rw-r--r--libmultipath/checkers/directio.c4
-rw-r--r--libmultipath/checkers/emc_clariion.c2
-rw-r--r--libmultipath/checkers/libsg.c3
-rw-r--r--libmultipath/checkers/readsector0.c2
-rw-r--r--libmultipath/checkers/tur.c4
-rw-r--r--libmultipath/config.c44
-rw-r--r--libmultipath/config.h18
-rw-r--r--libmultipath/configure.c183
-rw-r--r--libmultipath/configure.h10
-rw-r--r--libmultipath/debug.c3
-rw-r--r--libmultipath/defaults.h22
-rw-r--r--libmultipath/devmapper.c86
-rw-r--r--libmultipath/devmapper.h4
-rw-r--r--libmultipath/dict.c85
-rw-r--r--libmultipath/dict.h2
-rw-r--r--libmultipath/discovery.c158
-rw-r--r--libmultipath/discovery.h14
-rw-r--r--libmultipath/dmparser.c22
-rw-r--r--libmultipath/dmparser.h2
-rw-r--r--libmultipath/hwtable.c723
-rw-r--r--libmultipath/list.h10
-rw-r--r--libmultipath/lock.c1
-rw-r--r--libmultipath/log_pthread.c3
-rw-r--r--libmultipath/memory.h8
-rw-r--r--libmultipath/parser.c61
-rw-r--r--libmultipath/parser.h33
-rw-r--r--libmultipath/pgpolicies.c14
-rw-r--r--libmultipath/pgpolicies.h2
-rw-r--r--libmultipath/print.c315
-rw-r--r--libmultipath/print.h78
-rw-r--r--libmultipath/prio.c42
-rw-r--r--libmultipath/prio.h36
-rw-r--r--libmultipath/prioritizers/Makefile19
-rw-r--r--libmultipath/prioritizers/alua.c28
-rw-r--r--libmultipath/prioritizers/alua_rtpg.c36
-rw-r--r--libmultipath/prioritizers/alua_rtpg.h9
-rw-r--r--libmultipath/prioritizers/alua_spc3.h3
-rw-r--r--libmultipath/prioritizers/const.c2
-rw-r--r--libmultipath/prioritizers/datacore.c15
-rw-r--r--libmultipath/prioritizers/emc.c16
-rw-r--r--libmultipath/prioritizers/hds.c46
-rw-r--r--libmultipath/prioritizers/hp_sw.c54
-rw-r--r--libmultipath/prioritizers/iet.c11
-rw-r--r--libmultipath/prioritizers/ontap.c29
-rw-r--r--libmultipath/prioritizers/random.c2
-rw-r--r--libmultipath/prioritizers/rdac.c16
-rw-r--r--libmultipath/prioritizers/sysfs.c61
-rw-r--r--libmultipath/prioritizers/weightedpath.c15
-rw-r--r--libmultipath/propsel.c105
-rw-r--r--libmultipath/propsel.h48
-rw-r--r--libmultipath/structs.c5
-rw-r--r--libmultipath/structs.h4
-rw-r--r--libmultipath/structs_vec.c73
-rw-r--r--libmultipath/structs_vec.h13
-rw-r--r--libmultipath/sysfs.c67
-rw-r--r--libmultipath/uevent.c33
-rw-r--r--libmultipath/uxsock.c4
-rw-r--r--libmultipath/vector.h6
-rw-r--r--libmultipath/version.h4
-rw-r--r--libmultipath/waiter.c7
-rw-r--r--libmultipath/wwids.c22
-rw-r--r--mpathpersist/Makefile24
-rw-r--r--mpathpersist/main.c95
-rw-r--r--mpathpersist/main.h3
-rw-r--r--multipath-tools.spec.in58
-rwxr-xr-xmultipath/01_udev2
-rwxr-xr-xmultipath/02_multipath3
-rw-r--r--multipath/Makefile12
-rw-r--r--multipath/main.c319
-rw-r--r--multipath/multipath.conf.5715
-rw-r--r--multipath/multipath.init.suse158
-rw-r--r--multipathd/Makefile15
-rw-r--r--multipathd/cli.c22
-rw-r--r--multipathd/cli.h2
-rw-r--r--multipathd/cli_handlers.c211
-rw-r--r--multipathd/cli_handlers.h3
-rw-r--r--multipathd/main.c376
-rw-r--r--multipathd/multipathd.824
-rw-r--r--multipathd/multipathd.init.debian29
-rw-r--r--multipathd/multipathd.init.redhat152
-rw-r--r--multipathd/multipathd.init.suse200
-rw-r--r--multipathd/pidfile.c8
-rw-r--r--multipathd/uxclnt.c14
-rw-r--r--multipathd/uxlsnr.c27
-rw-r--r--multipathd/uxlsnr.h1
135 files changed, 3236 insertions, 3317 deletions
diff --git a/.gitignore b/.gitignore
index 7f25d0e..aee4ece 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,5 @@ multipath/multipath
multipathd/multipathd
mpathpersist/mpathpersist
.nfs*
+*.swp
+*.patch
diff --git a/AUTHOR b/AUTHOR
deleted file mode 100644
index e55a659..0000000
--- a/AUTHOR
+++ /dev/null
@@ -1 +0,0 @@
-Christophe Varoqui, <christophe.varoqui@opensvc.com>
diff --git a/COPYING b/COPYING
index 0ade0e9..5bc8fb2 100644
--- a/COPYING
+++ b/COPYING
@@ -1,16 +1,15 @@
-
- GNU LIBRARY GENERAL PUBLIC LICENSE
- Version 2, June 1991
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
- Preamble
+ Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -100,7 +99,7 @@ works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
- GNU LIBRARY GENERAL PUBLIC LICENSE
+ GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
@@ -412,7 +411,7 @@ decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
- NO WARRANTY
+ NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
@@ -435,9 +434,9 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
- END OF TERMS AND CONDITIONS
+ END OF TERMS AND CONDITIONS
- Appendix: How to Apply These Terms to Your New Libraries
+ How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
@@ -464,9 +463,8 @@ convey the exclusion of warranty; and each file should have at least the
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
diff --git a/FAQ b/FAQ
deleted file mode 100644
index 040f807..0000000
--- a/FAQ
+++ /dev/null
@@ -1,97 +0,0 @@
-More at http://christophe.varoqui.free.fr/faq.html
-See also http://christophe.varoqui.free.fr/usage.html
-
-1. How to set up System-on-multipath ?
-======================================
-
-prerequisite : udev and multipath-tools installed
-
-here are the steps on a Debian SID system :
-
-* add dm-mpath and dm-multipath to /etc/mkinitrd/modules
-* copy $tools_dir/multipath/0[12]_* to /etc/mkinitrd/scripts
-* define a friendly alias for your multipathed root disk
- (in /etc/multipath.conf). Example : "system"
-* enable busybox in /etc/mkinitrd/mkinitrd.conf and set ROOT
- to any valid block-device (but not a /dev/dm-* one, due to
- an mkintrd misbelief that all dm-* are managed by LVM2)
-* run mkinitrd
-* in /boot/grub/menu.lst, define the root= kernel parameter
- Example : root=/dev/system1
-* modify /etc/fstab to reference /dev/system* partitions
-
-At reboot, you should see some info like :
-
-path /dev/sda : multipath system
-...
-gpt: 0 slices
-dos: 5 slices
-reduced size of partition #2 to 63
-Added system1 : 0 70685937 linear /dev/system 63
-Added system2 : 0 63 linear /dev/system 7068600
-Added system5 : 0 995967 linear /dev/system 70686063
-...
-
-2. How does it compare to commercial product XXX ?
-==================================================
-
-Here are a few distinctive features :
-
-* you can mix HBA models, even different vendors, different speed ...
-* you can mix storage controllers on your SAN, and access them all, applying
- different path grouping policy
-* completely event-driven model : no administration burden if you accept the
- default behaviours
-* extensible : you can plug your own policies if the available ones don't fill
- your needs
-* supports root FS on multipathed SAN
-* free, open-source software
-
-3. LVM2 doesn't see my multipathed devices as PV, what's up ?
-=============================================================
-
-By default, lvm2 does not consider device-mapper block devices (such as a
-dm-crypt device) for use as physical volumes.
-
-In order to use a dm-crypt device as an lvm2 pv, add this line to the
-devices block in /etc/lvm/lvm.conf:
-
-types = [ "device-mapper", 16 ]
-
-If /etc/lvm/lvm.conf does not exist, you can create one based on your
-current/default config like so:
-
-lvm dumpconfig > /etc/lvm/lvm.conf
-
-(tip from Christophe Saout)
-
-4. I see a lot of "io_setup failed" message using the directio checker
-======================================================================
-
-The directio path checker makes use of the asynchronous I/O API (aio) provided
-by modern Linux systems. Asynchronous I/O allows an application to submit I/O
-requests asynchronously and be notified later of their completion status. To
-allow this, we must allocate an asynchronous I/O context (an object of type
-aio_context_t) and this task is handled by the io_setup system call.
-
-A system wide limit on the number of AIO contexts that may be active
-simultaneously is imposed via the aio-max-nr sysctl parameter.
-
-Once this limit has been reached further calls to io_setup will fail with the
-error number EAGAIN leading to the "io_setup failed" messages seen for e.g. when
-running "multipath -ll".
-
-To avoid this problem the number of available aio contexts should be increased
-by setting the aio-max-nr parameter. This can be set on a one-time basis via the
-/proc file system, for e.g.:
-
- # echo 131072 > /proc/sys/fs/aio-max-nr
-
-Doubles the number of available contexts from the default value of 65536.
-
-To make this setting persistent a line may be added to /etc/sysctl.conf:
-
- fs.aio-max-nr = 131072
-
-Consult appropriate application and operating system tuning recommendations for
-guidance on appropriate values for this parameter.
diff --git a/Makefile b/Makefile
index 06f50c8..cf1acd9 100644
--- a/Makefile
+++ b/Makefile
@@ -40,7 +40,7 @@ all: recurse
recurse:
@for dir in $(BUILDDIRS); do \
- $(MAKE) -C $$dir BUILD=$(BUILD) VERSION=$(VERSION) \
+ $(MAKE) -C $$dir VERSION=$(VERSION) \
KRNLSRC=$(KRNLSRC) KRNLOBJ=$(KRNLOBJ) || exit $?; \
done
@@ -60,8 +60,6 @@ recurse_uninstall:
done
clean: recurse_clean
- rm -f multipath-tools.spec
- rm -rf rpms
install: recurse_install
@@ -73,10 +71,3 @@ TAGS:
etags -a libmultipath/*.h
etags -a multipathd/*.c
etags -a multipathd/*.h
-
-release:
- sed -e "s/__VERSION__/${VERSION}/" \
- multipath-tools.spec.in > multipath-tools.spec
-
-rpm: release
- rpmbuild -bb multipath-tools.spec
diff --git a/Makefile.inc b/Makefile.inc
index ecc20ef..3e8635f 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -39,7 +39,7 @@ ifndef SYSTEMDPATH
SYSTEMDPATH=usr/lib
endif
-prefix =
+prefix =
exec_prefix = $(prefix)
bindir = $(exec_prefix)/sbin
libudevdir = $(prefix)/$(SYSTEMDPATH)/udev
@@ -48,7 +48,6 @@ 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
syslibdir = $(prefix)/$(LIB)
incdir = $(prefix)/usr/include
libdir = $(prefix)/$(LIB)/multipath
@@ -57,16 +56,15 @@ mpathpersistdir = $(TOPDIR)/libmpathpersist
mpathcmddir = $(TOPDIR)/libmpathcmd
GZIP = gzip -9 -c
+RM = rm -f
+LN = ln -sf
INSTALL_PROGRAM = install
-ifndef RPM_OPT_FLAGS
- RPM_OPT_FLAGS = -O2 -g -pipe -Wformat-security -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4
-endif
+OPTFLAGS = -Wunused -Wstrict-prototypes -O2 -g -pipe -Wformat-security -Wall \
+ -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4
-OPTFLAGS = $(RPM_OPT_FLAGS) -Wunused -Wstrict-prototypes
CFLAGS = $(OPTFLAGS) -fPIC -DLIB_STRING=\"${LIB}\" -DRUN_DIR=\"${RUN}\"
SHARED_FLAGS = -shared
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
-
diff --git a/README b/README
index 1914e38..c1c53fc 100644
--- a/README
+++ b/README
@@ -1,14 +1,30 @@
multipath-tools for Linux <http://christophe.varoqui.free.fr/>
+
This package provides the following binaries to drive the
Device Mapper multipathing driver:
multipath - Device mapper target autoconfig.
multipathd - Multipath daemon.
mpathpersist - Manages SCSI persistent reservations on dm multipath devices.
-kpartxrtx - Create device maps from partition tables.
+kpartx - Create device maps from partition tables.
+
+
+tarballs are not generated anymore, to get a specific release do:
+git clone http://git.opensvc.com/multipath-tools/.git
+cd multipath-tools
+git tag
+git archive --format=tar.gz --prefix=multipath-tools-X.Y.Z/ X.Y.Z > ../multipath-tools-X.Y.Z.tar.gz
-To get latest code: git clone http://git.opensvc.com/multipath-tools/.git
+Alternatively it may be obtained from gitweb, go to:
+http://git.opensvc.com/?p=multipath-tools/.git;a=tags
+select a release-tag and then click on "snapshot".
+
+
+To get latest devel code: git clone http://git.opensvc.com/multipath-tools/.git
Mailing list: http://www.redhat.com/mailman/listinfo/dm-devel
Gitweb: http://git.opensvc.com/?p=multipath-tools/.git
+Patchwork: http://patchwork.kernel.org/project/dm-devel/list/
+
+Current maintainer is Christophe Varoqui <christophe.varoqui@opensvc.com>
diff --git a/kpartx/ChangeLog b/kpartx/ChangeLog
deleted file mode 100644
index cd0c6c1..0000000
--- a/kpartx/ChangeLog
+++ /dev/null
@@ -1,9 +0,0 @@
-002:
-* convert to kpartx name everywhere
-* remove all HDGEO ioctl code
-* now work with files by mapping loops on the fly
-* merged and massage lopart.[ch] from lomount.[ch]
- (due credit to original author here : hpa ?)
-* added a fn find_loop_by_file in lopart.[ch]
-001:
-* Initial release
diff --git a/kpartx/Makefile b/kpartx/Makefile
index 501b277..5476545 100644
--- a/kpartx/Makefile
+++ b/kpartx/Makefile
@@ -34,11 +34,11 @@ install: $(EXEC) $(EXEC).8
$(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)/rules.d/66-kpartx.rules
- rm -f $(DESTDIR)$(libudevdir)/rules.d/67-kpartx-compat.rules
+ $(RM) $(DESTDIR)$(bindir)/$(EXEC)
+ $(RM) $(DESTDIR)$(mandir)/$(EXEC).8.gz
+ $(RM) $(DESTDIR)$(libudevdir)/kpartx_id
+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/66-kpartx.rules
+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/67-kpartx-compat.rules
clean:
- rm -f core *.o $(EXEC) *.gz
+ $(RM) core *.o $(EXEC) *.gz
diff --git a/kpartx/README b/kpartx/README
deleted file mode 100644
index e0680b1..0000000
--- a/kpartx/README
+++ /dev/null
@@ -1,9 +0,0 @@
-This version of partx is intented to be build
-static against klibc.
-
-It creates partitions as device maps.
-
-With due respect to the original authors,
-
-have fun,
-cvaroqui
diff --git a/kpartx/crc32.c b/kpartx/crc32.c
index 42d803d..b23a083 100644
--- a/kpartx/crc32.c
+++ b/kpartx/crc32.c
@@ -1,4 +1,4 @@
-/*
+/*
* crc32.c
* This code is in the public domain; copyright abandoned.
* Liability for non-performance of this code is limited to the amount
@@ -48,7 +48,7 @@
* other uses, or the previous crc32 value if computing incrementally.
* @p - pointer to buffer over which CRC is run
* @len - length of buffer @p
- *
+ *
*/
uint32_t attribute((pure)) crc32_le(uint32_t crc, unsigned char const *p, size_t len)
{
@@ -106,7 +106,7 @@ crc32cleanup_le(void)
* other uses, or the previous crc32 value if computing incrementally.
* @p - pointer to buffer over which CRC is run
* @len - length of buffer @p
- *
+ *
*/
uint32_t attribute((pure)) crc32_le(uint32_t crc, unsigned char const *p, size_t len)
{
@@ -151,7 +151,7 @@ uint32_t attribute((pure)) crc32_le(uint32_t crc, unsigned char const *p, size_t
* other uses, or the previous crc32 value if computing incrementally.
* @p - pointer to buffer over which CRC is run
* @len - length of buffer @p
- *
+ *
*/
uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t len)
{
@@ -209,7 +209,7 @@ crc32cleanup_be(void)
* other uses, or the previous crc32 value if computing incrementally.
* @p - pointer to buffer over which CRC is run
* @len - length of buffer @p
- *
+ *
*/
uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t len)
{
@@ -277,8 +277,8 @@ uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t
*
* A big-endian CRC written this way would be coded like:
* for (i = 0; i < input_bits; i++) {
- * multiple = remainder & 0x80000000 ? CRCPOLY : 0;
- * remainder = (remainder << 1 | next_input_bit()) ^ multiple;
+ * multiple = remainder & 0x80000000 ? CRCPOLY : 0;
+ * remainder = (remainder << 1 | next_input_bit()) ^ multiple;
* }
* Notice how, to get at bit 32 of the shifted remainder, we look
* at bit 31 of the remainder *before* shifting it.
@@ -297,14 +297,14 @@ uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t
* This changes the code to:
* for (i = 0; i < input_bits; i++) {
* remainder ^= next_input_bit() << 31;
- * multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
- * remainder = (remainder << 1) ^ multiple;
+ * multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
+ * remainder = (remainder << 1) ^ multiple;
* }
* With this optimization, the little-endian code is simpler:
* for (i = 0; i < input_bits; i++) {
* remainder ^= next_input_bit();
- * multiple = (remainder & 1) ? CRCPOLY : 0;
- * remainder = (remainder >> 1) ^ multiple;
+ * multiple = (remainder & 1) ? CRCPOLY : 0;
+ * remainder = (remainder >> 1) ^ multiple;
* }
*
* Note that the other details of endianness have been hidden in CRCPOLY
@@ -314,19 +314,19 @@ uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t
* order, we can actually do the merging 8 or more bits at a time rather
* than one bit at a time:
* for (i = 0; i < input_bytes; i++) {
- * remainder ^= next_input_byte() << 24;
- * for (j = 0; j < 8; j++) {
- * multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
- * remainder = (remainder << 1) ^ multiple;
- * }
+ * remainder ^= next_input_byte() << 24;
+ * for (j = 0; j < 8; j++) {
+ * multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
+ * remainder = (remainder << 1) ^ multiple;
+ * }
* }
* Or in little-endian:
* for (i = 0; i < input_bytes; i++) {
- * remainder ^= next_input_byte();
- * for (j = 0; j < 8; j++) {
- * multiple = (remainder & 1) ? CRCPOLY : 0;
- * remainder = (remainder << 1) ^ multiple;
- * }
+ * remainder ^= next_input_byte();
+ * for (j = 0; j < 8; j++) {
+ * multiple = (remainder & 1) ? CRCPOLY : 0;
+ * remainder = (remainder << 1) ^ multiple;
+ * }
* }
* If the input is a multiple of 32 bits, you can even XOR in a 32-bit
* word at a time and increase the inner loop count to 32.
@@ -340,7 +340,7 @@ uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t
* in the correct multiple to subtract, we can shift a byte at a time.
* This produces a 40-bit (rather than a 33-bit) intermediate remainder,
* but again the multiple of the polynomial to subtract depends only on
- * the high bits, the high 8 bits in this case.
+ * the high bits, the high 8 bits in this case.
*
* The multile we need in that case is the low 32 bits of a 40-bit
* value whose high 8 bits are given, and which is a multiple of the
@@ -362,7 +362,7 @@ uint32_t attribute((pure)) crc32_be(uint32_t crc, unsigned char const *p, size_t
/**
* init_crc32(): generates CRC32 tables
- *
+ *
* On successful initialization, use count is increased.
* This guarantees that the library functions will stay resident
* in memory, and prevents someone from 'rmmod crc32' while
diff --git a/kpartx/dasd.c b/kpartx/dasd.c
index 14c35b1..046a08b 100644
--- a/kpartx/dasd.c
+++ b/kpartx/dasd.c
@@ -19,9 +19,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
@@ -65,7 +63,7 @@ typedef unsigned int __attribute__((__may_alias__)) label_ints_t;
/*
*/
-int
+int
read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
{
int retval = -1;
@@ -114,7 +112,7 @@ read_dasd_pt(int fd, struct slice all, struct slice *sp, int ns)
* major/minor into an openable device file, so we have
* to create one for ourselves.
*/
-
+
sprintf(pathname, "/dev/.kpartx-node-%u-%u",
(unsigned int)major(dev), (unsigned int)minor(dev));
if ((fd_dasd = open(pathname, O_RDONLY)) == -1) {
diff --git a/kpartx/dasd.h b/kpartx/dasd.h
index 6fa64e6..749af49 100644
--- a/kpartx/dasd.h
+++ b/kpartx/dasd.h
@@ -19,50 +19,48 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _DASD_H
#define _DASD_H
-typedef struct ttr
+typedef struct ttr
{
- uint16_t tt;
- uint8_t r;
+ uint16_t tt;
+ uint8_t r;
} __attribute__ ((packed)) ttr_t;
-typedef struct cchhb
+typedef struct cchhb
{
- uint16_t cc;
- uint16_t hh;
- uint8_t b;
+ uint16_t cc;
+ uint16_t hh;
+ uint8_t b;
} __attribute__ ((packed)) cchhb_t;
-typedef struct cchh
+typedef struct cchh
{
- uint16_t cc;
- uint16_t hh;
+ uint16_t cc;
+ uint16_t hh;
} __attribute__ ((packed)) cchh_t;
-typedef struct labeldate
+typedef struct labeldate
{
- uint8_t year;
- uint16_t day;
+ uint8_t year;
+ uint16_t day;
} __attribute__ ((packed)) labeldate_t;
-typedef struct volume_label
+typedef struct volume_label
{
- char volkey[4]; /* volume key = volume label */
+ char volkey[4]; /* volume key = volume label */
char vollbl[4]; /* volume label */
char volid[6]; /* volume identifier */
uint8_t security; /* security byte */
cchhb_t vtoc; /* VTOC address */
char res1[5]; /* reserved */
- char cisize[4]; /* CI-size for FBA,... */
- /* ...blanks for CKD */
+ char cisize[4]; /* CI-size for FBA,... */
+ /* ...blanks for CKD */
char blkperci[4]; /* no of blocks per CI (FBA), blanks for CKD */
char labperci[4]; /* no of labels per CI (FBA), blanks for CKD */
char res2[4]; /* reserved */
@@ -73,31 +71,31 @@ typedef struct volume_label
} __attribute__ ((packed)) volume_label_t;
-typedef struct extent
+typedef struct extent
{
- uint8_t typeind; /* extent type indicator */
- uint8_t seqno; /* extent sequence number */
- cchh_t llimit; /* starting point of this extent */
- cchh_t ulimit; /* ending point of this extent */
+ uint8_t typeind; /* extent type indicator */
+ uint8_t seqno; /* extent sequence number */
+ cchh_t llimit; /* starting point of this extent */
+ cchh_t ulimit; /* ending point of this extent */
} __attribute__ ((packed)) extent_t;
-typedef struct dev_const
+typedef struct dev_const
{
- uint16_t DS4DSCYL; /* number of logical cyls */
- uint16_t DS4DSTRK; /* number of tracks in a logical cylinder */
- uint16_t DS4DEVTK; /* device track length */
- uint8_t DS4DEVI; /* non-last keyed record overhead */
- uint8_t DS4DEVL; /* last keyed record overhead */
- uint8_t DS4DEVK; /* non-keyed record overhead differential */
- uint8_t DS4DEVFG; /* flag byte */
- uint16_t DS4DEVTL; /* device tolerance */
- uint8_t DS4DEVDT; /* number of DSCB's per track */
- uint8_t DS4DEVDB; /* number of directory blocks per track */
+ uint16_t DS4DSCYL; /* number of logical cyls */
+ uint16_t DS4DSTRK; /* number of tracks in a logical cylinder */
+ uint16_t DS4DEVTK; /* device track length */
+ uint8_t DS4DEVI; /* non-last keyed record overhead */
+ uint8_t DS4DEVL; /* last keyed record overhead */
+ uint8_t DS4DEVK; /* non-keyed record overhead differential */
+ uint8_t DS4DEVFG; /* flag byte */
+ uint16_t DS4DEVTL; /* device tolerance */
+ uint8_t DS4DEVDT; /* number of DSCB's per track */
+ uint8_t DS4DEVDB; /* number of directory blocks per track */
} __attribute__ ((packed)) dev_const_t;
-typedef struct format1_label
+typedef struct format1_label
{
char DS1DSNAM[44]; /* data set name */
uint8_t DS1FMTID; /* format identifier */
@@ -106,27 +104,27 @@ typedef struct format1_label
labeldate_t DS1CREDT; /* creation date: ydd */
labeldate_t DS1EXPDT; /* expiration date */
uint8_t DS1NOEPV; /* number of extents on volume */
- uint8_t DS1NOBDB; /* no. of bytes used in last direction blk */
+ uint8_t DS1NOBDB; /* no. of bytes used in last direction blk */
uint8_t DS1FLAG1; /* flag 1 */
char DS1SYSCD[13]; /* system code */
labeldate_t DS1REFD; /* date last referenced */
- uint8_t DS1SMSFG; /* system managed storage indicators */
- uint8_t DS1SCXTF; /* sec. space extension flag byte */
- uint16_t DS1SCXTV; /* secondary space extension value */
- uint8_t DS1DSRG1; /* data set organisation byte 1 */
- uint8_t DS1DSRG2; /* data set organisation byte 2 */
- uint8_t DS1RECFM; /* record format */
+ uint8_t DS1SMSFG; /* system managed storage indicators */
+ uint8_t DS1SCXTF; /* sec. space extension flag byte */
+ uint16_t DS1SCXTV; /* secondary space extension value */
+ uint8_t DS1DSRG1; /* data set organisation byte 1 */
+ uint8_t DS1DSRG2; /* data set organisation byte 2 */
+ uint8_t DS1RECFM; /* record format */
uint8_t DS1OPTCD; /* option code */
uint16_t DS1BLKL; /* block length */
uint16_t DS1LRECL; /* record length */
uint8_t DS1KEYL; /* key length */
uint16_t DS1RKP; /* relative key position */
uint8_t DS1DSIND; /* data set indicators */
- uint8_t DS1SCAL1; /* secondary allocation flag byte */
- char DS1SCAL3[3]; /* secondary allocation quantity */
+ uint8_t DS1SCAL1; /* secondary allocation flag byte */
+ char DS1SCAL3[3]; /* secondary allocation quantity */
ttr_t DS1LSTAR; /* last used track and block on track */
uint16_t DS1TRBAL; /* space remaining on last used track */
- uint16_t res1; /* reserved */
+ uint16_t res1; /* reserved */
extent_t DS1EXT1; /* first extent description */
extent_t DS1EXT2; /* second extent description */
extent_t DS1EXT3; /* third extent description */
@@ -178,16 +176,16 @@ static unsigned char EBCtoASC[256] =
/* 0x08 -GE -SPS -RPT VT FF CR SO SI */
0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
/* 0x10 DLE DC1 DC2 DC3 -RES -NL BS -POC
- -ENP ->LF */
+ -ENP ->LF */
0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
/* 0x18 CAN EM -UBS -CU1 -IFS -IGS -IRS -ITB
- -IUS */
+ -IUS */
0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* 0x20 -DS -SOS FS -WUS -BYP LF ETB ESC
- -INP */
+ -INP */
0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
/* 0x28 -SA -SFE -SM -CSP -MFA ENQ ACK BEL
- -SW */
+ -SW */
0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
/* 0x30 ---- ---- SYN -IR -PP -TRN -NBS EOT */
0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
@@ -243,12 +241,12 @@ static unsigned char EBCtoASC[256] =
0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
};
-static inline void
+static inline void
vtoc_ebcdic_dec (const char *source, char *target, int l)
{
int i;
- for (i = 0; i < l; i++)
+ for (i = 0; i < l; i++)
target[i]=(char)EBCtoASC[(unsigned char)(source[i])];
}
diff --git a/kpartx/devmapper.c b/kpartx/devmapper.c
index e006bc3..382f511 100644
--- a/kpartx/devmapper.c
+++ b/kpartx/devmapper.c
@@ -77,19 +77,13 @@ dm_simplecmd (int task, const char *name, int no_flush, uint16_t udev_flags) {
#ifdef LIBDM_API_COOKIE
if (!udev_sync)
udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
- if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags)) {
- dm_udev_complete(cookie);
+ if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
- }
#endif
r = dm_task_run(dmt);
#ifdef LIBDM_API_COOKIE
- if (udev_wait_flag) {
- if (!r)
- dm_udev_complete(cookie);
- else
+ if (udev_wait_flag)
dm_udev_wait(cookie);
- }
#endif
out:
dm_task_destroy(dmt);
@@ -145,19 +139,13 @@ dm_addmap (int task, const char *name, const char *target,
if (!udev_sync)
udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
if (task == DM_DEVICE_CREATE &&
- !dm_task_set_cookie(dmt, &cookie, udev_flags)) {
- dm_udev_complete(cookie);
+ !dm_task_set_cookie(dmt, &cookie, udev_flags))
goto addout;
- }
#endif
r = dm_task_run (dmt);
#ifdef LIBDM_API_COOKIE
- if (task == DM_DEVICE_CREATE) {
- if (!r)
- dm_udev_complete(cookie);
- else
+ if (task == DM_DEVICE_CREATE)
dm_udev_wait(cookie);
- }
#endif
addout:
dm_task_destroy (dmt);
@@ -323,7 +311,6 @@ dm_get_map(int major, int minor, char * outparams)
{
int r = 1;
struct dm_task *dmt;
- void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params = NULL;
@@ -339,8 +326,8 @@ dm_get_map(int major, int minor, char * outparams)
goto out;
/* Fetch 1st target */
- next = dm_get_next_target(dmt, next, &start, &length,
- &target_type, &params);
+ dm_get_next_target(dmt, NULL, &start, &length,
+ &target_type, &params);
if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
r = 0;
diff --git a/kpartx/dos.c b/kpartx/dos.c
index 90ad3bd..64b27b6 100644
--- a/kpartx/dos.c
+++ b/kpartx/dos.c
@@ -1,7 +1,7 @@
/*
* Source: copy of util-linux' partx dos.c
*
- * Copyrights of the original file apply
+ * Copyrights of the original file apply
* Copyright (c) 2005 Bastian Blank
*/
#include "kpartx.h"
@@ -79,7 +79,7 @@ read_dos_pt(int fd, struct slice all, struct slice *sp, int ns) {
unsigned long offset = all.start;
int i, n=4;
unsigned char *bp;
- int sector_size_mul = get_sector_size(fd)/512;
+ uint64_t sector_size_mul = get_sector_size(fd)/512;
bp = (unsigned char *)getblock(fd, offset);
if (bp == NULL)
diff --git a/kpartx/efi.h b/kpartx/efi.h
index 1cbd961..af5660a 100644
--- a/kpartx/efi.h
+++ b/kpartx/efi.h
@@ -1,8 +1,8 @@
/*
efi.[ch] - Manipulates EFI variables as exported in /proc/efi/vars
-
+
Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@dell.com>
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -14,8 +14,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EFI_H
diff --git a/kpartx/gpt.c b/kpartx/gpt.c
index 5a54970..75a1c2b 100644
--- a/kpartx/gpt.c
+++ b/kpartx/gpt.c
@@ -1,7 +1,7 @@
/*
gpt.[ch]
- Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@dell.com>
+ Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@dell.com>
EFI GUID Partition Table handling
Per Intel EFI Specification v1.02
@@ -18,8 +18,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _FILE_OFFSET_BITS 64
@@ -66,9 +65,9 @@
#endif
struct blkdev_ioctl_param {
- unsigned int block;
- size_t content_length;
- char * block_contents;
+ unsigned int block;
+ size_t content_length;
+ char * block_contents;
};
/**
@@ -77,7 +76,7 @@ struct blkdev_ioctl_param {
* @len - length of buf
*
* Description: Returns EFI-style CRC32 value for @buf
- *
+ *
* This function uses the little endian Ethernet polynomial
* but seeds the function with ~0, and xor's with ~0 at the end.
* Note, the EFI Specification, v1.02, has a reference to
@@ -107,7 +106,7 @@ is_pmbr_valid(legacy_mbr *mbr)
signature = (__le16_to_cpu(mbr->signature) == MSDOS_MBR_SIGNATURE);
for (i = 0; signature && i < 4; i++) {
if (mbr->partition[i].sys_type ==
- EFI_PMBR_OSTYPE_EFI_GPT) {
+ EFI_PMBR_OSTYPE_EFI_GPT) {
found = 1;
break;
}
@@ -122,7 +121,7 @@ is_pmbr_valid(legacy_mbr *mbr)
* - filedes is an open file descriptor, suitable for reading
* Modifies: nothing
* Returns:
- * Last LBA value on success
+ * Last LBA value on success
* 0 on error
*
* Try getting BLKGETSIZE64 and BLKSSZGET first,
@@ -146,9 +145,9 @@ _get_num_sectors(int filedes)
/************************************************************
* last_lba(): return number of last logical block of device
- *
+ *
* @fd
- *
+ *
* Description: returns Last LBA value on success, 0 on error.
* Notes: The value st_blocks gives the size of the file
* in 512-byte blocks, which is OK if
@@ -185,19 +184,19 @@ last_lba(int filedes)
static ssize_t
read_lastoddsector(int fd, uint64_t lba, void *buffer, size_t count)
{
- int rc;
- struct blkdev_ioctl_param ioctl_param;
+ int rc;
+ struct blkdev_ioctl_param ioctl_param;
- if (!buffer) return 0;
+ if (!buffer) return 0;
- ioctl_param.block = 0; /* read the last sector */
- ioctl_param.content_length = count;
- ioctl_param.block_contents = buffer;
+ ioctl_param.block = 0; /* read the last sector */
+ ioctl_param.content_length = count;
+ ioctl_param.block_contents = buffer;
- rc = ioctl(fd, BLKGETLASTSECT, &ioctl_param);
- if (rc == -1) perror("read failed");
+ rc = ioctl(fd, BLKGETLASTSECT, &ioctl_param);
+ if (rc == -1) perror("read failed");
- return !rc;
+ return !rc;
}
static ssize_t
@@ -206,30 +205,31 @@ read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
int sector_size = get_sector_size(fd);
off_t offset = lba * sector_size;
uint64_t lastlba;
- ssize_t bytesread;
+ ssize_t bytesread;
- lseek(fd, offset, SEEK_SET);
+ if (lseek(fd, offset, SEEK_SET) < 0)
+ return 0;
bytesread = read(fd, buffer, bytes);
lastlba = last_lba(fd);
if (!lastlba)
return bytesread;
- /* Kludge. This is necessary to read/write the last
- block of an odd-sized disk, until Linux 2.5.x kernel fixes.
- This is only used by gpt.c, and only to read
- one sector, so we don't have to be fancy.
- */
- if (!bytesread && !(lastlba & 1) && lba == lastlba) {
- bytesread = read_lastoddsector(fd, lba, buffer, bytes);
- }
- return bytesread;
+ /* Kludge. This is necessary to read/write the last
+ block of an odd-sized disk, until Linux 2.5.x kernel fixes.
+ This is only used by gpt.c, and only to read
+ one sector, so we don't have to be fancy.
+ */
+ if (!bytesread && !(lastlba & 1) && lba == lastlba) {
+ bytesread = read_lastoddsector(fd, lba, buffer, bytes);
+ }
+ return bytesread;
}
/**
* alloc_read_gpt_entries(): reads partition entries from disk
* @fd is an open file descriptor to the whole disk
- * @gpt is a buffer into which the GPT will be put
+ * @gpt is a buffer into which the GPT will be put
* Description: Returns ptes on success, NULL on error.
* Allocates space for PTEs based on information found in @gpt.
* Notes: remember to free pte when you're done!
@@ -238,10 +238,10 @@ static gpt_entry *
alloc_read_gpt_entries(int fd, gpt_header * gpt)
{
gpt_entry *pte;
- size_t count = __le32_to_cpu(gpt->num_partition_entries) *
- __le32_to_cpu(gpt->sizeof_partition_entry);
+ size_t count = __le32_to_cpu(gpt->num_partition_entries) *
+ __le32_to_cpu(gpt->sizeof_partition_entry);
- if (!count) return NULL;
+ if (!count) return NULL;
pte = (gpt_entry *)malloc(count);
if (!pte)
@@ -249,7 +249,7 @@ alloc_read_gpt_entries(int fd, gpt_header * gpt)
memset(pte, 0, count);
if (!read_lba(fd, __le64_to_cpu(gpt->partition_entry_lba), pte,
- count)) {
+ count)) {
free(pte);
return NULL;
}
@@ -260,7 +260,7 @@ alloc_read_gpt_entries(int fd, gpt_header * gpt)
* alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
* @fd is an open file descriptor to the whole disk
* @lba is the Logical Block Address of the partition table
- *
+ *
* Description: returns GPT header on success, NULL on error. Allocates
* and fills a GPT header starting at @ from @bdev.
* Note: remember to free gpt when finished with it.
@@ -294,19 +294,19 @@ alloc_read_gpt_header(int fd, uint64_t lba)
*/
static int
is_gpt_valid(int fd, uint64_t lba,
- gpt_header ** gpt, gpt_entry ** ptes)
+ gpt_header ** gpt, gpt_entry ** ptes)
{
int rc = 0; /* default to not valid */
uint32_t crc, origcrc;
if (!gpt || !ptes)
- return 0;
+ return 0;
if (!(*gpt = alloc_read_gpt_header(fd, lba)))
return 0;
/* Check the GUID Partition Table signature */
if (__le64_to_cpu((*gpt)->signature) != GPT_HEADER_SIGNATURE) {
- /*
+ /*
printf("GUID Partition Table Header signature is wrong: %" PRIx64" != %" PRIx64 "\n",
__le64_to_cpu((*gpt)->signature), GUID_PT_HEADER_SIGNATURE);
*/
@@ -333,7 +333,7 @@ is_gpt_valid(int fd, uint64_t lba,
if (__le64_to_cpu((*gpt)->my_lba) != lba) {
/*
printf( "my_lba % PRIx64 "x != lba %"PRIx64 "x.\n",
- __le64_to_cpu((*gpt)->my_lba), lba);
+ __le64_to_cpu((*gpt)->my_lba), lba);
*/
free(*gpt);
*gpt = NULL;
@@ -366,7 +366,7 @@ is_gpt_valid(int fd, uint64_t lba,
/* Check the GUID Partition Entry Array CRC */
crc = efi_crc32(*ptes,
- __le32_to_cpu((*gpt)->num_partition_entries) *
+ __le32_to_cpu((*gpt)->num_partition_entries) *
__le32_to_cpu((*gpt)->sizeof_partition_entry));
if (crc != __le32_to_cpu((*gpt)->partition_entry_array_crc32)) {
// printf("GUID Partitition Entry Array CRC check failed.\n");
@@ -387,7 +387,7 @@ is_gpt_valid(int fd, uint64_t lba,
* @lastlba is the last LBA number
* Description: Returns nothing. Sanity checks pgpt and agpt fields
* and prints warnings on discrepancies.
- *
+ *
*/
static void
compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
@@ -397,42 +397,42 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
return;
if (__le64_to_cpu(pgpt->my_lba) != __le64_to_cpu(agpt->alternate_lba)) {
error_found++;
- fprintf(stderr,
+ fprintf(stderr,
"GPT:Primary header LBA != Alt. header alternate_lba\n");
#ifdef DEBUG
fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
__le64_to_cpu(pgpt->my_lba),
- __le64_to_cpu(agpt->alternate_lba));
+ __le64_to_cpu(agpt->alternate_lba));
#endif
}
if (__le64_to_cpu(pgpt->alternate_lba) != __le64_to_cpu(agpt->my_lba)) {
error_found++;
- fprintf(stderr,
+ fprintf(stderr,
"GPT:Primary header alternate_lba != Alt. header my_lba\n");
#ifdef DEBUG
fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
__le64_to_cpu(pgpt->alternate_lba),
- __le64_to_cpu(agpt->my_lba));
+ __le64_to_cpu(agpt->my_lba));
#endif
}
if (__le64_to_cpu(pgpt->first_usable_lba) !=
- __le64_to_cpu(agpt->first_usable_lba)) {
+ __le64_to_cpu(agpt->first_usable_lba)) {
error_found++;
fprintf(stderr, "GPT:first_usable_lbas don't match.\n");
#ifdef DEBUG
fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
__le64_to_cpu(pgpt->first_usable_lba),
- __le64_to_cpu(agpt->first_usable_lba));
+ __le64_to_cpu(agpt->first_usable_lba));
#endif
}
if (__le64_to_cpu(pgpt->last_usable_lba) !=
- __le64_to_cpu(agpt->last_usable_lba)) {
+ __le64_to_cpu(agpt->last_usable_lba)) {
error_found++;
fprintf(stderr, "GPT:last_usable_lbas don't match.\n");
#ifdef DEBUG
fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
__le64_to_cpu(pgpt->last_usable_lba),
- __le64_to_cpu(agpt->last_usable_lba));
+ __le64_to_cpu(agpt->last_usable_lba));
#endif
}
if (efi_guidcmp(pgpt->disk_guid, agpt->disk_guid)) {
@@ -440,7 +440,7 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
fprintf(stderr, "GPT:disk_guids don't match.\n");
}
if (__le32_to_cpu(pgpt->num_partition_entries) !=
- __le32_to_cpu(agpt->num_partition_entries)) {
+ __le32_to_cpu(agpt->num_partition_entries)) {
error_found++;
fprintf(stderr, "GPT:num_partition_entries don't match: "
"0x%x != 0x%x\n",
@@ -448,26 +448,26 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
__le32_to_cpu(agpt->num_partition_entries));
}
if (__le32_to_cpu(pgpt->sizeof_partition_entry) !=
- __le32_to_cpu(agpt->sizeof_partition_entry)) {
+ __le32_to_cpu(agpt->sizeof_partition_entry)) {
error_found++;
- fprintf(stderr,
+ fprintf(stderr,
"GPT:sizeof_partition_entry values don't match: "
"0x%x != 0x%x\n",
- __le32_to_cpu(pgpt->sizeof_partition_entry),
+ __le32_to_cpu(pgpt->sizeof_partition_entry),
__le32_to_cpu(agpt->sizeof_partition_entry));
}
if (__le32_to_cpu(pgpt->partition_entry_array_crc32) !=
- __le32_to_cpu(agpt->partition_entry_array_crc32)) {
+ __le32_to_cpu(agpt->partition_entry_array_crc32)) {
error_found++;
- fprintf(stderr,
+ fprintf(stderr,
"GPT:partition_entry_array_crc32 values don't match: "
"0x%x != 0x%x\n",
- __le32_to_cpu(pgpt->partition_entry_array_crc32),
+ __le32_to_cpu(pgpt->partition_entry_array_crc32),
__le32_to_cpu(agpt->partition_entry_array_crc32));
}
if (__le64_to_cpu(pgpt->alternate_lba) != lastlba) {
error_found++;
- fprintf(stderr,
+ fprintf(stderr,
"GPT:Primary header thinks Alt. header is not at the end of the disk.\n");
#ifdef DEBUG
fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
@@ -477,7 +477,7 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
if (__le64_to_cpu(agpt->my_lba) != lastlba) {
error_found++;
- fprintf(stderr,
+ fprintf(stderr,
"GPT:Alternate GPT header not at the end of the disk.\n");
#ifdef DEBUG
fprintf(stderr, "GPT:%" PRIx64 " != %" PRIx64 "\n",
@@ -486,7 +486,7 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
}
if (error_found)
- fprintf(stderr,
+ fprintf(stderr,
"GPT: Use GNU Parted to correct GPT errors.\n");
return;
}
@@ -504,7 +504,7 @@ compare_gpts(gpt_header *pgpt, gpt_header *agpt, uint64_t lastlba)
static int
find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
{
- extern int force_gpt;
+ extern int force_gpt;
int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
gpt_header *pgpt = NULL, *agpt = NULL;
gpt_entry *pptes = NULL, *aptes = NULL;
@@ -517,93 +517,93 @@ find_valid_gpt(int fd, gpt_header ** gpt, gpt_entry ** ptes)
return 0;
good_pgpt = is_gpt_valid(fd, GPT_PRIMARY_PARTITION_TABLE_LBA,
&pgpt, &pptes);
- if (good_pgpt) {
+ if (good_pgpt) {
good_agpt = is_gpt_valid(fd,
- __le64_to_cpu(pgpt->alternate_lba),
+ __le64_to_cpu(pgpt->alternate_lba),
&agpt, &aptes);
- if (!good_agpt) {
- good_agpt = is_gpt_valid(fd, lastlba,
- &agpt, &aptes);
- }
- }
- else {
- good_agpt = is_gpt_valid(fd, lastlba,
- &agpt, &aptes);
- }
-
- /* The obviously unsuccessful case */
- if (!good_pgpt && !good_agpt) {
- goto fail;
- }
+ if (!good_agpt) {
+ good_agpt = is_gpt_valid(fd, lastlba,
+ &agpt, &aptes);
+ }
+ }
+ else {
+ good_agpt = is_gpt_valid(fd, lastlba,
+ &agpt, &aptes);
+ }
+
+ /* The obviously unsuccessful case */
+ if (!good_pgpt && !good_agpt) {
+ goto fail;
+ }
/* This will be added to the EFI Spec. per Intel after v1.02. */
- legacymbr = malloc(sizeof (*legacymbr));
- if (legacymbr) {
- memset(legacymbr, 0, sizeof (*legacymbr));
- read_lba(fd, 0, (uint8_t *) legacymbr,
- sizeof (*legacymbr));
- good_pmbr = is_pmbr_valid(legacymbr);
- free(legacymbr);
- legacymbr=NULL;
- }
-
- /* Failure due to bad PMBR */
- if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
- fprintf(stderr,
- " Warning: Disk has a valid GPT signature "
- "but invalid PMBR.\n"
- " Assuming this disk is *not* a GPT disk anymore.\n"
- " Use gpt kernel option to override. "
- "Use GNU Parted to correct disk.\n");
- goto fail;
- }
-
- /* Would fail due to bad PMBR, but force GPT anyhow */
- if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
- fprintf(stderr,
- " Warning: Disk has a valid GPT signature but "
- "invalid PMBR.\n"
- " Use GNU Parted to correct disk.\n"
- " gpt option taken, disk treated as GPT.\n");
- }
-
- compare_gpts(pgpt, agpt, lastlba);
-
- /* The good cases */
- if (good_pgpt && (good_pmbr || force_gpt)) {
- *gpt = pgpt;
- *ptes = pptes;
- if (agpt) { free(agpt); agpt = NULL; }
- if (aptes) { free(aptes); aptes = NULL; }
- if (!good_agpt) {
- fprintf(stderr,
+ legacymbr = malloc(sizeof (*legacymbr));
+ if (legacymbr) {
+ memset(legacymbr, 0, sizeof (*legacymbr));
+ read_lba(fd, 0, (uint8_t *) legacymbr,
+ sizeof (*legacymbr));
+ good_pmbr = is_pmbr_valid(legacymbr);
+ free(legacymbr);
+ legacymbr=NULL;
+ }
+
+ /* Failure due to bad PMBR */
+ if ((good_pgpt || good_agpt) && !good_pmbr && !force_gpt) {
+ fprintf(stderr,
+ " Warning: Disk has a valid GPT signature "
+ "but invalid PMBR.\n"
+ " Assuming this disk is *not* a GPT disk anymore.\n"
+ " Use gpt kernel option to override. "
+ "Use GNU Parted to correct disk.\n");
+ goto fail;
+ }
+
+ /* Would fail due to bad PMBR, but force GPT anyhow */
+ if ((good_pgpt || good_agpt) && !good_pmbr && force_gpt) {
+ fprintf(stderr,
+ " Warning: Disk has a valid GPT signature but "
+ "invalid PMBR.\n"
+ " Use GNU Parted to correct disk.\n"
+ " gpt option taken, disk treated as GPT.\n");
+ }
+
+ compare_gpts(pgpt, agpt, lastlba);
+
+ /* The good cases */
+ if (good_pgpt && (good_pmbr || force_gpt)) {
+ *gpt = pgpt;
+ *ptes = pptes;
+ if (agpt) { free(agpt); agpt = NULL; }
+ if (aptes) { free(aptes); aptes = NULL; }
+ if (!good_agpt) {
+ fprintf(stderr,
"Alternate GPT is invalid, "
- "using primary GPT.\n");
- }
- return 1;
- }
- else if (good_agpt && (good_pmbr || force_gpt)) {
- *gpt = agpt;
- *ptes = aptes;
- if (pgpt) { free(pgpt); pgpt = NULL; }
- if (pptes) { free(pptes); pptes = NULL; }
- fprintf(stderr,
- "Primary GPT is invalid, using alternate GPT.\n");
- return 1;
- }
+ "using primary GPT.\n");
+ }
+ return 1;
+ }
+ else if (good_agpt && (good_pmbr || force_gpt)) {
+ *gpt = agpt;
+ *ptes = aptes;
+ if (pgpt) { free(pgpt); pgpt = NULL; }
+ if (pptes) { free(pptes); pptes = NULL; }
+ fprintf(stderr,
+ "Primary GPT is invalid, using alternate GPT.\n");
+ return 1;
+ }
fail:
- if (pgpt) { free(pgpt); pgpt=NULL; }
- if (agpt) { free(agpt); agpt=NULL; }
- if (pptes) { free(pptes); pptes=NULL; }
- if (aptes) { free(aptes); aptes=NULL; }
- *gpt = NULL;
- *ptes = NULL;
- return 0;
+ if (pgpt) { free(pgpt); pgpt=NULL; }
+ if (agpt) { free(agpt); agpt=NULL; }
+ if (pptes) { free(pptes); pptes=NULL; }
+ if (aptes) { free(aptes); aptes=NULL; }
+ *gpt = NULL;
+ *ptes = NULL;
+ return 0;
}
/**
- * read_gpt_pt()
+ * read_gpt_pt()
* @fd
* @all - slice with start/size of whole disk
*
@@ -618,7 +618,7 @@ read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns)
gpt_entry *ptes = NULL;
uint32_t i;
int n = 0;
- int last_used_index=-1;
+ int last_used_index=-1;
int sector_size_mul = get_sector_size(fd)/512;
if (!find_valid_gpt (fd, &gpt, &ptes) || !gpt || !ptes) {
@@ -640,7 +640,7 @@ read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns)
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;
+ last_used_index=n;
n++;
}
}
diff --git a/kpartx/gpt.h b/kpartx/gpt.h
index a073b42..66ce8f1 100644
--- a/kpartx/gpt.h
+++ b/kpartx/gpt.h
@@ -1,7 +1,7 @@
/*
gpt.[ch]
- Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@dell.com>
+ Copyright (C) 2000-2001 Dell Computer Corporation <Matt_Domsch@dell.com>
EFI GUID Partition Table handling
Per Intel EFI Specification v1.02
@@ -18,8 +18,7 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _GPT_H
@@ -63,7 +62,7 @@ typedef struct _gpt_header {
typedef struct _gpt_entry_attributes {
uint64_t required_to_function:1;
uint64_t reserved:47;
- uint64_t type_guid_specific:16;
+ uint64_t type_guid_specific:16;
} __attribute__ ((packed)) gpt_entry_attributes;
typedef struct _gpt_entry {
@@ -76,19 +75,19 @@ typedef struct _gpt_entry {
} __attribute__ ((packed)) gpt_entry;
-/*
+/*
These values are only defaults. The actual on-disk structures
may define different sizes, so use those unless creating a new GPT disk!
*/
#define GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE 16384
-/*
+/*
Number of actual partition entries should be calculated
- as:
+ as:
*/
#define GPT_DEFAULT_RESERVED_PARTITION_ENTRIES \
- (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE / \
- sizeof(gpt_entry))
+ (GPT_DEFAULT_RESERVED_PARTITION_ENTRY_ARRAY_SIZE / \
+ sizeof(gpt_entry))
/* Protected Master Boot Record & Legacy MBR share same structure */
@@ -118,7 +117,7 @@ int read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns);
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
- * c-indent-level: 4
+ * c-indent-level: 4
* c-brace-imaginary-offset: 0
* c-brace-offset: -4
* c-argdecl-indent: 4
diff --git a/kpartx/kpartx.8 b/kpartx/kpartx.8
index 021ddc0..4c55831 100644
--- a/kpartx/kpartx.8
+++ b/kpartx/kpartx.8
@@ -9,8 +9,8 @@ kpartx \- Create device maps from partition tables
.RB wholedisk
.SH DESCRIPTION
This tool, derived from util-linux' partx, reads partition
-tables on specified device and create device maps over partitions
-segments detected. It is called from hotplug upon device maps
+tables on specified device and create device maps over partitions
+segments detected. It is called from hotplug upon device maps
creation and deletion.
.SH OPTIONS
.TP
@@ -50,15 +50,15 @@ kpartx \-av disk.img
.PP
This will output lines such as:
.IP
-loop3p1 : 0 20964762 /dev/loop3 63
+add map loop1p1 (254:4): 0 409597 linear 7:1 3
.PP
-The
-.I loop3p1
-is the name of a device file under
+The
+.I loop1p1
+is the name of a device file under
.I /dev/mapper
which you can use to access the partition, for example to fsck it:
.IP
-fsck /dev/mapper/loop3p1
+fsck /dev/mapper/loop1p1
.PP
When you're done, you need to remove the devices:
.IP
@@ -71,4 +71,3 @@ kpartx \-d disk.img
This man page was assembled By Patrick Caulfield
for the Debian project. From documentation provided
by the multipath author Christophe Varoqui, <christophe.varoqui@opensvc.com> and others.
-
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
index e8c35d4..b7b4047 100644
--- a/kpartx/kpartx.c
+++ b/kpartx/kpartx.c
@@ -150,7 +150,7 @@ static char *
get_hotplug_device(void)
{
unsigned int major, minor, off, len;
- const char *mapname;
+ char *mapname;
char *devname = NULL;
char *device = NULL;
char *var = NULL;
@@ -178,16 +178,21 @@ get_hotplug_device(void)
len = strlen(mapname);
/* Dirname + mapname + \0 */
- if (!(device = (char *)malloc(sizeof(char) * (off + len + 1))))
+ if (!(device = (char *)malloc(sizeof(char) * (off + len + 1)))) {
+ free(mapname);
return NULL;
+ }
/* Create new device name. */
snprintf(device, off + 1, "%s", devname);
snprintf(device + off, len + 1, "%s", mapname);
- if (strlen(device) != (off + len))
+ if (strlen(device) != (off + len)) {
+ free(device);
+ free(mapname);
return NULL;
-
+ }
+ free(mapname);
return device;
}
@@ -477,14 +482,14 @@ main(int argc, char **argv){
printf("del devmap : %s\n", partname);
}
- if (S_ISREG (buf.st_mode)) {
- if (del_loop(device)) {
+ if (loopdev) {
+ if (del_loop(loopdev)) {
if (verbose)
printf("can't del loop : %s\n",
- device);
+ loopdev);
exit(1);
}
- printf("loop deleted : %s\n", device);
+ printf("loop deleted : %s\n", loopdev);
}
break;
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
index f6a3706..8858a60 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
@@ -41,5 +41,3 @@ ENV{DM_STATE}!="SUSPENDED", ENV{DM_UUID}=="mpath-*", \
RUN+="/sbin/kpartx -u -p -part /dev/$name"
LABEL="kpartx_end"
-
-
diff --git a/kpartx/lopart.c b/kpartx/lopart.c
index ffde6d9..e8e3f08 100644
--- a/kpartx/lopart.c
+++ b/kpartx/lopart.c
@@ -27,7 +27,7 @@
#include <sys/mman.h>
#include <sys/types.h>
#include <dirent.h>
-#include <sysmacros.h>
+#include "sysmacros.h"
#include <linux/loop.h>
#include "lopart.h"
@@ -38,7 +38,7 @@
#endif
#if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) \
- && !defined (__s390x__)
+ && !defined (__s390x__)
#define int2ptr(x) ((void *) ((int) x))
#else
#define int2ptr(x) ((void *) ((long) x))
@@ -76,9 +76,9 @@ is_loop_device (const char *device)
loopmajor = 0;
if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
-
+
while (fgets (line, sizeof(line), procdev)) {
-
+
if ((cp = strstr (line, " loop\n")) != NULL) {
*cp='\0';
loopmajor=atoi(line);
@@ -117,14 +117,16 @@ find_loop_by_file (const char * filename)
continue;
sprintf(dev, "/dev/%s", dent->d_name);
- if (stat (dev, &statbuf) != 0 ||
- !S_ISBLK(statbuf.st_mode))
- continue;
-
fd = open (dev, O_RDONLY);
if (fd < 0)
break;
+ if (fstat (fd, &statbuf) != 0 ||
+ !S_ISBLK(statbuf.st_mode)) {
+ close (fd);
+ continue;
+ }
+
if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
close (fd);
continue;
@@ -154,33 +156,31 @@ find_unused_loop_device (void)
while (next_loop_dev == NULL) {
if (stat("/dev/loop-control", &statbuf) == 0 &&
S_ISCHR(statbuf.st_mode)) {
- fd = open("/dev/loop-control", O_RDWR);
- if (fd < 0)
+ int next_loop_fd;
+
+ next_loop_fd = open("/dev/loop-control", O_RDWR);
+ if (next_loop_fd < 0)
return NULL;
- next_loop = ioctl(fd, LOOP_CTL_GET_FREE);
+ next_loop = ioctl(next_loop_fd, LOOP_CTL_GET_FREE);
+ close(next_loop_fd);
if (next_loop < 0)
return NULL;
- close(fd);
}
sprintf(dev, "/dev/loop%d", next_loop);
- if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
- somedev++;
- fd = open (dev, O_RDONLY);
-
- if (fd >= 0) {
-
+ fd = open (dev, O_RDONLY);
+ if (fd >= 0) {
+ if (fstat (fd, &statbuf) == 0 &&
+ S_ISBLK(statbuf.st_mode)) {
+ somedev++;
if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
someloop++; /* in use */
-
- else if (errno == ENXIO) {
- close (fd);
+ else if (errno == ENXIO)
next_loop_dev = xstrdup(dev);
- }
- close (fd);
}
+ close (fd);
/* continue trying as long as devices exist */
continue;
@@ -253,6 +253,7 @@ set_loop (const char *device, const char *file, int offset, int *loopro)
}
if ((fd = open (device, mode)) < 0) {
+ close(ffd);
perror (device);
return 1;
}
@@ -285,10 +286,10 @@ set_loop (const char *device, const char *file, int offset, int *loopro)
return 0;
}
-extern int
+extern int
del_loop (const char *device)
{
- int retries = 3;
+ int retries = 5;
int fd;
if ((fd = open (device, O_RDONLY)) < 0) {
diff --git a/kpartx/mac.c b/kpartx/mac.c
index 5432e67..6e82c95 100644
--- a/kpartx/mac.c
+++ b/kpartx/mac.c
@@ -7,11 +7,11 @@
int
read_mac_pt(int fd, struct slice all, struct slice *sp, int ns) {
struct mac_driver_desc *md;
- struct mac_partition *part;
+ struct mac_partition *part;
unsigned secsize;
char *data;
int blk, blocks_in_map;
- int n = 0;
+ int n = 0;
md = (struct mac_driver_desc *) getblock(fd, 0);
if (md == NULL)
diff --git a/kpartx/mac.h b/kpartx/mac.h
index 3c712ba..a44cf38 100644
--- a/kpartx/mac.h
+++ b/kpartx/mac.h
@@ -9,21 +9,21 @@
#define APPLE_AUX_TYPE "Apple_UNIX_SVR2"
struct mac_partition {
- uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
- uint16_t res1;
- uint32_t map_count; /* # blocks in partition map */
- uint32_t start_block; /* absolute starting block # of partition */
- uint32_t block_count; /* number of blocks in partition */
- /* there is more stuff after this that we don't need */
+ uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
+ uint16_t res1;
+ uint32_t map_count; /* # blocks in partition map */
+ uint32_t start_block; /* absolute starting block # of partition */
+ uint32_t block_count; /* number of blocks in partition */
+ /* there is more stuff after this that we don't need */
};
#define MAC_DRIVER_MAGIC 0x4552
/* Driver descriptor structure, in block 0 */
struct mac_driver_desc {
- uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
- uint16_t block_size;
- uint32_t block_count;
+ uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
+ uint16_t block_size;
+ uint32_t block_count;
/* ... more stuff */
};
diff --git a/kpartx/ps3.c b/kpartx/ps3.c
index d1e5d64..2fe868d 100644
--- a/kpartx/ps3.c
+++ b/kpartx/ps3.c
@@ -50,7 +50,7 @@ read_disklabel(int fd, struct disklabel *label) {
int
read_ps3_pt(int fd, struct slice all, struct slice *sp, int ns) {
struct disklabel label;
- int n = 0;
+ int n = 0;
int i;
if (!read_disklabel(fd, &label))
@@ -70,8 +70,3 @@ read_ps3_pt(int fd, struct slice all, struct slice *sp, int ns) {
return n;
}
-
-
-
-
-
diff --git a/kpartx/solaris.c b/kpartx/solaris.c
index e3000e9..355a6cb 100644
--- a/kpartx/solaris.c
+++ b/kpartx/solaris.c
@@ -11,7 +11,7 @@
struct solaris_x86_slice {
unsigned short s_tag; /* ID tag of partition */
unsigned short s_flag; /* permision flags */
- daddr_t s_start; /* start sector no of partition */
+ daddr_t s_start; /* start sector no of partition */
long s_size; /* # of blocks in partition */
};
@@ -37,7 +37,7 @@ read_solaris_pt(int fd, struct slice all, struct slice *sp, int ns) {
int i, n;
char *bp;
- bp = getblock(fd, offset+1); /* 1 sector suffices */
+ bp = getblock(fd, offset+1); /* 1 sector suffices */
if (bp == NULL)
return -1;
@@ -68,4 +68,3 @@ read_solaris_pt(int fd, struct slice all, struct slice *sp, int ns) {
}
return n;
}
-
diff --git a/kpartx/sun.c b/kpartx/sun.c
index b8c023b..276066d 100644
--- a/kpartx/sun.c
+++ b/kpartx/sun.c
@@ -126,4 +126,3 @@ read_sun_pt(int fd, struct slice all, struct slice *sp, int ns) {
}
return n;
}
-
diff --git a/kpartx/unixware.c b/kpartx/unixware.c
index 41cc957..c7b9786 100644
--- a/kpartx/unixware.c
+++ b/kpartx/unixware.c
@@ -17,7 +17,7 @@ struct unixware_disklabel {
unsigned int d_type; /* drive type */
unsigned char d_magic[4]; /* the magic number */
unsigned int d_version; /* version number */
- char d_serial[12]; /* serial number of the device */
+ char d_serial[12]; /* serial number of the device */
unsigned int d_ncylinders; /* # of data cylinders per device */
unsigned int d_ntracks; /* # of tracks per cylinder */
unsigned int d_nsectors; /* # of data sectors per track */
@@ -37,7 +37,7 @@ struct unixware_disklabel {
struct unixware_vtoc {
unsigned char v_magic[4]; /* the magic number */
unsigned int v_version; /* version number */
- char v_name[8]; /* volume name */
+ char v_name[8]; /* volume name */
unsigned short v_nslices; /* # of slices */
unsigned short v_unknown1; /* ? */
unsigned int v_reserved[10]; /* reserved */
@@ -55,7 +55,7 @@ read_unixware_pt(int fd, struct slice all, struct slice *sp, int ns) {
char *bp;
int n = 0;
- bp = getblock(fd, offset+29); /* 1 sector suffices */
+ bp = getblock(fd, offset+29); /* 1 sector suffices */
if (bp == NULL)
return -1;
diff --git a/libmpathcmd/Makefile b/libmpathcmd/Makefile
index 0304ecc..44c221d 100644
--- a/libmpathcmd/Makefile
+++ b/libmpathcmd/Makefile
@@ -12,19 +12,19 @@ all: $(LIBS)
$(LIBS): $(OBJS)
$(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ $(CFLAGS) -o $@ $(OBJS) $(LIBDEPS)
- ln -sf $@ $(DEVLIB)
+ $(LN) $@ $(DEVLIB)
install: $(LIBS)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir)
$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS)
- ln -sf $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB)
+ $(LN) $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(incdir)
- $(INSTALL_PROGRAM) -m 755 mpath_cmd.h $(DESTDIR)$(incdir)
+ $(INSTALL_PROGRAM) -m 644 mpath_cmd.h $(DESTDIR)$(incdir)
uninstall:
- rm -f $(DESTDIR)$(syslibdir)/$(LIBS)
- rm -f $(DESTDIR)$(syslibdir)/$(DEVLIB)
- rm -f $(DESTDIR)$(incdir)/mpath_cmd.h
+ $(RM) $(DESTDIR)$(syslibdir)/$(LIBS)
+ $(RM) $(DESTDIR)$(syslibdir)/$(DEVLIB)
+ $(RM) $(DESTDIR)$(incdir)/mpath_cmd.h
clean:
- rm -f core *.a *.o *.gz *.so *.so.*
+ $(RM) core *.a *.o *.gz *.so *.so.*
diff --git a/libmpathcmd/mpath_cmd.c b/libmpathcmd/mpath_cmd.c
index 1aaf5ea..2290ecb 100644
--- a/libmpathcmd/mpath_cmd.c
+++ b/libmpathcmd/mpath_cmd.c
@@ -142,6 +142,8 @@ int mpath_recv_reply(int fd, char **reply, unsigned int timeout)
len = mpath_recv_reply_len(fd, timeout);
if (len <= 0)
return len;
+ if (len > MAX_REPLY_LEN)
+ return -EINVAL;
*reply = malloc(len);
if (!*reply)
return -1;
diff --git a/libmpathcmd/mpath_cmd.h b/libmpathcmd/mpath_cmd.h
index 6d80a2f..7293d91 100644
--- a/libmpathcmd/mpath_cmd.h
+++ b/libmpathcmd/mpath_cmd.h
@@ -13,10 +13,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIB_MPATH_CMD_H
@@ -28,42 +26,43 @@ extern "C" {
#define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd"
#define DEFAULT_REPLY_TIMEOUT 1000
+#define MAX_REPLY_LEN 65536
/*
* DESCRIPTION:
- * Connect to the running multipathd daemon. On systems with the
- * multipathd.socket systemd unit file installed, this command will
- * start multipathd if it is not already running. This function
- * must be run before any of the others in this library
+ * Connect to the running multipathd daemon. On systems with the
+ * multipathd.socket systemd unit file installed, this command will
+ * start multipathd if it is not already running. This function
+ * must be run before any of the others in this library
*
* RETURNS:
- * A file descriptor on success. -1 on failure (with errno set).
+ * A file descriptor on success. -1 on failure (with errno set).
*/
int mpath_connect(void);
/*
* DESCRIPTION:
- * Disconnect from the multipathd daemon. This function must be
- * run after after processing all the multipath commands.
+ * Disconnect from the multipathd daemon. This function must be
+ * run after after processing all the multipath commands.
*
* RETURNS:
- * 0 on success. -1 on failure (with errno set).
+ * 0 on success. -1 on failure (with errno set).
*/
int mpath_disconnect(int fd);
/*
* DESCRIPTION
- * Send multipathd a command and return the reply. This function
- * does the same as calling mpath_send_cmd() and then
+ * Send multipathd a command and return the reply. This function
+ * does the same as calling mpath_send_cmd() and then
* mpath_recv_reply()
*
* RETURNS:
- * 0 on successs, and reply will either be NULL (if there was no
- * reply data), or point to the reply string, which must be freed by
- * the caller. -1 on failure (with errno set).
+ * 0 on successs, and reply will either be NULL (if there was no
+ * reply data), or point to the reply string, which must be freed by
+ * the caller. -1 on failure (with errno set).
*/
int mpath_process_cmd(int fd, const char *cmd, char **reply,
unsigned int timeout);
@@ -71,50 +70,50 @@ int mpath_process_cmd(int fd, const char *cmd, char **reply,
/*
* DESCRIPTION:
- * Send a command to multipathd
+ * Send a command to multipathd
*
* RETURNS:
- * 0 on success. -1 on failure (with errno set)
+ * 0 on success. -1 on failure (with errno set)
*/
int mpath_send_cmd(int fd, const char *cmd);
/*
* DESCRIPTION:
- * Return a reply from multipathd for a previously sent command.
- * This is equivalent to calling mpath_recv_reply_len(), allocating
- * a buffer of the appropriate size, and then calling
+ * Return a reply from multipathd for a previously sent command.
+ * This is equivalent to calling mpath_recv_reply_len(), allocating
+ * a buffer of the appropriate size, and then calling
* mpath_recv_reply_data() with that buffer.
*
* RETURNS:
- * 0 on success, and reply will either be NULL (if there was no
- * reply data), or point to the reply string, which must be freed by
- * the caller, -1 on failure (with errno set).
+ * 0 on success, and reply will either be NULL (if there was no
+ * reply data), or point to the reply string, which must be freed by
+ * the caller, -1 on failure (with errno set).
*/
int mpath_recv_reply(int fd, char **reply, unsigned int timeout);
/*
* DESCRIPTION:
- * Return the size of the upcoming reply data from the sent multipath
- * command. This must be called before calling mpath_recv_reply_data().
+ * Return the size of the upcoming reply data from the sent multipath
+ * command. This must be called before calling mpath_recv_reply_data().
*
* RETURNS:
- * The required size of the reply data buffer on success. -1 on
- * failure (with errno set).
+ * The required size of the reply data buffer on success. -1 on
+ * failure (with errno set).
*/
ssize_t mpath_recv_reply_len(int fd, unsigned int timeout);
/*
* DESCRIPTION:
- * Return the reply data from the sent multipath command.
- * mpath_recv_reply_len must be called first. reply must point to a
- * buffer of len size.
+ * Return the reply data from the sent multipath command.
+ * mpath_recv_reply_len must be called first. reply must point to a
+ * buffer of len size.
*
* RETURNS:
- * 0 on success, and reply will contain the reply data string. -1
- * on failure (with errno set).
+ * 0 on success, and reply will contain the reply data string. -1
+ * on failure (with errno set).
*/
int mpath_recv_reply_data(int fd, char *reply, size_t len,
unsigned int timeout);
diff --git a/libmpathpersist/Makefile b/libmpathpersist/Makefile
index 59db73a..07fcf70 100644
--- a/libmpathpersist/Makefile
+++ b/libmpathpersist/Makefile
@@ -1,30 +1,27 @@
# Makefile
#
-BUILD = glibc
include ../Makefile.inc
-INSTALL_PROGRAM = install
-
SONAME=0
DEVLIB = libmpathpersist.so
LIBS = $(DEVLIB).$(SONAME)
-CFLAGS += -I$(multipathdir) -I$(mpathpersistdir) -I$(mpathcmddir)
+CFLAGS += -I$(multipathdir) -I$(mpathpersistdir) -I$(mpathcmddir)
LIBDEPS += -lpthread -ldevmapper -ldl -L$(multipathdir) -lmultipath \
-L$(mpathcmddir) -lmpathcmd
-OBJS = mpath_persist.o mpath_updatepr.o mpath_pr_ioctl.o
+OBJS = mpath_persist.o mpath_updatepr.o mpath_pr_ioctl.o
all: $(LIBS)
-$(LIBS):
- $(CC) -Wall -fPIC -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
- $(GZIP) mpath_persistent_reserve_out.3 > mpath_persistent_reserve_out.3.gz
+$(LIBS):
+ $(CC) -Wall -fPIC -c $(CFLAGS) *.c
+ $(CC) $(SHARED_FLAGS) $(LIBDEPS) -Wl,-soname=$@ $(CFLAGS) -o $@ $(OBJS)
+ $(LN) $(LIBS) $(DEVLIB)
+ $(GZIP) mpath_persistent_reserve_in.3 > mpath_persistent_reserve_in.3.gz
+ $(GZIP) mpath_persistent_reserve_out.3 > mpath_persistent_reserve_out.3.gz
install: $(LIBS)
$(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir)
@@ -32,19 +29,20 @@ install: $(LIBS)
$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(syslibdir)
$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(man3dir)
$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(incdir)
- $(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)/usr/share/doc/mpathpersist/
- ln -sf $(DESTDIR)$(syslibdir)/$(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)$(incdir)
+ $(LN) $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB)
+ $(INSTALL_PROGRAM) -m 644 mpath_persistent_reserve_in.3.gz $(DESTDIR)$(man3dir)
+ $(INSTALL_PROGRAM) -m 644 mpath_persistent_reserve_out.3.gz $(DESTDIR)$(man3dir)
+ $(INSTALL_PROGRAM) -m 644 mpath_persist.h $(DESTDIR)$(incdir)
uninstall:
- rm -f $(DESTDIR)$(syslibdir)/$(LIBS)
- rm $(DESTDIR)$(man3dir)/mpath_persistent_reserve_in.3.gz
- rm $(DESTDIR)$(man3dir)/mpath_persistent_reserve_out.3.gz
+ $(RM) $(DESTDIR)$(syslibdir)/$(LIBS)
+ $(RM) $(DESTDIR)$(man3dir)/mpath_persistent_reserve_in.3.gz
+ $(RM) $(DESTDIR)$(man3dir)/mpath_persistent_reserve_out.3.gz
+ $(RM) $(DESTDIR)$(incdir)/mpath_persist.h
+ $(RM) $(DESTDIR)$(syslibdir)/$(DEVLIB)
clean:
- rm -f core *.a *.o
- rm -f libmpathpersist.so.0
- rm -f libmpathpersist.so
- rm -f mpath_persistent_reserve_in.3.gz mpath_persistent_reserve_out.3.gz
+ $(RM) core *.a *.o
+ $(RM) libmpathpersist.so.0
+ $(RM) libmpathpersist.so
+ $(RM) mpath_persistent_reserve_in.3.gz mpath_persistent_reserve_out.3.gz
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
index b23e116..252d6fc 100644
--- a/libmpathpersist/mpath_persist.c
+++ b/libmpathpersist/mpath_persist.c
@@ -1,25 +1,25 @@
#include <libdevmapper.h>
-#include <defaults.h>
+#include "defaults.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
-#include <vector.h>
-#include <checkers.h>
-#include <structs.h>
-#include <structs_vec.h>
+#include "vector.h"
+#include "checkers.h"
+#include "structs.h"
+#include "structs_vec.h"
#include <libudev.h>
-#include <prio.h>
+#include "prio.h"
#include <unistd.h>
-#include <devmapper.h>
-#include <debug.h>
-#include <config.h>
-#include <switchgroup.h>
-#include <discovery.h>
-#include <dmparser.h>
+#include "devmapper.h"
+#include "debug.h"
+#include "config.h"
+#include "switchgroup.h"
+#include "discovery.h"
+#include "dmparser.h"
#include <ctype.h>
-#include <propsel.h>
-#include <util.h>
+#include "propsel.h"
+#include "util.h"
#include "mpath_persist.h"
#include "mpathpr.h"
@@ -34,13 +34,17 @@
#define __STDC_FORMAT_MACROS 1
+struct udev *udev;
-int
+struct config *
mpath_lib_init (struct udev *udev)
{
- if (load_config(DEFAULT_CONFIGFILE, udev)){
+ struct config *conf;
+
+ conf = load_config(DEFAULT_CONFIGFILE);
+ if (!conf) {
condlog(0, "Failed to initialize multipath config.");
- return 1;
+ return NULL;
}
if (conf->max_fds) {
@@ -53,11 +57,11 @@ mpath_lib_init (struct udev *udev)
conf->max_fds, strerror(errno));
}
- return 0;
+ return conf;
}
int
-mpath_lib_exit (void)
+mpath_lib_exit (struct config *conf)
{
dm_lib_release();
dm_lib_exit();
@@ -84,7 +88,7 @@ updatepaths (struct multipath * mpp)
vector_foreach_slot (pgp->paths, pp, j){
if (!strlen(pp->dev)){
- if (devt2devname(pp->dev, PATH_SIZE,
+ if (devt2devname(pp->dev, FILE_NAME_SIZE,
pp->dev_t)){
/*
* path is not in sysfs anymore
@@ -93,16 +97,16 @@ updatepaths (struct multipath * mpp)
continue;
}
pp->mpp = mpp;
- pathinfo(pp, conf->hwtable, DI_ALL);
+ pathinfo(pp, conf, DI_ALL);
continue;
}
pp->mpp = mpp;
if (pp->state == PATH_UNCHECKED ||
pp->state == PATH_WILD)
- pathinfo(pp, conf->hwtable, DI_CHECKER);
+ pathinfo(pp, conf, DI_CHECKER);
if (pp->priority == PRIO_UNDEF)
- pathinfo(pp, conf->hwtable, DI_PRIO);
+ pathinfo(pp, conf, DI_PRIO);
}
}
return 0;
@@ -195,10 +199,14 @@ int mpath_persistent_reserve_in (int fd, int rq_servact,
if (!curmp || !pathvec){
condlog (0, "%s: vector allocation failed.", alias);
ret = MPATH_PR_DMMP_ERROR;
+ if (curmp)
+ vector_free(curmp);
+ if (pathvec)
+ vector_free(pathvec);
goto out;
}
- if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) {
+ if (path_discovery(pathvec, DI_SYSFS | DI_CHECKER) < 0) {
ret = MPATH_PR_DMMP_ERROR;
goto out1;
}
@@ -285,10 +293,14 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
if (!curmp || !pathvec){
condlog (0, "%s: vector allocation failed.", alias);
ret = MPATH_PR_DMMP_ERROR;
+ if (curmp)
+ vector_free(curmp);
+ if (pathvec)
+ vector_free(pathvec);
goto out;
}
- if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER) < 0) {
+ if (path_discovery(pathvec, DI_SYSFS | DI_CHECKER) < 0) {
ret = MPATH_PR_DMMP_ERROR;
goto out1;
}
@@ -308,7 +320,7 @@ int mpath_persistent_reserve_out ( int fd, int rq_servact, int rq_scope,
goto out1;
}
- select_reservation_key(mpp);
+ select_reservation_key(conf, mpp);
switch(rq_servact)
{
@@ -375,7 +387,8 @@ get_mpvec (vector curmp, vector pathvec, char * refwwid)
/*
* discard out of scope maps
*/
- if (mpp->alias && refwwid && strncmp (mpp->alias, refwwid, WWID_SIZE)){
+ if (mpp->alias && refwwid &&
+ strncmp (mpp->alias, refwwid, WWID_SIZE - 1)){
free_multipath (mpp, KEEP_PATHS);
vector_del_slot (curmp, i);
i--;
@@ -386,7 +399,7 @@ get_mpvec (vector curmp, vector pathvec, char * refwwid)
condlog(3, "params = %s", params);
dm_get_status(mpp->alias, status);
condlog(3, "status = %s", status);
- disassemble_map (pathvec, params, mpp);
+ disassemble_map (pathvec, params, mpp, 0);
/*
* disassemble_map() can add new paths to pathvec.
@@ -485,7 +498,8 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
condlog (1, "%s: %s path not up. Skip.", mpp->wwid, pp->dev);
continue;
}
- strncpy(thread[count].param.dev, pp->dev, FILE_NAME_SIZE);
+ strncpy(thread[count].param.dev, pp->dev,
+ FILE_NAME_SIZE - 1);
if (count && (thread[count].param.paramp->sa_flags & MPATH_F_SPEC_I_PT_MASK)){
/*
@@ -530,7 +544,7 @@ int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
memcpy(&thread[i].param.paramp->key, &thread[i].param.paramp->sa_key, 8);
memset(&thread[i].param.paramp->sa_key, 0, 8);
thread[i].param.status = MPATH_PR_SUCCESS;
- rc = pthread_create(&thread[i].id, &attr, mpath_prout_pthread_fn,
+ rc = pthread_create(&thread[i].id, &attr, mpath_prout_pthread_fn,
(void *)(&thread[i].param));
if (rc){
condlog (0, "%s: failed to create thread for rollback. %d", mpp->wwid, rc);
@@ -602,7 +616,7 @@ int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
int rc;
memset(&thread, 0, sizeof(thread));
- strncpy(param.dev, dev, FILE_NAME_SIZE);
+ strncpy(param.dev, dev, FILE_NAME_SIZE - 1);
/* Initialize and set thread joinable attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
@@ -670,7 +684,8 @@ int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
continue;
}
- strncpy(thread[count].param.dev, pp->dev, FILE_NAME_SIZE);
+ strncpy(thread[count].param.dev, pp->dev,
+ FILE_NAME_SIZE - 1);
condlog (3, "%s: sending pr out command to %s", mpp->wwid, pp->dev);
rc = pthread_create (&thread[count].id, &attr, mpath_prout_pthread_fn,
(void *) (&thread[count].param));
@@ -910,6 +925,3 @@ int update_map_pr(struct multipath *mpp)
free(resp);
return MPATH_PR_SUCCESS;
}
-
-
-
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
index a5e7868..fde0416 100644
--- a/libmpathpersist/mpath_persist.h
+++ b/libmpathpersist/mpath_persist.h
@@ -12,7 +12,7 @@ extern "C" {
#define MPATH_MAX_PARAM_LEN 8192
-#define MPATH_MX_TIDS 32 /* Max number of transport ids"*/
+#define MPATH_MX_TIDS 32 /* Max number of transport ids"*/
#define MPATH_MX_TID_LEN 256 /* Max lenght of transport id */
/* PRIN Service Actions */
@@ -34,24 +34,24 @@ extern "C" {
#define MPATH_LU_SCOPE 0x00 /* LU_SCOPE */
/* Persistent reservations type */
-#define MPATH_PRTPE_WE 0x01 /* Write Exclusive */
-#define MPATH_PRTPE_EA 0x03 /* Exclusive Access*/
-#define MPATH_PRTPE_WE_RO 0x05 /* WriteExclusive Registrants Only */
-#define MPATH_PRTPE_EA_RO 0x06 /* Exclusive Access. Registrants Only*/
+#define MPATH_PRTPE_WE 0x01 /* Write Exclusive */
+#define MPATH_PRTPE_EA 0x03 /* Exclusive Access*/
+#define MPATH_PRTPE_WE_RO 0x05 /* WriteExclusive Registrants Only */
+#define MPATH_PRTPE_EA_RO 0x06 /* Exclusive Access. Registrants Only*/
#define MPATH_PRTPE_WE_AR 0x07 /* Write Exclusive. All Registrants*/
-#define MPATH_PRTPE_EA_AR 0x08 /* Exclusive Access. All Registrants */
+#define MPATH_PRTPE_EA_AR 0x08 /* Exclusive Access. All Registrants */
/* PR RETURN_STATUS */
-#define MPATH_PR_SUCCESS 0
+#define MPATH_PR_SUCCESS 0
#define MPATH_PR_SYNTAX_ERROR 1 /* syntax error or invalid parameter */
/* status for check condition */
-#define MPATH_PR_SENSE_NOT_READY 2 /* [sk,asc,ascq: 0x2,*,*] */
+#define MPATH_PR_SENSE_NOT_READY 2 /* [sk,asc,ascq: 0x2,*,*] */
#define MPATH_PR_SENSE_MEDIUM_ERROR 3 /* [sk,asc,ascq: 0x3,*,*] */
#define MPATH_PR_SENSE_HARDWARE_ERROR 4 /* [sk,asc,ascq: 0x4,*,*] */
-#define MPATH_PR_ILLEGAL_REQ 5 /* [sk,asc,ascq: 0x5,*,*]*/
+#define MPATH_PR_ILLEGAL_REQ 5 /* [sk,asc,ascq: 0x5,*,*]*/
#define MPATH_PR_SENSE_UNIT_ATTENTION 6 /* [sk,asc,ascq: 0x6,*,*] */
-#define MPATH_PR_SENSE_INVALID_OP 7 /* [sk,asc,ascq: 0x5,0x20,0x0]*/
+#define MPATH_PR_SENSE_INVALID_OP 7 /* [sk,asc,ascq: 0x5,0x20,0x0]*/
#define MPATH_PR_SENSE_ABORTED_COMMAND 8 /* [sk,asc,ascq: 0xb,*,*] */
#define MPATH_PR_NO_SENSE 9 /* [sk,asc,ascq: 0x0,*,*] */
@@ -66,7 +66,7 @@ extern "C" {
#define MPATH_F_APTPL_MASK 0x01 /* APTPL MASK*/
#define MPATH_F_ALL_TG_PT_MASK 0x04 /* ALL_TG_PT MASK*/
#define MPATH_F_SPEC_I_PT_MASK 0x08 /* SPEC_I_PT MASK*/
-#define MPATH_PR_TYPE_MASK 0x0f /* TYPE MASK*/
+#define MPATH_PR_TYPE_MASK 0x0f /* TYPE MASK*/
#define MPATH_PR_SCOPE_MASK 0xf0 /* SCOPE MASK*/
/*Transport ID PROTOCOL IDENTIFIER values */
@@ -125,7 +125,7 @@ struct transportid
struct prin_fulldescr
{
uint8_t key[8];
- uint8_t flag; /* All_tg_pt and reservation holder */
+ uint8_t flag; /* All_tg_pt and reservation holder */
uint8_t scope_type; /* Use PR SCOPE AND TYPE MASK specified above.
Meaningful only for reservation holder */
uint16_t rtpi;
@@ -151,7 +151,7 @@ struct prin_resp
}prin_descriptor;
};
-struct prout_param_descriptor { /* PROUT parameter descriptor */
+struct prout_param_descriptor { /* PROUT parameter descriptor */
uint8_t key[8];
uint8_t sa_key[8];
uint32_t _obsolete;
@@ -172,9 +172,9 @@ struct prout_param_descriptor { /* PROUT parameter descriptor */
* before performing reservation management functions.
* RESTRICTIONS:
*
- * RETURNS: 0->Success, 1->Failed.
+ * RETURNS: struct config ->Success, NULL->Failed.
*/
-extern int mpath_lib_init (struct udev *udev);
+extern struct config * mpath_lib_init (struct udev *udev);
/*
@@ -185,7 +185,7 @@ extern int mpath_lib_init (struct udev *udev);
*
* RETURNS: 0->Success, 1->Failed.
*/
-extern int mpath_lib_exit (void );
+extern int mpath_lib_exit (struct config *conf);
/*
@@ -195,7 +195,7 @@ extern int mpath_lib_exit (void );
* @fd: The file descriptor of a multipath device. Input argument.
* @rq_servact: PRIN command service action. Input argument
* @resp: The response from PRIN service action. The resp is a struct specified above. The caller should
- * manage the memory allocation of this struct
+ * manage the memory allocation of this struct
* @noisy: Turn on debugging trace: Input argument. 0->Disable, 1->Enable
* @verbose: Set verbosity level. Input argument. value:[0-3]. 0->disabled, 3->Max verbose
*
@@ -221,7 +221,7 @@ extern int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp
* 7h (Write exclusive - All registrants)
* 8h (Exclusive access - All registrants).
* @paramp: PROUT command parameter data. The paramp is a struct which describes PROUT
- * parameter list. The caller should manage the memory allocation of this struct.
+ * parameter list. The caller should manage the memory allocation of this struct.
* @noisy: Turn on debugging trace: Input argument.0->Disable, 1->Enable.
* @verbose: Set verbosity level. Input argument. value:0 to 3. 0->disabled, 3->Max verbose
*
diff --git a/libmpathpersist/mpath_persistent_reserve_in.3 b/libmpathpersist/mpath_persistent_reserve_in.3
index c404e13..8601645 100644
--- a/libmpathpersist/mpath_persistent_reserve_in.3
+++ b/libmpathpersist/mpath_persistent_reserve_in.3
@@ -1,5 +1,5 @@
.\"
-.TH MPATH_PERSISTENT_RESERVE_IN 3 2011-04-08 "Linux Manpage"
+.TH MPATH_PERSISTENT_RESERVE_IN 3 2011-04-08 "Linux Manpage"
.SH NAME
mpath_persistent_reserve_in
.SH SYNOPSIS
@@ -34,10 +34,10 @@ sends PRIN command to the DM device and gets the response.
.I MPATH_PR_SUCCESS
.B if PR command successful
.br
-.I MPATH_PR_SYNTAX_ERROR
+.I MPATH_PR_SYNTAX_ERROR
.B if syntax error or invalid parameter
.br
-.I MPATH_PR_SENSE_NOT_READY
+.I MPATH_PR_SENSE_NOT_READY
.B if command fails with [sk,asc,ascq: 0x2,*,*]
.br
.I MPATH_PR_SENSE_MEDIUM_ERROR
@@ -61,14 +61,14 @@ sends PRIN command to the DM device and gets the response.
.I MPATH_PR_NO_SENSE
.B if command fails with [sk,asc,ascq: 0x0,*,*]
.br
-.I MPATH_PR_SENSE_MALFORMED
+.I MPATH_PR_SENSE_MALFORMED
.B if command fails with SCSI command malformed
.br
.I MPATH_PR_FILE_ERROR
.B if command fails while accessing file (device node) problems(e.g. not found)
.br
.I MPATH_PR_DMMP_ERROR
-.B if Device Mapper related error.(e.g Error in getting dm info)
+.B if Device Mapper related error.(e.g Error in getting dm info)
.br
.I MPATH_PR_OTHER
.B if other error/warning has occurred(e.g transport or driver error)
diff --git a/libmpathpersist/mpath_persistent_reserve_out.3 b/libmpathpersist/mpath_persistent_reserve_out.3
index f7f84ff..8a3b52c 100644
--- a/libmpathpersist/mpath_persistent_reserve_out.3
+++ b/libmpathpersist/mpath_persistent_reserve_out.3
@@ -1,5 +1,5 @@
.\"
-.TH MPATH_PERSISTENT_RESERVE_OUT 3 2011-04-08 "Linux Manpage"
+.TH MPATH_PERSISTENT_RESERVE_OUT 3 2011-04-08 "Linux Manpage"
.SH NAME
mpath_persistent_reserve_out
.SH SYNOPSIS
@@ -14,7 +14,7 @@ sends PR OUT command to the DM device and gets the response.
.br
.BI Parameters:
.br
-.I fd
+.I fd
.B The file descriptor of a multipath device. Input argument.
.br
.I rq_servact
@@ -43,10 +43,10 @@ sends PR OUT command to the DM device and gets the response.
.I MPATH_PR_SUCCESS
.B if PR command successful else returns any one of the status mentioned below
.br
-.I MPATH_PR_SYNTAX_ERROR
+.I MPATH_PR_SYNTAX_ERROR
.B if syntax error or invalid parameter
.br
-.I MPATH_PR_SENSE_NOT_READY
+.I MPATH_PR_SENSE_NOT_READY
.B if command fails with [sk,asc,ascq: 0x2,*,*]
.br
.I MPATH_PR_SENSE_MEDIUM_ERROR
@@ -70,7 +70,7 @@ sends PR OUT command to the DM device and gets the response.
.I MPATH_PR_NO_SENSE
.B if command fails with [sk,asc,ascq: 0x0,*,*]
.br
-.I MPATH_PR_SENSE_MALFORMED
+.I MPATH_PR_SENSE_MALFORMED
.B if command fails with SCSI command malformed
.br
.I MPATH_PR_RESERV_CONFLICT
@@ -80,7 +80,7 @@ sends PR OUT command to the DM device and gets the response.
.B if command fails while accessing file (device node) problems(e.g. not found)
.br
.I MPATH_PR_DMMP_ERROR
-.B if Device Mapper related error.(e.g Error in getting dm info)
+.B if Device Mapper related error.(e.g Error in getting dm info)
.br
.I MPATH_PR_OTHER
.B if other error/warning has occurred(e.g transport or driver error)
@@ -88,5 +88,5 @@ sends PR OUT command to the DM device and gets the response.
.SH "SEE ALSO"
-.I mpath_persistent_reserve_in mpathpersist /usr/share/doc/mpathpersist/README
+.I mpath_persistent_reserve_in mpathpersist /usr/share/doc/mpathpersist/README
.br
diff --git a/libmpathpersist/mpath_pr_ioctl.c b/libmpathpersist/mpath_pr_ioctl.c
index c85fd10..cf7141a 100644
--- a/libmpathpersist/mpath_pr_ioctl.c
+++ b/libmpathpersist/mpath_pr_ioctl.c
@@ -12,9 +12,9 @@
#include <unistd.h>
#include <libudev.h>
#include "mpath_pr_ioctl.h"
-#include <mpath_persist.h>
+#include "mpath_persist.h"
-#include <debug.h>
+#include "debug.h"
#define FILE_NAME_SIZE 256
@@ -24,10 +24,11 @@
int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp *resp, int noisy);
void mpath_format_readkeys(struct prin_resp *pr_buff, int len , int noisy);
void mpath_format_readfullstatus(struct prin_resp *pr_buff, int len, int noisy);
-int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr, SenseData_t Sensedata, int noisy);
+int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr,
+ SenseData_t *Sensedata, int noisy);
void dumpHex(const char* str, int len, int no_ascii);
int prout_do_scsi_ioctl( char * dev, int rq_servact, int rq_scope,
- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy);
+ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy);
uint32_t format_transportids(struct prout_param_descriptor *paramp);
void mpath_reverse_uint32_byteorder(uint32_t *num);
void mpath_reverse_uint16_byteorder(uint16_t *num);
@@ -38,7 +39,7 @@ int mpath_isLittleEndian(void);
extern unsigned int mpath_mx_alloc_len;
int prout_do_scsi_ioctl(char * dev, int rq_servact, int rq_scope,
- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
+ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy)
{
int status, paramlen = 24, ret = 0;
@@ -64,7 +65,7 @@ int prout_do_scsi_ioctl(char * dev, int rq_servact, int rq_scope,
{
translen = format_transportids(paramp);
paramlen = 24 + translen;
- }
+ }
else
paramlen = 24;
@@ -75,7 +76,7 @@ int prout_do_scsi_ioctl(char * dev, int rq_servact, int rq_scope,
cdb[8] = (unsigned char)(paramlen & 0xff);
retry :
- condlog(3, "%s: rq_servact = %d", dev, rq_servact);
+ condlog(3, "%s: rq_servact = %d", dev, rq_servact);
condlog(3, "%s: rq_scope = %d ", dev, rq_scope);
condlog(3, "%s: rq_type = %d ", dev, rq_type);
condlog(3, "%s: paramlen = %d", dev, paramlen);
@@ -113,13 +114,13 @@ retry :
condlog(2, "%s: Duration=%u (ms)", dev, io_hdr.duration);
- status = mpath_translate_response(dev, io_hdr, Sensedata, noisy);
+ status = mpath_translate_response(dev, io_hdr, &Sensedata, noisy);
condlog(3, "%s: status = %d", dev, status);
if (status == MPATH_PR_SENSE_UNIT_ATTENTION && (retry > 0))
{
--retry;
- condlog(2, "%s: retrying for Unit Attention. Remaining retries = %d",
+ condlog(2, "%s: retrying for Unit Attention. Remaining retries = %d",
dev, retry);
goto retry;
}
@@ -134,13 +135,13 @@ retry :
goto retry;
}
- close(fd);
+ close(fd);
return status;
}
uint32_t format_transportids(struct prout_param_descriptor *paramp)
{
- int i = 0, len;
+ int i = 0, len;
uint32_t buff_offset = 4;
memset(paramp->private_buffer, 0, MPATH_MAX_PARAM_LEN);
for (i=0; i < paramp->num_transportid; i++ )
@@ -163,43 +164,43 @@ uint32_t format_transportids(struct prout_param_descriptor *paramp)
break;
case MPATH_PROTOCOL_ID_ISCSI:
buff_offset += 1;
- len = (paramp->trnptid_list[i]->iscsi_name[1] & 0xff)+2;
+ len = (paramp->trnptid_list[i]->iscsi_name[1] & 0xff)+2;
memcpy(&paramp->private_buffer[buff_offset], &paramp->trnptid_list[i]->iscsi_name,len);
- buff_offset += len ;
+ buff_offset += len ;
break;
}
}
- buff_offset -= 4;
+ buff_offset -= 4;
paramp->private_buffer[0] = (unsigned char)((buff_offset >> 24) & 0xff);
paramp->private_buffer[1] = (unsigned char)((buff_offset >> 16) & 0xff);
paramp->private_buffer[2] = (unsigned char)((buff_offset >> 8) & 0xff);
paramp->private_buffer[3] = (unsigned char)(buff_offset & 0xff);
- buff_offset += 4;
- return buff_offset;
+ buff_offset += 4;
+ return buff_offset;
}
void mpath_format_readkeys( struct prin_resp *pr_buff, int len, int noisy)
{
- mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.prgeneration);
- mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.additional_length);
+ mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.prgeneration);
+ mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.additional_length);
}
void mpath_format_readresv(struct prin_resp *pr_buff, int len, int noisy)
{
- mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.prgeneration);
- mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.additional_length);
+ mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.prgeneration);
+ mpath_reverse_uint32_byteorder(&pr_buff->prin_descriptor.prin_readkeys.additional_length);
- return;
+ return;
}
void mpath_format_reportcapabilities(struct prin_resp *pr_buff, int len, int noisy)
{
- mpath_reverse_uint16_byteorder(&pr_buff->prin_descriptor.prin_readcap.length);
- mpath_reverse_uint16_byteorder(&pr_buff->prin_descriptor.prin_readcap.pr_type_mask);
+ mpath_reverse_uint16_byteorder(&pr_buff->prin_descriptor.prin_readcap.length);
+ mpath_reverse_uint16_byteorder(&pr_buff->prin_descriptor.prin_readcap.pr_type_mask);
- return;
+ return;
}
void mpath_format_readfullstatus(struct prin_resp *pr_buff, int len, int noisy)
@@ -304,11 +305,11 @@ int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp * resp, int
{MPATH_PRIN_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0};
snprintf(devname, FILE_NAME_SIZE, "/dev/%s",dev);
- fd = open(devname, O_WRONLY);
- if(fd < 0){
- condlog(0, "%s: Unable to open device ", dev);
+ fd = open(devname, O_WRONLY);
+ if(fd < 0){
+ condlog(0, "%s: Unable to open device ", dev);
return MPATH_PR_FILE_ERROR;
- }
+ }
if (mpath_mx_alloc_len)
mx_resp_len = mpath_mx_alloc_len;
@@ -353,7 +354,7 @@ retry :
condlog(2, "%s: duration = %u (ms)", dev, io_hdr.duration);
condlog(2, "%s: persistent reservation in: requested %d bytes but got %d bytes)", dev, mx_resp_len, got);
- status = mpath_translate_response(dev, io_hdr, Sensedata, noisy);
+ status = mpath_translate_response(dev, io_hdr, &Sensedata, noisy);
if (status == MPATH_PR_SENSE_UNIT_ATTENTION && (retry > 0))
{
@@ -398,26 +399,25 @@ out:
return status;
}
-int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr, SenseData_t Sensedata, int noisy)
+int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr,
+ SenseData_t *Sensedata, int noisy)
{
- condlog(3, "%s: status driver:%02x host:%02x scsi:%02x", dev,
+ condlog(3, "%s: status driver:%02x host:%02x scsi:%02x", dev,
io_hdr.driver_status, io_hdr.host_status ,io_hdr.status);
io_hdr.status &= 0x7e;
- if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
- (0 == io_hdr.driver_status))
- {
+ if ((0 == io_hdr.status) &&
+ (0 == io_hdr.host_status) &&
+ (0 == io_hdr.driver_status))
return MPATH_PR_SUCCESS;
- }
- switch(io_hdr.status)
- {
+ switch(io_hdr.status) {
case SAM_STAT_GOOD:
break;
case SAM_STAT_CHECK_CONDITION:
- condlog(2, "%s: Sense_Key=%02x, ASC=%02x ASCQ=%02x", dev,
- Sensedata.Sense_Key, Sensedata.ASC, Sensedata.ASCQ);
- switch(Sensedata.Sense_Key)
- {
+ condlog(2, "%s: Sense_Key=%02x, ASC=%02x ASCQ=%02x",
+ dev, Sensedata->Sense_Key,
+ Sensedata->ASC, Sensedata->ASCQ);
+ switch(Sensedata->Sense_Key) {
case NO_SENSE:
return MPATH_PR_NO_SENSE;
case RECOVERED_ERROR:
@@ -450,8 +450,7 @@ int mpath_translate_response (char * dev, struct sg_io_hdr io_hdr, SenseData_t S
return MPATH_PR_OTHER;
}
- switch(io_hdr.host_status)
- {
+ switch(io_hdr.host_status) {
case DID_OK :
break;
default :
@@ -560,25 +559,25 @@ dumpHex(const char* str, int len, int log)
int get_prin_length(int rq_servact)
{
- int mx_resp_len;
- switch (rq_servact)
- {
- case MPATH_PRIN_RKEY_SA:
- mx_resp_len = sizeof(struct prin_readdescr);
- break;
- case MPATH_PRIN_RRES_SA :
- mx_resp_len = sizeof(struct prin_resvdescr);
- break;
- case MPATH_PRIN_RCAP_SA :
- mx_resp_len = sizeof(struct prin_capdescr);
- break;
- case MPATH_PRIN_RFSTAT_SA:
- mx_resp_len = sizeof(struct print_fulldescr_list) + sizeof(struct prin_fulldescr *)*32;
- break;
+ int mx_resp_len;
+ switch (rq_servact)
+ {
+ case MPATH_PRIN_RKEY_SA:
+ mx_resp_len = sizeof(struct prin_readdescr);
+ break;
+ case MPATH_PRIN_RRES_SA :
+ mx_resp_len = sizeof(struct prin_resvdescr);
+ break;
+ case MPATH_PRIN_RCAP_SA :
+ mx_resp_len = sizeof(struct prin_capdescr);
+ break;
+ case MPATH_PRIN_RFSTAT_SA:
+ mx_resp_len = sizeof(struct print_fulldescr_list) + sizeof(struct prin_fulldescr *)*32;
+ break;
default:
condlog(0, "invalid service action, %d", rq_servact);
mx_resp_len = 0;
break;
- }
- return mx_resp_len;
+ }
+ return mx_resp_len;
}
diff --git a/libmpathpersist/mpath_pr_ioctl.h b/libmpathpersist/mpath_pr_ioctl.h
index 573ff15..7dfda5a 100644
--- a/libmpathpersist/mpath_pr_ioctl.h
+++ b/libmpathpersist/mpath_pr_ioctl.h
@@ -107,5 +107,3 @@ typedef struct SenseData
/* Driver status */
#define DRIVER_OK 0x00
-
-
diff --git a/libmpathpersist/mpath_updatepr.c b/libmpathpersist/mpath_updatepr.c
index bda8991..9ff4b30 100644
--- a/libmpathpersist/mpath_updatepr.c
+++ b/libmpathpersist/mpath_updatepr.c
@@ -1,5 +1,5 @@
-#include<stdio.h>
-#include<unistd.h>
+#include <stdio.h>
+#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
@@ -9,11 +9,11 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/poll.h>
+#include <poll.h>
#include <errno.h>
-#include <debug.h>
-#include <mpath_cmd.h>
-#include <uxsock.h>
+#include "debug.h"
+#include "mpath_cmd.h"
+#include "uxsock.h"
#include "memory.h"
unsigned long mem_allocated; /* Total memory used in Bytes */
@@ -33,10 +33,14 @@ int update_prflag(char * arg1, char * arg2, int noisy)
snprintf(str,sizeof(str),"map %s %s", arg1, arg2);
condlog (2, "%s: pr flag message=%s", arg1, str);
- send_packet(fd, str);
+ if (send_packet(fd, str) != 0) {
+ condlog(2, "%s: message=%s send error=%d", arg1, str, errno);
+ mpath_disconnect(fd);
+ return -2;
+ }
ret = recv_packet(fd, &reply, DEFAULT_REPLY_TIMEOUT);
if (ret < 0) {
- condlog(2, "%s: message=%s error=%d", arg1, str, errno);
+ condlog(2, "%s: message=%s recv error=%d", arg1, str, errno);
ret = -2;
} else {
condlog (2, "%s: message=%s reply=%s", arg1, str, reply);
diff --git a/libmpathpersist/mpathpr.h b/libmpathpersist/mpathpr.h
index d69a732..cd58201 100644
--- a/libmpathpersist/mpathpr.h
+++ b/libmpathpersist/mpathpr.h
@@ -3,26 +3,26 @@
struct prin_param {
char dev[FILE_NAME_SIZE];
- int rq_servact;
- struct prin_resp *resp;
- int noisy;
- int status;
+ int rq_servact;
+ struct prin_resp *resp;
+ int noisy;
+ int status;
};
struct prout_param {
char dev[FILE_NAME_SIZE];
- int rq_servact;
- int rq_scope;
- unsigned int rq_type;
- struct prout_param_descriptor *paramp;
- int noisy;
- int status;
+ int rq_servact;
+ int rq_scope;
+ unsigned int rq_type;
+ struct prout_param_descriptor *paramp;
+ int noisy;
+ int status;
};
struct threadinfo {
- int status;
- pthread_t id;
- struct prout_param param;
+ int status;
+ pthread_t id;
+ struct prout_param param;
};
@@ -31,7 +31,7 @@ struct config * conf;
int prin_do_scsi_ioctl(char * dev, int rq_servact, struct prin_resp * resp, int noisy);
int prout_do_scsi_ioctl( char * dev, int rq_servact, int rq_scope,
- unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy);
+ unsigned int rq_type, struct prout_param_descriptor *paramp, int noisy);
void * _mpath_pr_update (void *arg);
int mpath_send_prin_activepath (char * dev, int rq_servact, struct prin_resp * resp, int noisy);
int get_mpvec (vector curmp, vector pathvec, char * refwwid);
@@ -39,13 +39,13 @@ void * mpath_prout_pthread_fn(void *p);
void dumpHex(const char* , int len, int no_ascii);
int mpath_prout_reg(struct multipath *mpp,int rq_servact, int rq_scope,
- unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy);
+ unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy);
int mpath_prout_common(struct multipath *mpp,int rq_servact, int rq_scope,
- unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy);
+ unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy);
int mpath_prout_rel(struct multipath *mpp,int rq_servact, int rq_scope,
- unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy);
+ unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy);
int send_prout_activepath(char * dev, int rq_servact, int rq_scope,
- unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy);
+ unsigned int rq_type, struct prout_param_descriptor * paramp, int noisy);
int update_prflag(char * arg1, char * arg2, int noisy);
void * mpath_alloc_prin_response(int prin_sa);
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
index 1ee968e..a14d4b3 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
@@ -57,15 +57,17 @@ all: $(LIBS)
$(LIBS): $(OBJS)
$(CC) $(LDFLAGS) $(SHARED_FLAGS) -Wl,-soname=$@ $(CFLAGS) -o $@ $(OBJS) $(LIBDEPS)
- ln -sf $@ $(DEVLIB)
+ $(LN) $@ $(DEVLIB)
install:
$(INSTALL_PROGRAM) -d $(DESTDIR)$(syslibdir)
$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(syslibdir)/$(LIBS)
$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(libdir)
+ $(LN) $(LIBS) $(DESTDIR)$(syslibdir)/$(DEVLIB)
uninstall:
- rm -f $(DESTDIR)$(syslibdir)/$(LIBS)
+ $(RM) $(DESTDIR)$(syslibdir)/$(LIBS)
+ $(RM) $(DESTDIR)$(syslibdir)/$(DEVLIB)
clean:
- rm -f core *.a *.o *.gz *.so *.so.*
+ $(RM) core *.a *.o *.gz *.so *.so.*
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
index 7d12a0c..b86843a 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
@@ -36,6 +36,14 @@
* See the file COPYING included with this distribution for more details.
*/
+int
+valid_alias(char *alias)
+{
+ if (strchr(alias, '/') != NULL)
+ return 0;
+ return 1;
+}
+
static int
format_devname(char *name, int id, int len, char *prefix)
@@ -221,7 +229,8 @@ allocate_binding(int fd, char *wwid, int id, char *prefix)
return NULL;
}
c = strchr(buf, ' ');
- *c = '\0';
+ if (c)
+ *c = '\0';
alias = strdup(buf);
if (alias == NULL)
condlog(0, "cannot copy new alias from bindings file : %s",
diff --git a/libmultipath/alias.h b/libmultipath/alias.h
index 9cb3e8f..95473ff 100644
--- a/libmultipath/alias.h
+++ b/libmultipath/alias.h
@@ -7,6 +7,7 @@
"# alias wwid\n" \
"#\n"
+int valid_alias(char *alias);
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);
diff --git a/libmultipath/blacklist.h b/libmultipath/blacklist.h
index 24a5fa5..443025d 100644
--- a/libmultipath/blacklist.h
+++ b/libmultipath/blacklist.h
@@ -2,7 +2,7 @@
#define _BLACKLIST_H
#include <libudev.h>
-#include "regex.h"
+#include <regex.h>
#define MATCH_NOTHING 0
#define MATCH_WWID_BLIST 1
diff --git a/libmultipath/callout.c b/libmultipath/callout.c
index d671b0c..4d1b067 100644
--- a/libmultipath/callout.c
+++ b/libmultipath/callout.c
@@ -76,8 +76,10 @@ int execute_program(char *path, char *value, int len)
/* Ignore writes to stderr */
null_fd = open("/dev/null", O_WRONLY);
if (null_fd > 0) {
+ int err_fd __attribute__ ((unused));
+
close(STDERR_FILENO);
- retval = dup(null_fd);
+ err_fd = dup(null_fd);
close(null_fd);
}
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
index ef1d099..ad7d96c 100644
--- a/libmultipath/checkers.c
+++ b/libmultipath/checkers.c
@@ -7,7 +7,6 @@
#include "debug.h"
#include "checkers.h"
#include "vector.h"
-#include "config.h"
char *checker_state_names[] = {
"wild",
@@ -29,9 +28,9 @@ char * checker_state_name (int i)
return checker_state_names[i];
}
-int init_checkers (void)
+int init_checkers (char *multipath_dir)
{
- if (!add_checker(DEFAULT_CHECKER))
+ if (!add_checker(multipath_dir, DEFAULT_CHECKER))
return 1;
return 0;
}
@@ -89,10 +88,10 @@ struct checker * checker_lookup (char * name)
if (!strncmp(name, c->name, CHECKER_NAME_LEN))
return c;
}
- return add_checker(name);
+ return NULL;
}
-struct checker * add_checker (char * name)
+struct checker * add_checker (char *multipath_dir, char * name)
{
char libname[LIB_CHECKER_NAMELEN];
struct stat stbuf;
@@ -104,10 +103,10 @@ struct checker * add_checker (char * name)
return NULL;
snprintf(c->name, CHECKER_NAME_LEN, "%s", name);
snprintf(libname, LIB_CHECKER_NAMELEN, "%s/libcheck%s.so",
- conf->multipath_dir, name);
+ multipath_dir, name);
if (stat(libname,&stbuf) < 0) {
condlog(0,"Checker '%s' not found in %s",
- name, conf->multipath_dir);
+ name, multipath_dir);
goto out;
}
condlog(3, "loading %s checker", libname);
@@ -253,13 +252,18 @@ void checker_clear_message (struct checker *c)
c->message[0] = '\0';
}
-void checker_get (struct checker * dst, char * name)
+void checker_get (char *multipath_dir, struct checker * dst, char * name)
{
- struct checker * src = checker_lookup(name);
+ struct checker * src = NULL;
if (!dst)
return;
+ if (name && strlen(name)) {
+ src = checker_lookup(name);
+ if (!src)
+ src = add_checker(multipath_dir, name);
+ }
if (!src) {
dst->check = NULL;
return;
diff --git a/libmultipath/checkers.h b/libmultipath/checkers.h
index a935b3f..ac382d7 100644
--- a/libmultipath/checkers.h
+++ b/libmultipath/checkers.h
@@ -85,7 +85,7 @@ enum path_check_state {
#define READSECTOR0 "readsector0"
#define CCISS_TUR "cciss_tur"
-#define DEFAULT_CHECKER DIRECTIO
+#define DEFAULT_CHECKER TUR
#define ASYNC_TIMEOUT_SEC 30
@@ -119,9 +119,9 @@ struct checker {
#define MSG(c, fmt, args...) snprintf((c)->message, CHECKER_MSG_LEN, fmt, ##args);
char * checker_state_name (int);
-int init_checkers (void);
+int init_checkers (char *);
void cleanup_checkers (void);
-struct checker * add_checker (char *);
+struct checker * add_checker (char *, char *);
struct checker * checker_lookup (char *);
int checker_init (struct checker *, void **);
void checker_put (struct checker *);
@@ -136,6 +136,6 @@ int checker_selected (struct checker *);
char * checker_name (struct checker *);
char * checker_message (struct checker *);
void checker_clear_message (struct checker *c);
-void checker_get (struct checker *, char *);
+void checker_get (char *, struct checker *, char *);
#endif /* _CHECKERS_H */
diff --git a/libmultipath/checkers/Makefile b/libmultipath/checkers/Makefile
index 4b1a108..fb8fff0 100644
--- a/libmultipath/checkers/Makefile
+++ b/libmultipath/checkers/Makefile
@@ -27,7 +27,7 @@ install:
$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir)
uninstall:
- for file in $(LIBS); do rm -f $(DESTDIR)$(libdir)/$$file; done
+ for file in $(LIBS); do $(RM) $(DESTDIR)$(libdir)/$$file; done
clean:
- rm -f core *.a *.o *.gz *.so
+ $(RM) core *.a *.o *.gz *.so
diff --git a/libmultipath/checkers/cciss.h b/libmultipath/checkers/cciss.h
index ebdff06..c9fa84a 100644
--- a/libmultipath/checkers/cciss.h
+++ b/libmultipath/checkers/cciss.h
@@ -139,4 +139,3 @@ void cciss_free (struct checker * c);
int cciss_tur( struct checker *);
#endif
-
diff --git a/libmultipath/checkers/cciss_tur.c b/libmultipath/checkers/cciss_tur.c
index 4c26901..81500dc 100644
--- a/libmultipath/checkers/cciss_tur.c
+++ b/libmultipath/checkers/cciss_tur.c
@@ -14,11 +14,7 @@
* for more details. *
* *
* 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., *
- * 675 Mass Ave, Cambridge, MA 02139, USA. *
- * *
- * The copy of the GNU General Public License is available at *
- * /opt/hp/HPDMmultipath-tool directoy *
+ * with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*****************************************************************************
*/
diff --git a/libmultipath/checkers/directio.c b/libmultipath/checkers/directio.c
index 46fe6a7..94bf8f7 100644
--- a/libmultipath/checkers/directio.c
+++ b/libmultipath/checkers/directio.c
@@ -104,9 +104,11 @@ void libcheck_free (struct checker * c)
if (ct->reset_flags) {
if ((flags = fcntl(c->fd, F_GETFL)) >= 0) {
+ int ret __attribute__ ((unused));
+
flags &= ~O_DIRECT;
/* No point in checking for errors */
- fcntl(c->fd, F_SETFL, flags);
+ ret = fcntl(c->fd, F_SETFL, flags);
}
}
diff --git a/libmultipath/checkers/emc_clariion.c b/libmultipath/checkers/emc_clariion.c
index a797734..5e416a0 100644
--- a/libmultipath/checkers/emc_clariion.c
+++ b/libmultipath/checkers/emc_clariion.c
@@ -10,12 +10,12 @@
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
-#include <memory.h>
#include "../libmultipath/sg_include.h"
#include "libsg.h"
#include "checkers.h"
#include "debug.h"
+#include "memory.h"
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
diff --git a/libmultipath/checkers/libsg.c b/libmultipath/checkers/libsg.c
index 0d3af1f..958ea92 100644
--- a/libmultipath/checkers/libsg.c
+++ b/libmultipath/checkers/libsg.c
@@ -19,7 +19,6 @@ sg_read (int sg_fd, unsigned char * buff, int buff_len,
long long start_block = 0;
int bs = 512;
int cdbsz = 10;
- int * diop = NULL;
unsigned char rdCmd[cdbsz];
unsigned char *sbb = sense;
@@ -55,8 +54,6 @@ sg_read (int sg_fd, unsigned char * buff, int buff_len,
io_hdr.sbp = sense;
io_hdr.timeout = timeout * 1000;
io_hdr.pack_id = (int)start_block;
- if (diop && *diop)
- io_hdr.flags |= SG_FLAG_DIRECT_IO;
retry:
memset(sense, 0, sense_len);
diff --git a/libmultipath/checkers/readsector0.c b/libmultipath/checkers/readsector0.c
index 0550fb6..1c2a868 100644
--- a/libmultipath/checkers/readsector0.c
+++ b/libmultipath/checkers/readsector0.c
@@ -29,7 +29,7 @@ int libcheck_check (struct checker * c)
unsigned char sbuf[SENSE_BUFF_LEN];
int ret;
- ret = sg_read(c->fd, &buf[0], 4069, &sbuf[0],
+ ret = sg_read(c->fd, &buf[0], 4096, &sbuf[0],
SENSE_BUFF_LEN, c->timeout);
switch (ret)
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
index bd7372d..2edc8ad 100644
--- a/libmultipath/checkers/tur.c
+++ b/libmultipath/checkers/tur.c
@@ -331,9 +331,11 @@ libcheck_check (struct checker * c)
setup_thread_attr(&attr, 32 * 1024, 1);
r = pthread_create(&ct->thread, &attr, tur_thread, ct);
if (r) {
+ pthread_spin_lock(&ct->hldr_lock);
+ ct->holders--;
+ pthread_spin_unlock(&ct->hldr_lock);
pthread_mutex_unlock(&ct->lock);
ct->thread = 0;
- 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);
diff --git a/libmultipath/config.c b/libmultipath/config.c
index 8b9e770..a48b8af 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
@@ -125,7 +125,7 @@ find_hwe (vector hwtable, char * vendor, char * product, char * revision)
}
extern struct mpentry *
-find_mpe (char * wwid)
+find_mpe (vector mptable, char * wwid)
{
int i;
struct mpentry * mpe;
@@ -133,7 +133,7 @@ find_mpe (char * wwid)
if (!wwid)
return NULL;
- vector_foreach_slot (conf->mptable, mpe, i)
+ vector_foreach_slot (mptable, mpe, i)
if (mpe->wwid && !strcmp(mpe->wwid, wwid))
return mpe;
@@ -141,7 +141,7 @@ find_mpe (char * wwid)
}
extern char *
-get_mpe_wwid (char * alias)
+get_mpe_wwid (vector mptable, char * alias)
{
int i;
struct mpentry * mpe;
@@ -149,7 +149,7 @@ get_mpe_wwid (char * alias)
if (!alias)
return NULL;
- vector_foreach_slot (conf->mptable, mpe, i)
+ vector_foreach_slot (mptable, mpe, i)
if (mpe->alias && strcmp(mpe->alias, alias) == 0)
return mpe->wwid;
@@ -419,7 +419,6 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
hwe->user_friendly_names = dhwe->user_friendly_names;
hwe->retain_hwhandler = dhwe->retain_hwhandler;
hwe->detect_prio = dhwe->detect_prio;
- conf->deferred_remove = DEFAULT_DEFERRED_REMOVE;
if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
goto out;
@@ -479,9 +478,6 @@ free_config (struct config * conf)
if (!conf)
return;
- if (conf->dev)
- FREE(conf->dev);
-
if (conf->multipath_dir)
FREE(conf->multipath_dir);
@@ -546,7 +542,7 @@ free_config (struct config * 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)
+process_config_dir(struct config *conf, vector keywords, char *dir)
{
struct dirent **namelist;
int i, n;
@@ -573,21 +569,20 @@ process_config_dir(vector keywords, char *dir)
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);
+ process_file(conf, path);
if (VECTOR_SIZE(conf->hwtable) > old_hwtable_size)
factorize_hwtable(conf->hwtable, old_hwtable_size);
}
}
-int
-load_config (char * file, struct udev *udev)
+struct config *
+load_config (char * file)
{
- if (!conf)
- conf = alloc_config();
+ struct config *conf = alloc_config();
- if (!conf || !udev)
- return 1;
+ if (!conf)
+ return NULL;
/*
* internal defaults
@@ -595,8 +590,6 @@ load_config (char * file, struct udev *udev)
if (!conf->verbosity)
conf->verbosity = DEFAULT_VERBOSITY;
- conf->udev = udev;
- conf->dev_type = DEV_NONE;
conf->minio = DEFAULT_MINIO;
conf->minio_rq = DEFAULT_MINIO_RQ;
get_sys_max_fds(&conf->max_fds);
@@ -622,6 +615,7 @@ load_config (char * file, struct udev *udev)
conf->retrigger_tries = DEFAULT_RETRIGGER_TRIES;
conf->retrigger_delay = DEFAULT_RETRIGGER_DELAY;
conf->uev_wait_timeout = DEFAULT_UEV_WAIT_TIMEOUT;
+ conf->deferred_remove = DEFAULT_DEFERRED_REMOVE;
/*
* preload default hwtable
@@ -638,14 +632,13 @@ load_config (char * file, struct udev *udev)
/*
* read the config file
*/
- set_current_keywords(&conf->keywords);
- alloc_keywords();
- init_keywords();
+ conf->keywords = vector_alloc();
+ init_keywords(conf->keywords);
if (filepresent(file)) {
int builtin_hwtable_size;
builtin_hwtable_size = VECTOR_SIZE(conf->hwtable);
- if (process_file(file)) {
+ if (process_file(conf, file)) {
condlog(0, "error parsing config file");
goto out;
}
@@ -663,7 +656,7 @@ load_config (char * file, struct udev *udev)
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);
+ process_config_dir(conf, conf->keywords, conf->config_dir);
/*
* fill the voids left in the config file
@@ -736,9 +729,8 @@ load_config (char * file, struct udev *udev)
!conf->wwids_file)
goto out;
- return 0;
+ return conf;
out:
free_config(conf);
- return 1;
+ return NULL;
}
-
diff --git a/libmultipath/config.h b/libmultipath/config.h
index 466e31e..a41207a 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
@@ -3,6 +3,7 @@
#include <sys/types.h>
#include <stdint.h>
+#include <urcu.h>
#define ORIGIN_DEFAULT 0
#define ORIGIN_CONFIG 1
@@ -24,6 +25,7 @@ enum devtypes {
};
enum mpath_cmds {
+ CMD_NONE,
CMD_CREATE,
CMD_DRY_RUN,
CMD_LIST_SHORT,
@@ -95,11 +97,10 @@ struct mpentry {
};
struct config {
+ struct rcu_head rcu;
int verbosity;
- enum mpath_cmds cmd;
int pgpolicy_flag;
int pgpolicy;
- enum devtypes dev_type;
int minio;
int minio_rq;
int checkint;
@@ -115,7 +116,6 @@ struct config {
int queue_without_daemon;
int ignore_wwids;
int checker_timeout;
- int daemon;
int flush_on_last_del;
int attribute_flags;
int fast_io_fail;
@@ -143,8 +143,6 @@ struct config {
int uev_wait_timeout;
unsigned int version[3];
- char * dev;
- struct udev * udev;
char * multipath_dir;
char * selector;
char * uid_attribute;
@@ -176,11 +174,11 @@ struct config {
vector elist_property;
};
-struct config * conf;
+extern struct udev * udev;
struct hwentry * find_hwe (vector hwtable, char * vendor, char * product, char *revision);
-struct mpentry * find_mpe (char * wwid);
-char * get_mpe_wwid (char * alias);
+struct mpentry * find_mpe (vector mptable, char * wwid);
+char * get_mpe_wwid (vector mptable, char * alias);
struct hwentry * alloc_hwe (void);
struct mpentry * alloc_mpe (void);
@@ -192,8 +190,10 @@ void free_mptable (vector mptable);
int store_hwe (vector hwtable, struct hwentry *);
-int load_config (char * file, struct udev * udev);
+struct config *load_config (char * file);
struct config * alloc_config (void);
void free_config (struct config * conf);
+extern struct config *get_multipath_config(void);
+extern void put_multipath_config(struct config *);
#endif
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
index a4a2c44..707e6be 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
@@ -14,7 +14,7 @@
#include <errno.h>
#include <libdevmapper.h>
#include <libudev.h>
-#include <mpath_cmd.h>
+#include "mpath_cmd.h"
#include "checkers.h"
#include "vector.h"
@@ -65,7 +65,7 @@ int group_by_host_adapter(struct pathgroup *pgp, vector adapters)
goto out;
agp->pgp = pgp;
- strncpy(agp->adapter_name, adapter_name1, SLOT_NAME_SIZE);
+ strncpy(agp->adapter_name, adapter_name1, SLOT_NAME_SIZE - 1);
store_adaptergroup(adapters, agp);
/* create a new host port group
@@ -257,6 +257,7 @@ extern int
setup_map (struct multipath * mpp, char * params, int params_size)
{
struct pathgroup * pgp;
+ struct config *conf;
int i;
/*
@@ -275,26 +276,28 @@ setup_map (struct multipath * mpp, char * params, int params_size)
/*
* properties selectors
*/
- select_pgfailback(mpp);
- select_pgpolicy(mpp);
- select_selector(mpp);
- select_features(mpp);
- select_hwhandler(mpp);
- select_rr_weight(mpp);
- select_minio(mpp);
- select_no_path_retry(mpp);
- select_mode(mpp);
- select_uid(mpp);
- select_gid(mpp);
- select_fast_io_fail(mpp);
- select_dev_loss(mpp);
- 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);
+ conf = get_multipath_config();
+ select_pgfailback(conf, mpp);
+ select_pgpolicy(conf, mpp);
+ select_selector(conf, mpp);
+ select_features(conf, mpp);
+ select_hwhandler(conf, mpp);
+ select_rr_weight(conf, mpp);
+ select_minio(conf, mpp);
+ select_no_path_retry(conf, mpp);
+ select_mode(conf, mpp);
+ select_uid(conf, mpp);
+ select_gid(conf, mpp);
+ select_fast_io_fail(conf, mpp);
+ select_dev_loss(conf, mpp);
+ select_reservation_key(conf, mpp);
+ select_retain_hwhandler(conf, mpp);
+ select_deferred_remove(conf, mpp);
+ select_delay_watch_checks(conf, mpp);
+ select_delay_wait_checks(conf, mpp);
+
+ sysfs_set_scsi_tmo(mpp, conf->checkint);
+ put_multipath_config(conf);
/*
* assign paths to path groups -- start with no groups and all paths
* in mpp->paths
@@ -395,7 +398,7 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
if (cmpp) {
condlog(2, "%s: rename %s to %s", mpp->wwid,
cmpp->alias, mpp->alias);
- strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE);
+ strncpy(mpp->alias_old, cmpp->alias, WWID_SIZE - 1);
mpp->action = ACT_RENAME;
if (force_reload)
mpp->action = ACT_FORCERENAME;
@@ -410,7 +413,7 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
if (!cmpp) {
condlog(2, "%s: remove (wwid changed)", mpp->alias);
dm_flush_map(mpp->alias);
- strncpy(cmpp_by_name->wwid, mpp->wwid, WWID_SIZE);
+ strncpy(cmpp_by_name->wwid, mpp->wwid, WWID_SIZE - 1);
drop_multipath(curmp, cmpp_by_name->wwid, KEEP_PATHS);
mpp->action = ACT_CREATE;
condlog(3, "%s: set ACT_CREATE (map wwid change)",
@@ -456,7 +459,7 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
return;
}
if (mpp->retain_hwhandler != RETAIN_HWHANDLER_ON &&
- (strlen(cmpp->hwhandler) != strlen(mpp->hwhandler) ||
+ (strlen(cmpp->hwhandler) != strlen(mpp->hwhandler) ||
strncmp(cmpp->hwhandler, mpp->hwhandler,
strlen(mpp->hwhandler)))) {
mpp->action = ACT_RELOAD;
@@ -579,15 +582,18 @@ fail:
#define DOMAP_DRY 3
extern int
-domap (struct multipath * mpp, char * params)
+domap (struct multipath * mpp, char * params, int is_daemon)
{
int r = DOMAP_FAIL;
+ struct config *conf;
/*
* last chance to quit before touching the devmaps
*/
- if (conf->cmd == CMD_DRY_RUN && mpp->action != ACT_NOTHING) {
+ if (mpp->action == ACT_DRY_RUN) {
+ conf = get_multipath_config();
print_multipath_topology(mpp, conf->verbosity);
+ put_multipath_config(conf);
return DOMAP_DRY;
}
@@ -633,11 +639,17 @@ domap (struct multipath * mpp, char * params)
break;
case ACT_RENAME:
- r = dm_rename(mpp->alias_old, mpp->alias);
+ conf = get_multipath_config();
+ r = dm_rename(mpp->alias_old, mpp->alias,
+ conf->partition_delim);
+ put_multipath_config(conf);
break;
case ACT_FORCERENAME:
- r = dm_rename(mpp->alias_old, mpp->alias);
+ conf = get_multipath_config();
+ r = dm_rename(mpp->alias_old, mpp->alias,
+ conf->partition_delim);
+ put_multipath_config(conf);
if (r)
r = dm_addmap_reload(mpp, params, 0);
break;
@@ -653,7 +665,7 @@ domap (struct multipath * mpp, char * params)
*/
if (mpp->action == ACT_CREATE)
remember_wwid(mpp->wwid);
- if (!conf->daemon) {
+ if (!is_daemon) {
/* multipath client mode */
dm_switchgroup(mpp->alias, mpp->bestpg);
} else {
@@ -669,8 +681,10 @@ domap (struct multipath * mpp, char * params)
if (mpp->action != ACT_CREATE)
mpp->action = ACT_NOTHING;
else {
+ conf = get_multipath_config();
mpp->wait_for_udev = 1;
mpp->uev_wait_tick = conf->uev_wait_timeout;
+ put_multipath_config(conf);
}
}
dm_setgeometry(mpp);
@@ -706,6 +720,8 @@ int check_daemon(void)
int fd;
char *reply;
int ret = 0;
+ unsigned int timeout;
+ struct config *conf;
fd = mpath_connect();
if (fd == -1)
@@ -713,7 +729,10 @@ int check_daemon(void)
if (send_packet(fd, "show daemon") != 0)
goto out;
- if (recv_packet(fd, &reply, conf->uxsock_timeout) != 0)
+ conf = get_multipath_config();
+ timeout = conf->uxsock_timeout;
+ put_multipath_config(conf);
+ if (recv_packet(fd, &reply, timeout) != 0)
goto out;
if (strstr(reply, "shutdown"))
@@ -729,16 +748,19 @@ out:
}
extern int
-coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_reload)
+coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_reload, enum mpath_cmds cmd)
{
int r = 1;
int k, i;
+ int is_daemon = (cmd == CMD_NONE) ? 1 : 0;
char params[PARAMS_SIZE];
struct multipath * mpp;
struct path * pp1;
struct path * pp2;
vector curmp = vecs->mpvec;
vector pathvec = vecs->pathvec;
+ struct config *conf;
+ int allow_queueing;
/* ignore refwwid if it's empty */
if (refwwid && !strlen(refwwid))
@@ -753,11 +775,14 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
/* skip this path for some reason */
/* 1. if path has no unique id or wwid blacklisted */
+ conf = get_multipath_config();
if (strlen(pp1->wwid) == 0 ||
filter_path(conf, pp1) > 0) {
+ put_multipath_config(conf);
orphan_path(pp1, "wwid blacklisted");
continue;
}
+ put_multipath_config(conf);
/* 2. if path already coalesced */
if (pp1->mpp)
@@ -770,7 +795,7 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
}
/* 4. path is out of scope */
- if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE))
+ if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE - 1))
continue;
/* If find_multipaths was selected check if the path is valid */
@@ -825,10 +850,12 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
continue;
}
+ if (cmd == CMD_DRY_RUN)
+ mpp->action = ACT_DRY_RUN;
if (mpp->action == ACT_UNDEF)
select_action(mpp, curmp, force_reload);
- r = domap(mpp, params);
+ r = domap(mpp, params, is_daemon);
if (r == DOMAP_FAIL || r == DOMAP_RETRY) {
condlog(3, "%s: domap (%u) failure "
@@ -846,7 +873,10 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
if (r == DOMAP_DRY)
continue;
- if (!conf->daemon && !conf->allow_queueing && !check_daemon()) {
+ conf = get_multipath_config();
+ allow_queueing = conf->allow_queueing;
+ put_multipath_config(conf);
+ if (!is_daemon && !allow_queueing && !check_daemon()) {
if (mpp->no_path_retry != NO_PATH_RETRY_UNDEF &&
mpp->no_path_retry != NO_PATH_RETRY_FAIL)
condlog(3, "%s: multipathd not running, unset "
@@ -871,8 +901,11 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
}
}
- if (!conf->daemon && mpp->action != ACT_NOTHING)
+ if (!is_daemon && mpp->action != ACT_NOTHING) {
+ conf = get_multipath_config();
print_multipath_topology(mpp, conf->verbosity);
+ put_multipath_config(conf);
+ }
if (newmp) {
if (mpp->action != ACT_REJECT) {
@@ -891,16 +924,14 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
if (newmp) {
vector_foreach_slot (newmp, mpp, i) {
char alias[WWID_SIZE];
- int j;
if (!deadmap(mpp))
continue;
- strncpy(alias, mpp->alias, WWID_SIZE);
-
- if ((j = find_slot(newmp, (void *)mpp)) != -1)
- vector_del_slot(newmp, j);
+ strncpy(alias, mpp->alias, WWID_SIZE - 1);
+ vector_del_slot(newmp, i);
+ i--;
remove_map(mpp, vecs, 0);
if (dm_flush_map(alias))
@@ -920,12 +951,15 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
* 2 - blacklist
*/
extern int
-get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
+get_refwwid (enum mpath_cmds cmd, char * dev, enum devtypes dev_type,
+ vector pathvec, char **wwid)
{
int ret = 1;
struct path * pp;
char buff[FILE_NAME_SIZE];
char * refwwid = NULL, tmpwwid[WWID_SIZE];
+ int flags = DI_SYSFS | DI_WWID;
+ struct config *conf;
if (!wwid)
return 1;
@@ -934,6 +968,9 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
if (dev_type == DEV_NONE)
return 1;
+ if (cmd != CMD_REMOVE_WWID)
+ flags |= DI_BLACKLIST;
+
if (dev_type == DEV_DEVNODE) {
if (basenamecpy(dev, buff, FILE_NAME_SIZE) == 0) {
condlog(1, "basename failed for '%s' (%s)",
@@ -943,14 +980,16 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
pp = find_path_by_dev(pathvec, buff);
if (!pp) {
- struct udev_device *udevice = udev_device_new_from_subsystem_sysname(conf->udev, "block", buff);
+ struct udev_device *udevice = udev_device_new_from_subsystem_sysname(udev, "block", buff);
if (!udevice) {
condlog(2, "%s: can't get udev device", buff);
return 1;
}
- ret = store_pathinfo(pathvec, conf->hwtable, udevice,
- DI_SYSFS | DI_WWID, &pp);
+ conf = get_multipath_config();
+ ret = store_pathinfo(pathvec, conf, udevice,
+ flags, &pp);
+ put_multipath_config(conf);
udev_device_unref(udevice);
if (!pp) {
if (ret == 1)
@@ -959,9 +998,13 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
return ret;
}
}
+ conf = get_multipath_config();
if (pp->udev && pp->uid_attribute &&
- filter_property(conf, pp->udev) > 0)
+ filter_property(conf, pp->udev) > 0) {
+ put_multipath_config(conf);
return 2;
+ }
+ put_multipath_config(conf);
refwwid = pp->wwid;
goto out;
@@ -975,14 +1018,16 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
}
pp = find_path_by_dev(pathvec, buff);
if (!pp) {
- struct udev_device *udevice = udev_device_new_from_devnum(conf->udev, 'b', parse_devt(dev));
+ struct udev_device *udevice = udev_device_new_from_devnum(udev, 'b', parse_devt(dev));
if (!udevice) {
condlog(2, "%s: can't get udev device", dev);
return 1;
}
- ret = store_pathinfo(pathvec, conf->hwtable, udevice,
- DI_SYSFS | DI_WWID, &pp);
+ conf = get_multipath_config();
+ ret = store_pathinfo(pathvec, conf, udevice,
+ flags, &pp);
+ put_multipath_config(conf);
udev_device_unref(udevice);
if (!pp) {
if (ret == 1)
@@ -991,40 +1036,48 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
return ret;
}
}
+ conf = get_multipath_config();
if (pp->udev && pp->uid_attribute &&
- filter_property(conf, pp->udev) > 0)
+ filter_property(conf, pp->udev) > 0) {
+ put_multipath_config(conf);
return 2;
-
+ }
+ put_multipath_config(conf);
refwwid = pp->wwid;
goto out;
}
if (dev_type == DEV_UEVENT) {
- struct udev_device *udevice = udev_device_new_from_environment(conf->udev);
+ struct udev_device *udevice = udev_device_new_from_environment(udev);
if (!udevice) {
condlog(2, "%s: can't get udev device", dev);
return 1;
}
- ret = store_pathinfo(pathvec, conf->hwtable, udevice,
- DI_SYSFS | DI_WWID, &pp);
+ conf = get_multipath_config();
+ ret = store_pathinfo(pathvec, conf, udevice,
+ flags, &pp);
udev_device_unref(udevice);
if (!pp) {
if (ret == 1)
condlog(0, "%s: can't store path info",
dev);
+ put_multipath_config(conf);
return ret;
}
if (pp->udev && pp->uid_attribute &&
- filter_property(conf, pp->udev) > 0)
+ filter_property(conf, pp->udev) > 0) {
+ put_multipath_config(conf);
return 2;
-
+ }
+ put_multipath_config(conf);
refwwid = pp->wwid;
goto out;
}
if (dev_type == DEV_DEVMAP) {
+ conf = get_multipath_config();
if (((dm_get_uuid(dev, tmpwwid)) == 0) && (strlen(tmpwwid))) {
refwwid = tmpwwid;
goto check;
@@ -1036,13 +1089,14 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
if (get_user_friendly_wwid(dev, tmpwwid,
conf->bindings_file) == 0) {
refwwid = tmpwwid;
+ put_multipath_config(conf);
goto check;
}
/*
* or may be an alias
*/
- refwwid = get_mpe_wwid(dev);
+ refwwid = get_mpe_wwid(conf->mptable, dev);
/*
* or directly a wwid
@@ -1053,9 +1107,12 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid)
check:
if (refwwid && strlen(refwwid)) {
if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
- refwwid, NULL) > 0)
- return 2;
+ refwwid, NULL) > 0) {
+ put_multipath_config(conf);
+ return 2;
+ }
}
+ put_multipath_config(conf);
}
out:
if (refwwid && strlen(refwwid)) {
@@ -1066,7 +1123,7 @@ out:
return 1;
}
-extern int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh)
+extern int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh, int is_daemon)
{
char params[PARAMS_SIZE] = {0};
struct path *pp;
@@ -1075,7 +1132,9 @@ extern int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh)
update_mpp_paths(mpp, vecs->pathvec);
if (refresh) {
vector_foreach_slot (mpp->paths, pp, i) {
- r = pathinfo(pp, conf->hwtable, DI_PRIO);
+ struct config *conf = get_multipath_config();
+ r = pathinfo(pp, conf, DI_PRIO);
+ put_multipath_config(conf);
if (r) {
condlog(2, "%s: failed to refresh pathinfo",
mpp->alias);
@@ -1089,7 +1148,7 @@ extern int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh)
}
select_action(mpp, vecs->mpvec, 1);
- r = domap(mpp, params);
+ r = domap(mpp, params, is_daemon);
if (r == DOMAP_FAIL || r == DOMAP_RETRY) {
condlog(3, "%s: domap (%u) failure "
"for reload map", mpp->alias, r);
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
index f357d9a..442c956 100644
--- a/libmultipath/configure.h
+++ b/libmultipath/configure.h
@@ -19,15 +19,17 @@ enum actions {
ACT_CREATE,
ACT_RESIZE,
ACT_FORCERENAME,
+ ACT_DRY_RUN,
};
#define FLUSH_ONE 1
#define FLUSH_ALL 2
int setup_map (struct multipath * mpp, char * params, int params_size );
-int domap (struct multipath * mpp, char * params);
+int domap (struct multipath * mpp, char * params, int is_daemon);
int reinstate_paths (struct multipath *mpp);
-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 coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload, enum mpath_cmds cmd);
+int get_refwwid (enum mpath_cmds cmd, char * dev, enum devtypes dev_type,
+ vector pathvec, char **wwid);
+int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh, int is_daemon);
int sysfs_get_host_adapter_name(struct path *pp, char *adapter_name);
diff --git a/libmultipath/debug.c b/libmultipath/debug.c
index bad78a8..b2e344d 100644
--- a/libmultipath/debug.c
+++ b/libmultipath/debug.c
@@ -16,9 +16,12 @@ void dlog (int sink, int prio, const char * fmt, ...)
{
va_list ap;
int thres;
+ struct config *conf;
va_start(ap, fmt);
+ conf = get_multipath_config();
thres = (conf) ? conf->verbosity : 0;
+ put_multipath_config(conf);
if (prio <= thres) {
if (sink < 1) {
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
index 96f5a2c..9de5914 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -7,22 +7,22 @@
#define DEFAULT_HWHANDLER "0"
#define DEFAULT_MINIO 1000
#define DEFAULT_MINIO_RQ 1
-#define DEFAULT_PGPOLICY FAILOVER
-#define DEFAULT_FAILBACK -FAILBACK_MANUAL
-#define DEFAULT_RR_WEIGHT RR_WEIGHT_NONE
-#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
+#define DEFAULT_PGPOLICY GROUP_BY_PRIO
+#define DEFAULT_FAILBACK -FAILBACK_IMMEDIATE
+#define DEFAULT_RR_WEIGHT RR_WEIGHT_NONE
+#define DEFAULT_NO_PATH_RETRY NO_PATH_RETRY_UNDEF
#define DEFAULT_VERBOSITY 2
#define DEFAULT_REASSIGN_MAPS 0
#define DEFAULT_FIND_MULTIPATHS 0
#define DEFAULT_FAST_IO_FAIL 5
-#define DEFAULT_DEV_LOSS_TMO 600
-#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_DEV_LOSS_TMO 600
+#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_ON
+#define DEFAULT_DETECT_PRIO DETECT_PRIO_ON
+#define DEFAULT_DEFERRED_REMOVE DEFERRED_REMOVE_OFF
+#define DEFAULT_DELAY_CHECKS DELAY_CHECKS_OFF
#define DEFAULT_UEVENT_STACKSIZE 256
-#define DEFAULT_RETRIGGER_DELAY 10
-#define DEFAULT_RETRIGGER_TRIES 3
+#define DEFAULT_RETRIGGER_DELAY 10
+#define DEFAULT_RETRIGGER_TRIES 3
#define DEFAULT_UEV_WAIT_TIMEOUT 30
#define DEFAULT_CHECKINT 5
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
index 6d1a5d6..2c76d8b 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -19,7 +19,6 @@
#include "debug.h"
#include "memory.h"
#include "devmapper.h"
-#include "config.h"
#include "sysfs.h"
#include "log_pthread.h"
@@ -32,6 +31,8 @@
#define UUID_PREFIX "mpath-"
#define UUID_PREFIX_LEN 6
+static int dm_conf_verbosity;
+
#ifdef LIBDM_API_DEFERRED
static int dm_cancel_remove_partmaps(const char * mapname);
#endif
@@ -65,7 +66,7 @@ dm_write_log (int level, const char *file, int line, const char *f, ...)
if (level > 6)
level = 6;
- thres = (conf) ? conf->verbosity : 0;
+ thres = dm_conf_verbosity;
if (thres <= 3 || level > thres)
return;
@@ -94,9 +95,9 @@ dm_write_log (int level, const char *file, int line, const char *f, ...)
}
extern void
-dm_init(void) {
+dm_init(int v) {
dm_log_init(&dm_write_log);
- dm_log_init_verbose(conf ? conf->verbosity + 3 : 0);
+ dm_log_init_verbose(v + 3);
}
static int
@@ -116,7 +117,10 @@ dm_lib_prereq (void)
dm_get_library_version(version, sizeof(version));
condlog(3, "libdevmapper version %s", version);
- sscanf(version, "%d.%d.%d ", &v[0], &v[1], &v[2]);
+ if (sscanf(version, "%d.%d.%d ", &v[0], &v[1], &v[2]) != 3) {
+ condlog(0, "invalid libdevmapper version %s", version);
+ return 1;
+ }
if VERSION_GE(v, minv)
return 0;
@@ -163,9 +167,9 @@ dm_drv_version (unsigned int * version, char * str)
goto out;
}
v = target->version;
- version[0] = v[0];
- version[1] = v[1];
- version[2] = v[2];
+ version[0] = v[0];
+ version[1] = v[1];
+ version[2] = v[2];
r = 0;
out:
dm_task_destroy(dmt);
@@ -177,7 +181,7 @@ dm_drv_prereq (void)
{
unsigned int minv[3] = {1, 0, 3};
unsigned int version[3] = {0, 0, 0};
- unsigned int * v = version;
+ unsigned int * v = version;
if (dm_drv_version(v, TGT_MPATH)) {
/* in doubt return not capable */
@@ -237,12 +241,8 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync, uint16_t
r = dm_task_run (dmt);
- if (udev_wait_flag) {
- if (!r)
- dm_udev_complete(cookie);
- else
+ if (udev_wait_flag)
dm_udev_wait(cookie);
- }
out:
dm_task_destroy (dmt);
return r;
@@ -325,12 +325,8 @@ dm_addmap (int task, const char *target, struct multipath *mpp,
r = dm_task_run (dmt);
- if (task == DM_DEVICE_CREATE) {
- if (!r)
- dm_udev_complete(cookie);
- else
+ if (task == DM_DEVICE_CREATE)
dm_udev_wait(cookie);
- }
freeout:
if (prefixed_uuid)
FREE(prefixed_uuid);
@@ -429,7 +425,6 @@ dm_get_map(const char * name, unsigned long long * size, char * outparams)
{
int r = 1;
struct dm_task *dmt;
- void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params = NULL;
@@ -446,8 +441,8 @@ dm_get_map(const char * name, unsigned long long * size, char * outparams)
goto out;
/* Fetch 1st target */
- next = dm_get_next_target(dmt, next, &start, &length,
- &target_type, &params);
+ dm_get_next_target(dmt, NULL, &start, &length,
+ &target_type, &params);
if (size)
*size = length;
@@ -538,7 +533,6 @@ dm_get_status(char * name, char * outstatus)
{
int r = 1;
struct dm_task *dmt;
- void *next = NULL;
uint64_t start, length;
char *target_type;
char *status;
@@ -555,8 +549,8 @@ dm_get_status(char * name, char * outstatus)
goto out;
/* Fetch 1st target */
- next = dm_get_next_target(dmt, next, &start, &length,
- &target_type, &status);
+ dm_get_next_target(dmt, NULL, &start, &length,
+ &target_type, &status);
if (snprintf(outstatus, PARAMS_SIZE, "%s", status) <= PARAMS_SIZE)
r = 0;
@@ -579,7 +573,6 @@ dm_type(const char * name, char * type)
{
int r = 0;
struct dm_task *dmt;
- void *next = NULL;
uint64_t start, length;
char *target_type = NULL;
char *params;
@@ -596,8 +589,8 @@ dm_type(const char * name, char * type)
goto out;
/* Fetch 1st target */
- next = dm_get_next_target(dmt, next, &start, &length,
- &target_type, &params);
+ dm_get_next_target(dmt, NULL, &start, &length,
+ &target_type, &params);
if (!target_type)
r = -1;
@@ -1383,21 +1376,21 @@ rename_partmap (const char *name, void *data)
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);
+ dm_rename(name, buff, rd->delim);
condlog(4, "partition map %s renamed", name);
return 0;
}
int
-dm_rename_partmaps (const char * old, char * new)
+dm_rename_partmaps (const char * old, char * new, char *delim)
{
struct rename_data rd;
rd.old = old;
rd.new = new;
- if (conf->partition_delim)
- rd.delim = conf->partition_delim;
+ if (delim)
+ rd.delim = delim;
if (isdigit(new[strlen(new)-1]))
rd.delim = "p";
else
@@ -1406,13 +1399,13 @@ dm_rename_partmaps (const char * old, char * new)
}
int
-dm_rename (const char * old, char * new)
+dm_rename (const char * old, char * new, char *delim)
{
int r = 0;
struct dm_task *dmt;
uint32_t cookie;
- if (dm_rename_partmaps(old, new))
+ if (dm_rename_partmaps(old, new, delim))
return r;
if (!(dmt = dm_task_create(DM_DEVICE_RENAME)))
@@ -1431,10 +1424,7 @@ dm_rename (const char * old, char * new)
goto out;
r = dm_task_run(dmt);
- if (!r)
- dm_udev_complete(cookie);
- else
- dm_udev_wait(cookie);
+ dm_udev_wait(cookie);
out:
dm_task_destroy(dmt);
@@ -1445,24 +1435,27 @@ out:
void dm_reassign_deps(char *table, char *dep, char *newdep)
{
char *p, *n;
- char newtable[PARAMS_SIZE];
+ char *newtable;
- strcpy(newtable, table);
+ newtable = strdup(table);
+ if (!newtable)
+ return;
p = strstr(newtable, dep);
n = table + (p - newtable);
strcpy(n, newdep);
n += strlen(newdep);
p += strlen(dep);
strcat(n, p);
+ free(newtable);
}
int dm_reassign_table(const char *name, char *old, char *new)
{
- int r, modified = 0;
+ int r = 0, modified = 0;
uint64_t start, length;
struct dm_task *dmt, *reload_dmt;
char *target, *params = NULL;
- char buff[PARAMS_SIZE];
+ char *buff;
void *next = NULL;
if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
@@ -1483,8 +1476,12 @@ int dm_reassign_table(const char *name, char *old, char *new)
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target, &params);
- memset(buff, 0, PARAMS_SIZE);
- strcpy(buff, params);
+ buff = strdup(params);
+ if (!buff) {
+ condlog(3, "%s: failed to replace target %s, "
+ "out of memory", name, target);
+ goto out_reload;
+ }
if (strcmp(target, TGT_MPATH) && strstr(params, old)) {
condlog(3, "%s: replace target %s %s",
name, target, buff);
@@ -1494,6 +1491,7 @@ int dm_reassign_table(const char *name, char *old, char *new)
modified++;
}
dm_task_add_target(reload_dmt, start, length, target, buff);
+ free(buff);
} while (next);
if (modified) {
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
index b5df369..4bc3b11 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -12,7 +12,7 @@
#define MPATH_UDEV_RELOAD_FLAG 0
#endif
-void dm_init(void);
+void dm_init(int verbosity);
int dm_prereq (void);
int dm_drv_version (unsigned int * version, char * str);
int dm_simplecmd_flush (int, const char *, uint16_t);
@@ -46,7 +46,7 @@ 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 (const char * old, char * new);
+int dm_rename (const char * old, char * new, char * delim);
int dm_reassign(const char * mapname);
int dm_reassign_table(const char *name, char *old, char *new);
int dm_setgeometry(struct multipath *mpp);
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
index 7f912ec..1933b6d 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -19,9 +19,9 @@
#include "blacklist.h"
#include "defaults.h"
#include "prio.h"
-#include "errno.h"
+#include <errno.h>
#include <inttypes.h>
-#include <mpath_cmd.h>
+#include "mpath_cmd.h"
static int
set_int(vector strvec, void *ptr)
@@ -135,21 +135,21 @@ print_yes_no_undef (char *buff, int len, void *ptr)
#define declare_def_handler(option, function) \
static int \
-def_ ## option ## _handler (vector strvec) \
+def_ ## option ## _handler (struct config *conf, vector strvec) \
{ \
return function (strvec, &conf->option); \
}
#define declare_def_snprint(option, function) \
static int \
-snprint_def_ ## option (char * buff, int len, void * data) \
+snprint_def_ ## option (struct config *conf, char * buff, int len, void * data) \
{ \
return function (buff, len, &conf->option); \
}
#define declare_def_snprint_defint(option, function, value) \
static int \
-snprint_def_ ## option (char * buff, int len, void * data) \
+snprint_def_ ## option (struct config *conf, char * buff, int len, void * data) \
{ \
int i = value; \
if (!conf->option) \
@@ -159,7 +159,7 @@ snprint_def_ ## option (char * buff, int len, void * data) \
#define declare_def_snprint_defstr(option, function, value) \
static int \
-snprint_def_ ## option (char * buff, int len, void * data) \
+snprint_def_ ## option (struct config *conf, char * buff, int len, void * data) \
{ \
char *s = value; \
if (!conf->option) \
@@ -169,7 +169,7 @@ snprint_def_ ## option (char * buff, int len, void * data) \
#define declare_hw_handler(option, function) \
static int \
-hw_ ## option ## _handler (vector strvec) \
+hw_ ## option ## _handler (struct config *conf, vector strvec) \
{ \
struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable); \
if (!hwe) \
@@ -179,7 +179,7 @@ hw_ ## option ## _handler (vector strvec) \
#define declare_hw_snprint(option, function) \
static int \
-snprint_hw_ ## option (char * buff, int len, void * data) \
+snprint_hw_ ## option (struct config *conf, char * buff, int len, void * data) \
{ \
struct hwentry * hwe = (struct hwentry *)data; \
return function (buff, len, &hwe->option); \
@@ -187,7 +187,7 @@ snprint_hw_ ## option (char * buff, int len, void * data) \
#define declare_ovr_handler(option, function) \
static int \
-ovr_ ## option ## _handler (vector strvec) \
+ovr_ ## option ## _handler (struct config *conf, vector strvec) \
{ \
if (!conf->overrides) \
return 1; \
@@ -196,14 +196,14 @@ ovr_ ## option ## _handler (vector strvec) \
#define declare_ovr_snprint(option, function) \
static int \
-snprint_ovr_ ## option (char * buff, int len, void * data) \
+snprint_ovr_ ## option (struct config *conf, char * buff, int len, void * data) \
{ \
return function (buff, len, &conf->overrides->option); \
}
#define declare_mp_handler(option, function) \
static int \
-mp_ ## option ## _handler (vector strvec) \
+mp_ ## option ## _handler (struct config *conf, vector strvec) \
{ \
struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \
if (!mpe) \
@@ -213,7 +213,7 @@ mp_ ## option ## _handler (vector strvec) \
#define declare_mp_snprint(option, function) \
static int \
-snprint_mp_ ## option (char * buff, int len, void * data) \
+snprint_mp_ ## option (struct config *conf, char * buff, int len, void * data) \
{ \
struct mpentry * mpe = (struct mpentry *)data; \
return function (buff, len, &mpe->option); \
@@ -324,7 +324,8 @@ declare_mp_snprint(minio_rq, print_nonzero)
declare_def_handler(queue_without_daemon, set_yes_no)
static int
-snprint_def_queue_without_daemon (char * buff, int len, void * data)
+snprint_def_queue_without_daemon (struct config *conf,
+ char * buff, int len, void * data)
{
switch (conf->queue_without_daemon) {
case QUE_NO_DAEMON_OFF:
@@ -403,7 +404,7 @@ declare_def_handler(strict_timing, set_yes_no)
declare_def_snprint(strict_timing, print_yes_no)
static int
-def_config_dir_handler(vector strvec)
+def_config_dir_handler(struct config *conf, vector strvec)
{
/* this is only valid in the main config file */
if (conf->processed_main_config)
@@ -414,14 +415,14 @@ declare_def_snprint(config_dir, print_str)
#define declare_def_attr_handler(option, function) \
static int \
-def_ ## option ## _handler (vector strvec) \
+def_ ## option ## _handler (struct config *conf, vector strvec) \
{ \
return function (strvec, &conf->option, &conf->attribute_flags);\
}
#define declare_def_attr_snprint(option, function) \
static int \
-snprint_def_ ## option (char * buff, int len, void * data) \
+snprint_def_ ## option (struct config *conf, char * buff, int len, void * data) \
{ \
return function (buff, len, &conf->option, \
&conf->attribute_flags); \
@@ -429,7 +430,7 @@ snprint_def_ ## option (char * buff, int len, void * data) \
#define declare_mp_attr_handler(option, function) \
static int \
-mp_ ## option ## _handler (vector strvec) \
+mp_ ## option ## _handler (struct config *conf, vector strvec) \
{ \
struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable); \
if (!mpe) \
@@ -439,7 +440,7 @@ mp_ ## option ## _handler (vector strvec) \
#define declare_mp_attr_snprint(option, function) \
static int \
-snprint_mp_ ## option (char * buff, int len, void * data) \
+snprint_mp_ ## option (struct config *conf, char * buff, int len, void * data) \
{ \
struct mpentry * mpe = (struct mpentry *)data; \
return function (buff, len, &mpe->option, \
@@ -708,7 +709,7 @@ get_sys_max_fds(int *max_fds)
static int
-max_fds_handler(vector strvec)
+max_fds_handler(struct config *conf, vector strvec)
{
char * buff;
int r = 0, max_fds;
@@ -738,7 +739,7 @@ max_fds_handler(vector strvec)
}
static int
-snprint_max_fds (char * buff, int len, void * data)
+snprint_max_fds (struct config *conf, char * buff, int len, void * data)
{
int r = 0, max_fds;
@@ -805,6 +806,8 @@ set_pgfailback(vector strvec, void *ptr)
char * buff;
buff = set_value(strvec);
+ if (!buff)
+ return 1;
if (strlen(buff) == 6 && !strcmp(buff, "manual"))
*int_ptr = -FAILBACK_MANUAL;
@@ -896,7 +899,7 @@ declare_mp_handler(no_path_retry, set_no_path_retry)
declare_mp_snprint(no_path_retry, print_no_path_retry)
static int
-def_log_checker_err_handler(vector strvec)
+def_log_checker_err_handler(struct config *conf, vector strvec)
{
char * buff;
@@ -915,7 +918,7 @@ def_log_checker_err_handler(vector strvec)
}
static int
-snprint_def_log_checker_err (char * buff, int len, void * data)
+snprint_def_log_checker_err (struct config *conf, char * buff, int len, void * data)
{
if (conf->log_checker_err == LOG_CHKR_ERR_ONCE)
return snprintf(buff, len, "once");
@@ -1048,7 +1051,7 @@ declare_mp_handler(delay_wait_checks, set_delay_checks)
declare_mp_snprint(delay_wait_checks, print_delay_checks)
static int
-def_uxsock_timeout_handler(vector strvec)
+def_uxsock_timeout_handler(struct config *conf, vector strvec)
{
unsigned int uxsock_timeout;
char *buff;
@@ -1071,7 +1074,7 @@ def_uxsock_timeout_handler(vector strvec)
* blacklist block handlers
*/
static int
-blacklist_handler(vector strvec)
+blacklist_handler(struct config *conf, vector strvec)
{
if (!conf->blist_devnode)
conf->blist_devnode = vector_alloc();
@@ -1090,7 +1093,7 @@ blacklist_handler(vector strvec)
}
static int
-blacklist_exceptions_handler(vector strvec)
+blacklist_exceptions_handler(struct config *conf, vector strvec)
{
if (!conf->elist_devnode)
conf->elist_devnode = vector_alloc();
@@ -1110,7 +1113,7 @@ blacklist_exceptions_handler(vector strvec)
#define declare_ble_handler(option) \
static int \
-ble_ ## option ## _handler (vector strvec) \
+ble_ ## option ## _handler (struct config *conf, vector strvec) \
{ \
char * buff; \
\
@@ -1126,7 +1129,7 @@ ble_ ## option ## _handler (vector strvec) \
#define declare_ble_device_handler(name, option, vend, prod) \
static int \
-ble_ ## option ## _ ## name ## _handler (vector strvec) \
+ble_ ## option ## _ ## name ## _handler (struct config *conf, vector strvec) \
{ \
char * buff; \
\
@@ -1148,13 +1151,13 @@ declare_ble_handler(blist_property)
declare_ble_handler(elist_property)
static int
-snprint_def_uxsock_timeout(char * buff, int len, void * data)
+snprint_def_uxsock_timeout(struct config *conf, char * buff, int len, void * data)
{
return snprintf(buff, len, "%u", conf->uxsock_timeout);
}
static int
-snprint_ble_simple (char * buff, int len, void * data)
+snprint_ble_simple (struct config *conf, char * buff, int len, void * data)
{
struct blentry * ble = (struct blentry *)data;
@@ -1162,13 +1165,13 @@ snprint_ble_simple (char * buff, int len, void * data)
}
static int
-ble_device_handler(vector strvec)
+ble_device_handler(struct config *conf, vector strvec)
{
return alloc_ble_device(conf->blist_device);
}
static int
-ble_except_device_handler(vector strvec)
+ble_except_device_handler(struct config *conf, vector strvec)
{
return alloc_ble_device(conf->elist_device);
}
@@ -1179,7 +1182,7 @@ declare_ble_device_handler(product, blist_device, NULL, buff)
declare_ble_device_handler(product, elist_device, NULL, buff)
static int
-snprint_bled_vendor (char * buff, int len, void * data)
+snprint_bled_vendor (struct config *conf, char * buff, int len, void * data)
{
struct blentry_device * bled = (struct blentry_device *)data;
@@ -1187,7 +1190,7 @@ snprint_bled_vendor (char * buff, int len, void * data)
}
static int
-snprint_bled_product (char * buff, int len, void * data)
+snprint_bled_product (struct config *conf, char * buff, int len, void * data)
{
struct blentry_device * bled = (struct blentry_device *)data;
@@ -1198,7 +1201,7 @@ snprint_bled_product (char * buff, int len, void * data)
* devices block handlers
*/
static int
-devices_handler(vector strvec)
+devices_handler(struct config *conf, vector strvec)
{
if (!conf->hwtable)
conf->hwtable = vector_alloc();
@@ -1210,7 +1213,7 @@ devices_handler(vector strvec)
}
static int
-device_handler(vector strvec)
+device_handler(struct config *conf, vector strvec)
{
struct hwentry * hwe;
@@ -1247,7 +1250,7 @@ declare_hw_snprint(hwhandler, print_str)
* overrides handlers
*/
static int
-overrides_handler(vector strvec)
+overrides_handler(struct config *conf, vector strvec)
{
if (!conf->overrides)
conf->overrides = alloc_hwe();
@@ -1264,7 +1267,7 @@ overrides_handler(vector strvec)
* multipaths block handlers
*/
static int
-multipaths_handler(vector strvec)
+multipaths_handler(struct config *conf, vector strvec)
{
if (!conf->mptable)
conf->mptable = vector_alloc();
@@ -1276,7 +1279,7 @@ multipaths_handler(vector strvec)
}
static int
-multipath_handler(vector strvec)
+multipath_handler(struct config *conf, vector strvec)
{
struct mpentry * mpe;
@@ -1305,7 +1308,7 @@ declare_mp_snprint(alias, print_str)
*/
static int
-deprecated_handler(vector strvec)
+deprecated_handler(struct config *conf, vector strvec)
{
char * buff;
@@ -1319,7 +1322,7 @@ deprecated_handler(vector strvec)
}
static int
-snprint_deprecated (char * buff, int len, void * data)
+snprint_deprecated (struct config *conf, char * buff, int len, void * data)
{
return 0;
}
@@ -1327,7 +1330,7 @@ snprint_deprecated (char * buff, int len, void * data)
#define __deprecated
void
-init_keywords(void)
+init_keywords(vector keywords)
{
install_keyword_root("defaults", NULL);
install_keyword("verbosity", &def_verbosity_handler, &snprint_def_verbosity);
diff --git a/libmultipath/dict.h b/libmultipath/dict.h
index 4fdd576..4cd03c5 100644
--- a/libmultipath/dict.h
+++ b/libmultipath/dict.h
@@ -5,7 +5,7 @@
#include "vector.h"
#endif
-void init_keywords(void);
+void init_keywords(vector keywords);
int get_sys_max_fds(int *);
int print_rr_weight (char * buff, int len, void *ptr);
int print_pgfailback (char * buff, int len, void *ptr);
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
index db82b00..1fb4db4 100644
--- a/libmultipath/discovery.c
+++ b/libmultipath/discovery.c
@@ -32,7 +32,7 @@
#include "defaults.h"
int
-alloc_path_with_pathinfo (vector hwtable, struct udev_device *udevice,
+alloc_path_with_pathinfo (struct config *conf, struct udev_device *udevice,
int flag, struct path **pp_ptr)
{
int err = PATHINFO_FAILED;
@@ -55,7 +55,7 @@ alloc_path_with_pathinfo (vector hwtable, struct udev_device *udevice,
condlog(0, "pp->dev too small");
} else {
pp->udev = udev_device_ref(udevice);
- err = pathinfo(pp, hwtable, flag | DI_BLACKLIST);
+ err = pathinfo(pp, conf, flag | DI_BLACKLIST);
}
if (err)
@@ -66,8 +66,8 @@ alloc_path_with_pathinfo (vector hwtable, struct udev_device *udevice,
}
int
-store_pathinfo (vector pathvec, vector hwtable, struct udev_device *udevice,
- int flag, struct path **pp_ptr)
+store_pathinfo (vector pathvec, struct config *conf,
+ struct udev_device *udevice, int flag, struct path **pp_ptr)
{
int err = PATHINFO_FAILED;
struct path * pp;
@@ -90,9 +90,7 @@ store_pathinfo (vector pathvec, vector hwtable, struct udev_device *udevice,
goto out;
}
pp->udev = udev_device_ref(udevice);
- err = pathinfo(pp, hwtable,
- (conf->cmd == CMD_REMOVE_WWID)? flag :
- (flag | DI_BLACKLIST));
+ err = pathinfo(pp, conf, flag);
if (err)
goto out;
@@ -128,22 +126,23 @@ path_discover (vector pathvec, struct config * conf,
pp = find_path_by_dev(pathvec, (char *)devname);
if (!pp) {
- return store_pathinfo(pathvec, conf->hwtable,
+ return store_pathinfo(pathvec, conf,
udevice, flag, NULL);
}
- return pathinfo(pp, conf->hwtable, flag);
+ return pathinfo(pp, conf, flag);
}
int
-path_discovery (vector pathvec, struct config * conf, int flag)
+path_discovery (vector pathvec, int flag)
{
struct udev_enumerate *udev_iter;
struct udev_list_entry *entry;
struct udev_device *udevice;
+ struct config *conf;
const char *devpath;
int num_paths = 0, total_paths = 0;
- udev_iter = udev_enumerate_new(conf->udev);
+ udev_iter = udev_enumerate_new(udev);
if (!udev_iter)
return -ENOMEM;
@@ -156,7 +155,7 @@ path_discovery (vector pathvec, struct config * conf, int flag)
const char *devtype;
devpath = udev_list_entry_get_name(entry);
condlog(4, "Discover device %s", devpath);
- udevice = udev_device_new_from_syspath(conf->udev, devpath);
+ udevice = udev_device_new_from_syspath(udev, devpath);
if (!udevice) {
condlog(4, "%s: no udev information", devpath);
continue;
@@ -164,9 +163,11 @@ path_discovery (vector pathvec, struct config * conf, int flag)
devtype = udev_device_get_devtype(udevice);
if(devtype && !strncmp(devtype, "disk", 4)) {
total_paths++;
+ conf = get_multipath_config();
if (path_discover(pathvec, conf,
udevice, flag) == PATHINFO_OK)
num_paths++;
+ put_multipath_config(conf);
}
udev_device_unref(udevice);
}
@@ -208,6 +209,8 @@ declare_sysfs_get_str(devtype);
declare_sysfs_get_str(vendor);
declare_sysfs_get_str(model);
declare_sysfs_get_str(rev);
+declare_sysfs_get_str(access_state);
+declare_sysfs_get_str(preferred_path);
ssize_t
sysfs_get_vpd (struct udev_device * udev, int pg,
@@ -325,7 +328,7 @@ sysfs_get_tgt_nodename (struct path *pp, char * node)
value = udev_device_get_sysname(tgtdev);
if (sscanf(value, "rport-%d:%d-%d",
&host, &channel, &tgtid) == 3) {
- tgtdev = udev_device_new_from_subsystem_sysname(conf->udev,
+ tgtdev = udev_device_new_from_subsystem_sysname(udev,
"fc_remote_ports", value);
if (tgtdev) {
condlog(3, "SCSI target %d:%d:%d -> "
@@ -358,7 +361,7 @@ sysfs_get_tgt_nodename (struct path *pp, char * node)
tgtid = -1;
}
if (parent && tgtname) {
- tgtdev = udev_device_new_from_subsystem_sysname(conf->udev,
+ tgtdev = udev_device_new_from_subsystem_sysname(udev,
"iscsi_session", tgtname);
if (tgtdev) {
const char *value;
@@ -432,7 +435,7 @@ int sysfs_get_host_pci_name(struct path *pp, char *pci_name)
return 1;
sprintf(host_name, "host%d", pp->sg_id.host_no);
- hostdev = udev_device_new_from_subsystem_sysname(conf->udev,
+ hostdev = udev_device_new_from_subsystem_sysname(udev,
"scsi_host", host_name);
if (!hostdev)
return 1;
@@ -468,7 +471,7 @@ int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address)
const char *value;
sprintf(host_name, "host%d", pp->sg_id.host_no);
- hostdev = udev_device_new_from_subsystem_sysname(conf->udev,
+ hostdev = udev_device_new_from_subsystem_sysname(udev,
"iscsi_host", host_name);
if (hostdev) {
value = udev_device_get_sysattr_value(hostdev,
@@ -483,6 +486,37 @@ int sysfs_get_iscsi_ip_address(struct path *pp, char *ip_address)
return 1;
}
+int
+sysfs_get_asymmetric_access_state(struct path *pp, char *buff, int buflen)
+{
+ struct udev_device *parent = pp->udev;
+ char value[16], *eptr;
+ unsigned int preferred;
+
+ while (parent) {
+ const char *subsys = udev_device_get_subsystem(parent);
+ if (subsys && !strncmp(subsys, "scsi", 4))
+ break;
+ parent = udev_device_get_parent(parent);
+ }
+
+ if (!parent)
+ return -1;
+
+ if (sysfs_get_access_state(parent, buff, buflen) <= 0)
+ return -1;
+
+ if (sysfs_get_preferred_path(parent, value, 16) <= 0)
+ return 0;
+
+ preferred = strtoul(value, &eptr, 0);
+ if (value == eptr || preferred == ULONG_MAX) {
+ /* Parse error, ignore */
+ return 0;
+ }
+ return preferred;
+}
+
static void
sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
{
@@ -494,7 +528,7 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
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,
+ rport_dev = udev_device_new_from_subsystem_sysname(udev,
"fc_remote_ports", rport_id);
if (!rport_dev) {
condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev,
@@ -598,7 +632,7 @@ sysfs_set_session_tmo(struct multipath *mpp, struct path *pp)
char value[11];
sprintf(session_id, "session%d", pp->sg_id.transport_id);
- session_dev = udev_device_new_from_subsystem_sysname(conf->udev,
+ session_dev = udev_device_new_from_subsystem_sysname(udev,
"iscsi_session", session_id);
if (!session_dev) {
condlog(1, "%s: No iscsi session for '%s'", pp->dev,
@@ -640,7 +674,7 @@ sysfs_set_nexus_loss_tmo(struct multipath *mpp, struct path *pp)
sprintf(end_dev_id, "end_device-%d:%d",
pp->sg_id.host_no, pp->sg_id.transport_id);
- sas_dev = udev_device_new_from_subsystem_sysname(conf->udev,
+ sas_dev = udev_device_new_from_subsystem_sysname(udev,
"sas_end_device", end_dev_id);
if (!sas_dev) {
condlog(1, "%s: No SAS end device for '%s'", pp->dev,
@@ -663,14 +697,14 @@ sysfs_set_nexus_loss_tmo(struct multipath *mpp, struct path *pp)
}
int
-sysfs_set_scsi_tmo (struct multipath *mpp)
+sysfs_set_scsi_tmo (struct multipath *mpp, int checkint)
{
struct path *pp;
int i;
int dev_loss_tmo = mpp->dev_loss;
if (mpp->no_path_retry > 0) {
- int no_path_retry_tmo = mpp->no_path_retry * conf->checkint;
+ uint64_t no_path_retry_tmo = mpp->no_path_retry * checkint;
if (no_path_retry_tmo > MAX_DEV_LOSS_TMO)
no_path_retry_tmo = MAX_DEV_LOSS_TMO;
@@ -1069,7 +1103,7 @@ get_vpd_sgio (int fd, int pg, char * str, int maxlen)
}
static int
-scsi_sysfs_pathinfo (struct path * pp)
+scsi_sysfs_pathinfo (struct path * pp, vector hwtable)
{
struct udev_device *parent;
const char *attr_path = NULL;
@@ -1111,7 +1145,7 @@ scsi_sysfs_pathinfo (struct path * pp)
/*
* set the hwe configlet pointer
*/
- pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, pp->rev);
+ pp->hwe = find_hwe(hwtable, pp->vendor_id, pp->product_id, pp->rev);
/*
* host / bus / target / lun
@@ -1136,7 +1170,7 @@ scsi_sysfs_pathinfo (struct path * pp)
}
static int
-ccw_sysfs_pathinfo (struct path * pp)
+ccw_sysfs_pathinfo (struct path * pp, vector hwtable)
{
struct udev_device *parent;
char attr_buff[NAME_SIZE];
@@ -1172,29 +1206,30 @@ ccw_sysfs_pathinfo (struct path * pp)
/*
* set the hwe configlet pointer
*/
- pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, NULL);
+ pp->hwe = find_hwe(hwtable, pp->vendor_id, pp->product_id, NULL);
/*
* host / bus / target / lun
*/
attr_path = udev_device_get_sysname(parent);
pp->sg_id.lun = 0;
- sscanf(attr_path, "%i.%i.%x",
- &pp->sg_id.host_no,
- &pp->sg_id.channel,
- &pp->sg_id.scsi_id);
- condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
+ if (sscanf(attr_path, "%i.%i.%x",
+ &pp->sg_id.host_no,
+ &pp->sg_id.channel,
+ &pp->sg_id.scsi_id) == 3) {
+ condlog(3, "%s: h:b:t:l = %i:%i:%i:%i",
pp->dev,
pp->sg_id.host_no,
pp->sg_id.channel,
pp->sg_id.scsi_id,
pp->sg_id.lun);
+ }
return 0;
}
static int
-cciss_sysfs_pathinfo (struct path * pp)
+cciss_sysfs_pathinfo (struct path * pp, vector hwtable)
{
const char * attr_path = NULL;
struct udev_device *parent;
@@ -1234,7 +1269,7 @@ cciss_sysfs_pathinfo (struct path * pp)
/*
* set the hwe configlet pointer
*/
- pp->hwe = find_hwe(conf->hwtable, pp->vendor_id, pp->product_id, pp->rev);
+ pp->hwe = find_hwe(hwtable, pp->vendor_id, pp->product_id, pp->rev);
/*
* host / bus / target / lun
@@ -1324,7 +1359,7 @@ path_offline (struct path * pp)
}
int
-sysfs_pathinfo(struct path * pp)
+sysfs_pathinfo(struct path * pp, vector hwtable)
{
if (common_sysfs_pathinfo(pp))
return 1;
@@ -1340,13 +1375,13 @@ sysfs_pathinfo(struct path * pp)
if (pp->bus == SYSFS_BUS_UNDEF)
return 0;
else if (pp->bus == SYSFS_BUS_SCSI) {
- if (scsi_sysfs_pathinfo(pp))
+ if (scsi_sysfs_pathinfo(pp, hwtable))
return 1;
} else if (pp->bus == SYSFS_BUS_CCW) {
- if (ccw_sysfs_pathinfo(pp))
+ if (ccw_sysfs_pathinfo(pp, hwtable))
return 1;
} else if (pp->bus == SYSFS_BUS_CCISS) {
- if (cciss_sysfs_pathinfo(pp))
+ if (cciss_sysfs_pathinfo(pp, hwtable))
return 1;
}
return 0;
@@ -1398,7 +1433,7 @@ cciss_ioctl_pathinfo (struct path * pp, int mask)
}
int
-get_state (struct path * pp, int daemon)
+get_state (struct path * pp, struct config *conf, int daemon)
{
struct checker * c = &pp->checker;
int state;
@@ -1407,13 +1442,13 @@ get_state (struct path * pp, int daemon)
if (!checker_selected(c)) {
if (daemon) {
- if (pathinfo(pp, conf->hwtable, DI_SYSFS) != PATHINFO_OK) {
+ if (pathinfo(pp, conf, DI_SYSFS) != PATHINFO_OK) {
condlog(3, "%s: couldn't get sysfs pathinfo",
pp->dev);
return PATH_UNCHECKED;
}
}
- select_checker(pp);
+ select_checker(conf, pp);
if (!checker_selected(c)) {
condlog(3, "%s: No checker selected", pp->dev);
return PATH_UNCHECKED;
@@ -1447,21 +1482,27 @@ get_state (struct path * pp, int daemon)
static int
get_prio (struct path * pp)
{
+ struct prio * p;
+ struct config *conf;
+
if (!pp)
return 0;
- struct prio * p = &pp->prio;
-
+ p = &pp->prio;
if (!prio_selected(p)) {
- select_detect_prio(pp);
- select_prio(pp);
+ conf = get_multipath_config();
+ select_detect_prio(conf, pp);
+ select_prio(conf, pp);
+ put_multipath_config(conf);
if (!prio_selected(p)) {
condlog(3, "%s: no prio selected", pp->dev);
pp->priority = PRIO_UNDEF;
return 1;
}
}
- pp->priority = prio_getprio(p, pp);
+ conf = get_multipath_config();
+ pp->priority = prio_getprio(p, pp, conf->checker_timeout);
+ put_multipath_config(conf);
if (pp->priority < 0) {
condlog(3, "%s: %s prio error", pp->dev, prio_name(p));
pp->priority = PRIO_UNDEF;
@@ -1480,7 +1521,7 @@ get_udev_uid(struct path * pp, char *uid_attribute)
value = udev_device_get_property_value(pp->udev,
uid_attribute);
- if ((!value || strlen(value) == 0) && conf->cmd == CMD_VALID_PATH)
+ if (!value || strlen(value) == 0)
value = getenv(uid_attribute);
if (value && strlen(value)) {
if (strlen(value) + 1 > WWID_SIZE) {
@@ -1519,9 +1560,13 @@ get_uid (struct path * pp, int path_state)
char *c;
const char *origin = "unknown";
ssize_t len = 0;
+ struct config *conf;
- if (!pp->uid_attribute && !pp->getuid)
- select_getuid(pp);
+ if (!pp->uid_attribute && !pp->getuid) {
+ conf = get_multipath_config();
+ select_getuid(conf, pp);
+ put_multipath_config(conf);
+ }
if (!pp->udev) {
condlog(1, "%s: no udev information", pp->dev);
@@ -1547,6 +1592,8 @@ get_uid (struct path * pp, int path_state)
len = strlen(pp->wwid);
origin = "callout";
} else {
+ int retrigger;
+
if (pp->uid_attribute) {
len = get_udev_uid(pp, pp->uid_attribute);
origin = "udev";
@@ -1555,8 +1602,14 @@ get_uid (struct path * pp, int path_state)
"%s: failed to get udev uid: %s",
pp->dev, strerror(-len));
+ } else {
+ len = get_vpd_uid(pp);
+ origin = "sysfs";
}
- if (len <= 0 && pp->retriggers >= conf->retrigger_tries &&
+ conf = get_multipath_config();
+ retrigger = conf->retrigger_tries;
+ put_multipath_config(conf);
+ if (len <= 0 && pp->retriggers >= retrigger &&
!strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
len = get_vpd_uid(pp);
origin = "sysfs";
@@ -1589,7 +1642,7 @@ get_uid (struct path * pp, int path_state)
}
extern int
-pathinfo (struct path *pp, vector hwtable, int mask)
+pathinfo (struct path *pp, struct config *conf, int mask)
{
int path_state;
@@ -1611,7 +1664,7 @@ pathinfo (struct path *pp, vector hwtable, int mask)
/*
* fetch info available in sysfs
*/
- if (mask & DI_SYSFS && sysfs_pathinfo(pp))
+ if (mask & DI_SYSFS && sysfs_pathinfo(pp, conf->hwtable))
return PATHINFO_FAILED;
if (mask & DI_BLACKLIST && mask & DI_SYSFS) {
@@ -1650,7 +1703,7 @@ pathinfo (struct path *pp, vector hwtable, int mask)
if (mask & DI_CHECKER) {
if (path_state == PATH_UP) {
- pp->chkrstate = pp->state = get_state(pp, 0);
+ pp->chkrstate = pp->state = get_state(pp, conf, 0);
if (pp->state == PATH_UNCHECKED ||
pp->state == PATH_WILD)
goto blank;
@@ -1698,7 +1751,8 @@ pathinfo (struct path *pp, vector hwtable, int mask)
}
}
- pp->initialized = INIT_OK;
+ if ((mask & DI_ALL) == DI_ALL)
+ pp->initialized = INIT_OK;
return PATHINFO_OK;
blank:
diff --git a/libmultipath/discovery.h b/libmultipath/discovery.h
index 5931bc6..0f5b1e6 100644
--- a/libmultipath/discovery.h
+++ b/libmultipath/discovery.h
@@ -30,23 +30,25 @@
struct config;
-int path_discovery (vector pathvec, struct config * conf, int flag);
+int path_discovery (vector pathvec, int flag);
int do_tur (char *);
int path_offline (struct path *);
-int get_state (struct path * pp, int daemon);
-int pathinfo (struct path *, vector hwtable, int mask);
-int alloc_path_with_pathinfo (vector hwtable, struct udev_device *udevice,
+int get_state (struct path * pp, struct config * conf, int daemon);
+int pathinfo (struct path * pp, struct config * conf, int mask);
+int alloc_path_with_pathinfo (struct config *conf, struct udev_device *udevice,
int flag, struct path **pp_ptr);
-int store_pathinfo (vector pathvec, vector hwtable,
+int store_pathinfo (vector pathvec, struct config *conf,
struct udev_device *udevice, int flag,
struct path **pp_ptr);
-int sysfs_set_scsi_tmo (struct multipath *mpp);
+int sysfs_set_scsi_tmo (struct multipath *mpp, int checkint);
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);
ssize_t sysfs_get_vpd (struct udev_device * udev, int pg, unsigned char * buff,
size_t len);
+int sysfs_get_asymmetric_access_state(struct path *pp,
+ char *buff, int buflen);
/*
* discovery bitmask
diff --git a/libmultipath/dmparser.c b/libmultipath/dmparser.c
index 289be89..9e79ecd 100644
--- a/libmultipath/dmparser.c
+++ b/libmultipath/dmparser.c
@@ -13,7 +13,6 @@
#include "structs.h"
#include "util.h"
#include "debug.h"
-#include "config.h"
#define WORD_SIZE 64
@@ -142,7 +141,8 @@ assemble_map (struct multipath * mp, char * params, int len)
}
extern int
-disassemble_map (vector pathvec, char * params, struct multipath * mpp)
+disassemble_map (vector pathvec, char * params, struct multipath * mpp,
+ int is_daemon)
{
char * word;
char * p;
@@ -344,18 +344,20 @@ disassemble_map (vector pathvec, char * params, struct multipath * mpp)
if (!pp)
goto out1;
- strncpy(pp->dev_t, word, BLK_DEV_SIZE);
- strncpy(pp->dev, devname, FILE_NAME_SIZE);
+ strncpy(pp->dev_t, word, BLK_DEV_SIZE - 1);
+ strncpy(pp->dev, devname, FILE_NAME_SIZE - 1);
if (strlen(mpp->wwid)) {
- strncpy(pp->wwid, mpp->wwid, WWID_SIZE);
+ strncpy(pp->wwid, mpp->wwid,
+ WWID_SIZE - 1);
}
/* Only call this in multipath client mode */
- if (!conf->daemon && store_path(pathvec, pp))
+ if (!is_daemon && store_path(pathvec, pp))
goto out1;
} else {
if (!strlen(pp->wwid) &&
strlen(mpp->wwid))
- strncpy(pp->wwid, mpp->wwid, WWID_SIZE);
+ strncpy(pp->wwid, mpp->wwid,
+ WWID_SIZE - 1);
}
FREE(word);
@@ -367,14 +369,16 @@ disassemble_map (vector pathvec, char * params, struct multipath * mpp)
* in the get_dm_mpvec() code path
*/
if (!strlen(mpp->wwid))
- strncpy(mpp->wwid, pp->wwid, WWID_SIZE);
+ strncpy(mpp->wwid, pp->wwid,
+ WWID_SIZE - 1);
/*
* Update wwid for paths which may not have been
* active at the time the getuid callout was run
*/
else if (!strlen(pp->wwid))
- strncpy(pp->wwid, mpp->wwid, WWID_SIZE);
+ strncpy(pp->wwid, mpp->wwid,
+ WWID_SIZE - 1);
pgp->id ^= (long)pp;
pp->pgindex = i + 1;
diff --git a/libmultipath/dmparser.h b/libmultipath/dmparser.h
index 1b45df0..e1badb0 100644
--- a/libmultipath/dmparser.h
+++ b/libmultipath/dmparser.h
@@ -1,3 +1,3 @@
int assemble_map (struct multipath *, char *, int);
-int disassemble_map (vector, char *, struct multipath *);
+int disassemble_map (vector, char *, struct multipath *, int);
int disassemble_status (char *, struct multipath *);
diff --git a/libmultipath/hwtable.c b/libmultipath/hwtable.c
index d05791d..a1fc3e8 100644
--- a/libmultipath/hwtable.c
+++ b/libmultipath/hwtable.c
@@ -10,95 +10,65 @@
/*
* Tuning suggestions on these parameters should go to
- * dm-devel@redhat.com
- *
+ * dm-devel@redhat.com (subscribers-only, see README)
+ *
* You are welcome to claim maintainership over a controller
* family. Please mail the currently enlisted maintainer and
* the upstream package maintainer.
+ *
+ * Please, use the TEMPLATE below to add new hardware.
+ *
+ * WARNING:
+ *
+ * Devices with a proprietary handler must also be included in
+ * the kernel side. Currently at drivers/scsi/scsi_dh.c
*/
static struct hwentry default_hw[] = {
/*
- * Compellent Technologies, Inc.
- *
- * Maintainer : Jim Lester, Compellent
- * Mail : jim.lester@compellent.com
+ * Compellent Technologies/DELL
*/
{
.vendor = "COMPELNT",
.product = "Compellent Vol",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
/*
- * Apple controller family
+ * Apple
*
* Maintainer : Shyam Sundar
* Mail : g.shyamsundar@yahoo.co.in
*/
{
- .vendor = "APPLE*",
- .product = "Xserve RAID ",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
+ .vendor = "APPLE.*",
+ .product = "Xserve RAID",
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DEFAULT_CHECKER,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
/*
- * StorageWorks controller family
- *
- * Maintainer : Christophe Varoqui
- * Mail : christophe.varoqui@opensvc.com
+ * StorageWorks/HPE
*/
{
.vendor = "3PARdata",
.product = "VV",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DEFAULT_CHECKER,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
.vendor = "DEC",
.product = "HSG80",
.features = "1 queue_if_no_path",
.hwhandler = "1 hp_sw",
- .pgpolicy = GROUP_BY_PRIO,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
.checker_name = HP_SW,
.prio_name = PRIO_HP_SW,
- .prio_args = NULL,
},
{
.vendor = "HP",
.product = "A6189A",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 12,
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
/* MSA 1000/MSA1500 EVA 3000/5000 with old firmware */
@@ -106,157 +76,88 @@ static struct hwentry default_hw[] = {
.product = "(MSA|HSV)1.0.*",
.features = "1 queue_if_no_path",
.hwhandler = "1 hp_sw",
- .pgpolicy = GROUP_BY_PRIO,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 12,
.minio = 100,
.checker_name = HP_SW,
.prio_name = PRIO_HP_SW,
- .prio_args = NULL,
},
{
/* MSA 1000/1500 with new firmware */
.vendor = "(COMPAQ|HP)",
.product = "MSA VOLUME",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 12,
.minio = 100,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
{
/* EVA 3000/5000 with new firmware, EVA 4000/6000/8000 */
.vendor = "(COMPAQ|HP)",
.product = "HSV1[01]1|HSV2[01]0|HSV3[046]0|HSV4[05]0",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 12,
.minio = 100,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
{
- /* HP MSA2000 product family with old firmware */
+ /* HP MSA2000 family with old firmware */
.vendor = "HP",
.product = "MSA2[02]12fc|MSA2012i",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 18,
.minio = 100,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
- /* HP MSA2000 product family with new firmware */
+ /* HP MSA2000 family with new firmware */
.vendor = "HP",
.product = "MSA2012sa|MSA23(12|24)(fc|i|sa)|MSA2000s VOLUME",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 18,
.minio = 100,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
{
- /* HP MSA 1040/2040 product family */
+ /* HP MSA 1040/2040 family */
.vendor = "HP",
.product = "MSA (1|2)040 SA(N|S)",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 18,
.minio = 100,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
-
{
/* HP SVSP */
.vendor = "HP",
.product = "HSVX700",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 alua",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 12,
.minio = 100,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
-
{
/* HP Smart Array */
.vendor = "HP",
.product = "LOGICAL VOLUME.*",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 12,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
- /* HP P2000 family arrays */
+ /* HP P2000 family */
.vendor = "HP",
.product = "P2000 G3 FC|P2000G3 FC/iSCSI|P2000 G3 SAS|P2000 G3 iSCSI",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 18,
.minio = 100,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
/*
- * DDN controller family
- *
- * Maintainer : Christophe Varoqui
- * Mail : christophe.varoqui@opensvc.com
+ * DDN
*/
{
.vendor = "DDN",
.product = "SAN DataDirector",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
/*
- * EMC / Clariion controller family
+ * EMC/DELL
*
* Maintainer : Edward Goggin, EMC
* Mail : egoggin@emc.com
@@ -264,93 +165,54 @@ static struct hwentry default_hw[] = {
{
.vendor = "EMC",
.product = "SYMMETRIX",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 6,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
- .vendor = "DGC",
- .product = ".*",
+ /* DGC CLARiiON CX/AX and EMC VNX */
+ .vendor = "^DGC",
+ .product = "^RAID|^DISK|^VRAID",
.bl_product = "LUNZ",
.features = "1 queue_if_no_path",
.hwhandler = "1 emc",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = (300 / DEFAULT_CHECKINT),
.checker_name = EMC_CLARIION,
.prio_name = PRIO_EMC,
- .prio_args = NULL,
- .retain_hwhandler = RETAIN_HWHANDLER_ON,
- .detect_prio = DETECT_PRIO_ON,
},
{
.vendor = "EMC",
.product = "Invista",
.bl_product = "LUNZ",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 5,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
.vendor = "XtremIO",
.product = "XtremApp",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.selector = "queue-length 0",
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .checker_name = TUR,
- .fast_io_fail = 5,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
/*
- * Fujitsu controller family
- *
- * Maintainer : Christophe Varoqui
- * Mail : christophe.varoqui@opensvc.com
+ * Fujitsu
*/
{
.vendor = "FSC",
.product = "CentricStor",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = GROUP_BY_SERIAL,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
.vendor = "FUJITSU",
.product = "ETERNUS_DX(H|L|M|400|8000)",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 10,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
/*
- * Hitachi controller family
+ * Hitachi
*
* Maintainer : Matthias Rudolph
* Mail : matthias.rudolph@hds.com
@@ -358,31 +220,17 @@ static struct hwentry default_hw[] = {
{
.vendor = "(HITACHI|HP)",
.product = "OPEN-.*",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
.vendor = "HITACHI",
.product = "DF.*",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
.prio_name = PRIO_HDS,
- .prio_args = NULL,
},
/*
- * IBM controller family
+ * IBM
*
* Maintainer : Hannes Reinecke, SuSE
* Mail : hare@suse.de
@@ -390,15 +238,8 @@ static struct hwentry default_hw[] = {
{
.vendor = "IBM",
.product = "ProFibre 4000R",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
/* IBM FAStT 1722-600 */
@@ -407,13 +248,9 @@ static struct hwentry default_hw[] = {
.bl_product = "Universal Xport",
.features = "1 queue_if_no_path",
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 300,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
/* IBM DS4100 */
@@ -422,13 +259,9 @@ static struct hwentry default_hw[] = {
.bl_product = "Universal Xport",
.features = "1 queue_if_no_path",
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 300,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
/* IBM DS3200 / DS3300 / DS3400 */
@@ -437,28 +270,19 @@ static struct hwentry default_hw[] = {
.bl_product = "Universal Xport",
.features = "1 queue_if_no_path",
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 300,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
/* IBM DS4400 / DS4500 / FAStT700 */
.vendor = "IBM",
.product = "^1742",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
.vendor = "IBM",
@@ -466,189 +290,114 @@ static struct hwentry default_hw[] = {
.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,
},
{
- /* IBM DS4700 */
+ /* IBM DS4700 */
.vendor = "IBM",
.product = "^1814",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
- /* IBM DS4800 */
+ /* IBM DS4800 */
.vendor = "IBM",
.product = "^1815",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
- /* IBM DS5000 */
+ /* IBM DS5000 */
.vendor = "IBM",
.product = "^1818",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
/* IBM Netfinity Fibre Channel RAID Controller Unit */
.vendor = "IBM",
.product = "^3526",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
/* IBM DS4200 / FAStT200 */
.vendor = "IBM",
.product = "^3542",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = GROUP_BY_SERIAL,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
/* IBM ESS F20 aka Shark */
.vendor = "IBM",
.product = "^2105800",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = GROUP_BY_SERIAL,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
/* IBM ESS F20 aka Shark */
.vendor = "IBM",
.product = "^2105F20",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = GROUP_BY_SERIAL,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
/* IBM DS6000 */
.vendor = "IBM",
.product = "^1750500",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
{
/* IBM DS8000 */
.vendor = "IBM",
.product = "^2107900",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
/* IBM SAN Volume Controller */
.vendor = "IBM",
.product = "^2145",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
{
/* IBM S/390 ECKD DASD */
.vendor = "IBM",
.product = "S/390 DASD ECKD",
- .bl_product = "S/390.*",
+ .bl_product = "S/390.*",
.uid_attribute = "ID_UID",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
/* IBM S/390 FBA DASD */
.vendor = "IBM",
.product = "S/390 DASD FBA",
- .bl_product = "S/390.*",
+ .bl_product = "S/390.*",
.uid_attribute = "ID_UID",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
/* IBM IPR */
@@ -656,43 +405,24 @@ static struct hwentry default_hw[] = {
.product = "^IPR.*",
.features = "1 queue_if_no_path",
.hwhandler = "1 alua",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
{
/* IBM RSSM */
.vendor = "IBM",
.product = "1820N00",
- .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,
.minio = 100,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
{
- /* IBM XIV Storage System */
+ /* IBM XIV Storage System */
.vendor = "IBM",
.product = "2810XIV",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = 15,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
.minio = 15,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
/*
* IBM Power Virtual SCSI Devices
@@ -704,44 +434,27 @@ static struct hwentry default_hw[] = {
/* AIX VDASD */
.vendor = "AIX",
.product = "VDASD",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = (300 / DEFAULT_CHECKINT),
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
- /* IBM 3303 NVDISK */
+ /* IBM 3303 NVDISK */
.vendor = "IBM",
.product = "3303 NVDISK",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = FAILOVER,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = (300 / DEFAULT_CHECKINT),
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
+ .pgpolicy = FAILOVER,
},
{
/* AIX NVDISK */
.vendor = "AIX",
.product = "NVDISK",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 alua",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = (300 / DEFAULT_CHECKINT),
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
+ /*
+ * DELL
+ */
{
/* DELL MD3000 */
.vendor = "DELL",
@@ -749,116 +462,57 @@ static struct hwentry default_hw[] = {
.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 MD3000i */
- .vendor = "DELL",
- .product = "MD3000i",
- .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 MD32xx */
- .vendor = "DELL",
- .product = "MD32xx",
- .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 MD32xxi */
- .vendor = "DELL",
- .product = "MD32xxi",
- .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 MD36xxi */
+ /* DELL MD32xx/MD36xx */
.vendor = "DELL",
- .product = "MD36xxi",
+ .product = "MD32xx|MD36xx",
.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 */
+ /* DELL MD34xx/MD38xx */
.vendor = "DELL",
- .product = "MD36xxf",
+ .product = "MD34xx|MD38xx",
.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
+ * NETAPP ONTAP family
*
- * Maintainer : Dave Wysochanski
- * Mail : davidw@netapp.com
+ * Maintainer : Martin George
+ * Mail : marting@netapp.com
*/
{
.vendor = "NETAPP",
.product = "LUN.*",
.features = "3 queue_if_no_path pg_init_retries 50",
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
.flush_on_last_del = FLUSH_ENABLED,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
.minio = 128,
.dev_loss = MAX_DEV_LOSS_TMO,
- .checker_name = TUR,
.prio_name = PRIO_ONTAP,
- .prio_args = NULL,
- .retain_hwhandler = RETAIN_HWHANDLER_ON,
- .user_friendly_names = USER_FRIENDLY_NAMES_OFF,
- .detect_prio = DETECT_PRIO_ON,
+ },
+ {
+ /* IBM NSeries */
+ .vendor = "IBM",
+ .product = "Nseries.*",
+ .features = "1 queue_if_no_path",
+ .minio = 128,
+ .prio_name = PRIO_ONTAP,
},
/*
- * NEXENTA/COMSTAR controller family
+ * NEXENTA
*
* Maintainer : Yacine Kheddache
* Mail : yacine@alyseo.com
@@ -867,88 +521,39 @@ static struct hwentry default_hw[] = {
.vendor = "NEXENTA",
.product = "COMSTAR",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = GROUP_BY_SERIAL,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 30,
.minio = 128,
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
/*
- * IBM NSeries (NETAPP) controller family
- *
- * Maintainer : Dave Wysochanski
- * Mail : davidw@netapp.com
- */
- {
- .vendor = "IBM",
- .product = "Nseries.*",
- .features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .minio = 128,
- .checker_name = DIRECTIO,
- .prio_name = PRIO_ONTAP,
- .prio_args = NULL,
- },
- /*
- * Pillar Data controller family
+ * Pillar Data/Oracle
*
* Maintainer : Srinivasan Ramani
- * Mail : sramani@pillardata.com
+ * Mail : srinivas.ramani@oracle.com
*/
{
.vendor = "Pillar",
.product = "Axiom.*",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
-
/*
- * SGI arrays
- *
- * Maintainer : Christophe Varoqui
- * Mail : christophe.varoqui@opensvc.com
+ * SGI
*/
{
.vendor = "SGI",
.product = "TP9[13]00",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
.vendor = "SGI",
.product = "TP9[45]00",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
.vendor = "SGI",
@@ -956,95 +561,55 @@ static struct hwentry default_hw[] = {
.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,
},
- /* NEC Storage M Series */
+ /*
+ * NEC
+ */
{
+ /* M-Series */
.vendor = "NEC",
.product = "DISK ARRAY",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 alua",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
/*
- * STK arrays
- *
- * Maintainer : Christophe Varoqui
- * Mail : christophe.varoqui@opensvc.com
+ * STK/Oracle
*/
{
.vendor = "STK",
.product = "OPENstorage D280",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
+ .checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
/*
- * SUN arrays
- *
- * Maintainer : Christophe Varoqui
- * Mail : christophe.varoqui@opensvc.com
+ * SUN/Oracle
*/
{
.vendor = "SUN",
.product = "(StorEdge 3510|T4)",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DIRECTIO,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
.vendor = "SUN",
.product = "STK6580_6780",
- .features = DEFAULT_FEATURES,
+ .bl_product = "Universal Xport",
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = TUR,
+ .checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
.vendor = "EUROLOGC",
.product = "FC2502",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
- .pgpolicy = GROUP_BY_PRIO,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
- .checker_name = DEFAULT_CHECKER,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
/*
- * Pivot3 RAIGE
+ * Pivot3
*
* Maintainer : Bart Brooks, Pivot3
* Mail : bartb@pivot3.com
@@ -1053,61 +618,40 @@ static struct hwentry default_hw[] = {
.vendor = "PIVOT3",
.product = "RAIGE VOLUME",
.features = "1 queue_if_no_path",
- .hwhandler = DEFAULT_HWHANDLER,
.pgpolicy = MULTIBUS,
.pgfailback = FAILBACK_UNDEF,
- .rr_weight = RR_WEIGHT_NONE,
- .no_path_retry = NO_PATH_RETRY_UNDEF,
.minio = 100,
- .checker_name = TUR,
- .prio_name = DEFAULT_PRIO,
- .prio_args = NULL,
},
{
.vendor = "SUN",
.product = "CSM200_R",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
/* SUN/LSI 2510, 2540, 2530, 2540 */
{
.vendor = "SUN",
.product = "LCSM100_[IEFS]",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
/* StorageTek 6180 */
{
.vendor = "SUN",
.product = "SUN_6180",
- .features = DEFAULT_FEATURES,
+ .bl_product = "Universal Xport",
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
- .minio = DEFAULT_MINIO,
- .minio_rq = DEFAULT_MINIO_RQ,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
},
- /* LSI/Engenio/NetApp E-Series RDAC storage
+ /* LSI/Engenio/NetApp RDAC
*
* Maintainer : Sean Stewart
* Mail : sean.stewart@netapp.com
@@ -1118,99 +662,142 @@ static struct hwentry default_hw[] = {
.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 = 30,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
- .detect_prio = DETECT_PRIO_ON,
- .retain_hwhandler = RETAIN_HWHANDLER_ON,
},
{
.vendor = "STK",
.product = "FLEXLINE 380",
.bl_product = "Universal Xport",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 rdac",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = NO_PATH_RETRY_QUEUE,
.checker_name = RDAC,
.prio_name = PRIO_RDAC,
- .prio_args = NULL,
},
{
.vendor = "Intel",
.product = "Multi-Flex",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 alua",
- .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,
},
{
.vendor = "(LIO-ORG|SUSE)",
.product = "RBD",
- .features = DEFAULT_FEATURES,
.hwhandler = "1 alua",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .rr_weight = RR_WEIGHT_NONE,
.no_path_retry = 12,
- .checker_name = TUR,
.minio = 100,
.prio_name = PRIO_ALUA,
- .prio_args = NULL,
},
{
.vendor = "DataCore",
.product = "SANmelody",
- .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,
},
{
.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,
},
{
.vendor = "PURE",
.product = "FlashArray",
- .features = DEFAULT_FEATURES,
- .hwhandler = DEFAULT_HWHANDLER,
.selector = "queue-length 0",
.pgpolicy = MULTIBUS,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .checker_name = TUR,
.fast_io_fail = 10,
- .user_friendly_names = USER_FRIENDLY_NAMES_OFF,
- .prio_name = DEFAULT_PRIO,
.no_path_retry = 0,
.dev_loss = 60,
- .prio_args = NULL,
},
+ {
+ .vendor = "HUAWEI",
+ .product = "XSG1",
+ .pgpolicy = MULTIBUS,
+ },
+ /*
+ * Violin Memory
+ */
+ {
+ .vendor = "VIOLIN",
+ .product = "CONCERTO ARRAY",
+ .selector = "round-robin 0",
+ .pgpolicy = MULTIBUS,
+ .prio_name = PRIO_ALUA,
+ .minio = 100,
+ .rr_weight = RR_WEIGHT_PRIO,
+ .features = "1 queue_if_no_path",
+ .no_path_retry = 300,
+ },
+ /*
+ * Infinidat
+ */
+ {
+ .vendor = "NFINIDAT",
+ .product = "InfiniBox.*",
+ .prio_name = PRIO_ALUA,
+ .selector = "round-robin 0",
+ .pgfailback = 30,
+ .rr_weight = RR_WEIGHT_PRIO,
+ .no_path_retry = NO_PATH_RETRY_FAIL,
+ .flush_on_last_del = FLUSH_ENABLED,
+ .dev_loss = 30,
+ },
+ /*
+ * Tegile Systems
+ */
+ {
+ .vendor = "TEGILE",
+ .product = "ZEBI-(FC|ISCSI)|INTELLIFLASH",
+ .hwhandler = "1 alua",
+ .selector = "round-robin 0",
+ .no_path_retry = 10,
+ .dev_loss = 50,
+ .prio_name = PRIO_ALUA,
+ .pgfailback = 30,
+ .minio = 128,
+ },
+#if 0
+ /*
+ * Copy this TEMPLATE to add new hardware.
+ *
+ * Keep only mandatory and modified attributes.
+ * Standard attributes must be removed.
+ *
+ * COMPANY_NAME
+ *
+ * Maintainer : XXX
+ * Mail : XXX
+ */
+ {
+ .vendor = "VENDOR", (Mandatory)
+ .product = "PRODUCT", (Mandatory)
+ .revision = "REVISION",
+ .bl_product = "BL_PRODUCT",
+ .pgpolicy = GROUP_BY_PRIO,
+ .uid_attribute = "ID_SERIAL",
+ .selector = "service-time 0",
+ .checker_name = TUR,
+ .features = "0",
+ .hwhandler = "0",
+ .prio_name = "const",
+ .prio_args = "",
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .rr_weight = RR_WEIGHT_NONE,
+ .no_path_retry = NO_PATH_RETRY_UNDEF,
+ .minio = 1000,
+ .minio_rq = 1,
+ .flush_on_last_del = FLUSH_DISABLED,
+ .fast_io_fail = 5,
+ .dev_loss = 600,
+ .retain_hwhandler = RETAIN_HWHANDLER_ON,
+ .detect_prio = DETECT_PRIO_ON,
+ .deferred_remove = DEFERRED_REMOVE_OFF,
+ .delay_watch_checks = DELAY_CHECKS_OFF,
+ .delay_wait_checks = DELAY_CHECKS_OFF,
+ },
+#endif
/*
* EOL
*/
diff --git a/libmultipath/list.h b/libmultipath/list.h
index a0d8184..ceaa381 100644
--- a/libmultipath/list.h
+++ b/libmultipath/list.h
@@ -54,7 +54,7 @@ struct list_head {
} while (0)
/*
- * Insert a new entry between two known consecutive entries.
+ * Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
@@ -128,7 +128,7 @@ static inline void list_del(struct list_head *entry)
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
- INIT_LIST_HEAD(entry);
+ INIT_LIST_HEAD(entry);
}
/**
@@ -290,7 +290,7 @@ static inline void list_splice_tail_init(struct list_head *list,
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
- &pos->member != (head); \
+ &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
/**
@@ -301,7 +301,7 @@ static inline void list_splice_tail_init(struct list_head *list,
*/
#define list_for_each_entry_reverse(pos, head, member) \
for (pos = list_entry((head)->prev, typeof(*pos), member); \
- &pos->member != (head); \
+ &pos->member != (head); \
pos = list_entry(pos->member.prev, typeof(*pos), member))
/**
@@ -314,7 +314,7 @@ static inline void list_splice_tail_init(struct list_head *list,
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
+ &pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
#endif /* _LIST_H */
diff --git a/libmultipath/lock.c b/libmultipath/lock.c
index 6ce9a74..ec53a5e 100644
--- a/libmultipath/lock.c
+++ b/libmultipath/lock.c
@@ -6,4 +6,3 @@ void cleanup_lock (void * data)
{
unlock ((*(struct mutex_lock *)data));
}
-
diff --git a/libmultipath/log_pthread.c b/libmultipath/log_pthread.c
index e6f4b5c..035ae5d 100644
--- a/libmultipath/log_pthread.c
+++ b/libmultipath/log_pthread.c
@@ -8,7 +8,7 @@
#include <pthread.h>
#include <sys/mman.h>
-#include <memory.h>
+#include "memory.h"
#include "log_pthread.h"
#include "log.h"
@@ -130,4 +130,3 @@ void log_thread_stop (void)
log_close();
}
-
diff --git a/libmultipath/memory.h b/libmultipath/memory.h
index 882699b..8573f6f 100644
--- a/libmultipath/memory.h
+++ b/libmultipath/memory.h
@@ -46,13 +46,13 @@ int debug;
#define MAX_ALLOC_LIST 2048
#define MALLOC(n) ( dbg_malloc((n), \
- (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
+ (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
#define FREE(b) ( dbg_free((b), \
- (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
+ (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
#define REALLOC(b,n) ( dbg_realloc((b), (n), \
- (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
+ (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
#define STRDUP(n) ( dbg_strdup((n), \
- (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
+ (__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
/* Memory debug prototypes defs */
extern void *dbg_malloc(unsigned long, char *, char *, int);
diff --git a/libmultipath/parser.c b/libmultipath/parser.c
index e4296ee..dd955f3 100644
--- a/libmultipath/parser.c
+++ b/libmultipath/parser.c
@@ -20,25 +20,20 @@
#include <syslog.h>
#include <errno.h>
+#include "vector.h"
+#include "config.h"
#include "parser.h"
#include "memory.h"
#include "debug.h"
/* local vars */
static int sublevel = 0;
-static vector keywords = NULL;
-static vector *keywords_addr = NULL;
static int line_nr;
-void set_current_keywords (vector *k)
-{
- keywords_addr = k;
- keywords = NULL;
-}
-
int
-keyword_alloc(vector keywords, char *string, int (*handler) (vector),
- int (*print) (char *, int, void *), int unique)
+keyword_alloc(vector keywords, char *string,
+ int (*handler) (struct config *, vector),
+ int (*print) (struct config *, char *, int, void *), int unique)
{
struct keyword *keyword;
@@ -61,15 +56,6 @@ keyword_alloc(vector keywords, char *string, int (*handler) (vector),
return 0;
}
-int
-install_keyword_root(char *string, int (*handler) (vector))
-{
- int r = keyword_alloc(keywords, string, handler, NULL, 1);
- if (!r)
- *keywords_addr = keywords;
- return r;
-}
-
void
install_sublevel(void)
{
@@ -83,8 +69,9 @@ install_sublevel_end(void)
}
int
-_install_keyword(char *string, int (*handler) (vector),
- int (*print) (char *, int, void *), int unique)
+_install_keyword(vector keywords, char *string,
+ int (*handler) (struct config *, vector),
+ int (*print) (struct config *, char *, int, void *), int unique)
{
int i = 0;
struct keyword *keyword;
@@ -127,7 +114,7 @@ free_keywords(vector keywords)
}
struct keyword *
-find_keyword(vector v, char * name)
+find_keyword(vector keywords, vector v, char * name)
{
struct keyword *keyword;
int i;
@@ -147,7 +134,7 @@ find_keyword(vector v, char * name)
!strcmp(keyword->string, name))
return keyword;
if (keyword->sub) {
- keyword = find_keyword(keyword->sub, name);
+ keyword = find_keyword(keywords, keyword->sub, name);
if (keyword)
return keyword;
}
@@ -161,6 +148,7 @@ snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, void *data)
int r;
int fwd = 0;
char *f = fmt;
+ struct config *conf;
if (!kw || !kw->print)
return 0;
@@ -179,7 +167,9 @@ snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw, void *data)
fwd += snprintf(buff + fwd, len - fwd, "%s", kw->string);
break;
case 'v':
- r = kw->print(buff + fwd, len - fwd, data);
+ conf = get_multipath_config();
+ r = kw->print(conf, buff + fwd, len - fwd, data);
+ put_multipath_config(conf);
if (!r) { /* no output if no value */
buff = '\0';
return 0;
@@ -466,7 +456,7 @@ validate_config_strvec(vector strvec, char *file)
}
static int
-process_stream(FILE *stream, vector keywords, char *file)
+process_stream(struct config *conf, FILE *stream, vector keywords, char *file)
{
int i;
int r = 0, t;
@@ -520,7 +510,7 @@ process_stream(FILE *stream, vector keywords, char *file)
goto out;
}
if (keyword->handler) {
- t = (*keyword->handler) (strvec);
+ t = (*keyword->handler) (conf, strvec);
r += t;
if (t)
condlog(1, "multipath.conf +%d, parsing failed: %s",
@@ -529,7 +519,7 @@ process_stream(FILE *stream, vector keywords, char *file)
if (keyword->sub) {
kw_level++;
- r += process_stream(stream,
+ r += process_stream(conf, stream,
keyword->sub, file);
kw_level--;
}
@@ -549,25 +539,14 @@ out:
return r;
}
-int alloc_keywords(void)
-{
- if (!keywords)
- keywords = vector_alloc();
-
- if (!keywords)
- return 1;
-
- return 0;
-}
-
/* Data initialization */
int
-process_file(char *file)
+process_file(struct config *conf, char *file)
{
int r;
FILE *stream;
- if (!keywords) {
+ if (!conf->keywords) {
condlog(0, "No keywords alocated");
return 1;
}
@@ -580,7 +559,7 @@ process_file(char *file)
/* Stream handling */
line_nr = 0;
- r = process_stream(stream, keywords, file);
+ r = process_stream(conf, stream, conf->keywords, file);
fclose(stream);
//free_keywords(keywords);
diff --git a/libmultipath/parser.h b/libmultipath/parser.h
index ba6859e..519b805 100644
--- a/libmultipath/parser.h
+++ b/libmultipath/parser.h
@@ -1,10 +1,10 @@
-/*
+/*
* Soft: Keepalived is a failover program for the LVS project
* <www.linuxvirtualserver.org>. It monitor & manipulate
* a loadbalanced server pool using multi-layer checks.
- *
+ *
* Part: cfreader.c include file.
- *
+ *
* Version: $Id: parser.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
@@ -33,6 +33,7 @@
/* local includes */
#include "vector.h"
+#include "config.h"
/* Global definitions */
#define EOB "}"
@@ -41,8 +42,8 @@
/* ketword definition */
struct keyword {
char *string;
- int (*handler) (vector);
- int (*print) (char *, int, void *);
+ int (*handler) (struct config *, vector);
+ int (*print) (struct config *, char *, int, void *);
vector sub;
int unique;
};
@@ -57,23 +58,23 @@ struct keyword {
for (i = 0; i < (k)->sub->allocated && ((p) = (k)->sub->slot[i]); i++)
/* Prototypes */
-extern int keyword_alloc(vector keywords, char *string, int (*handler) (vector),
- int (*print) (char *, int, void *), int unique);
-extern int install_keyword_root(char *string, int (*handler) (vector));
+extern int keyword_alloc(vector keywords, char *string,
+ int (*handler) (struct config *, vector),
+ int (*print) (struct config *, char *, int, void *), int unique);
+#define install_keyword_root(str, h) keyword_alloc(keywords, str, h, NULL, 1)
extern void install_sublevel(void);
extern void install_sublevel_end(void);
-extern int _install_keyword(char *string, int (*handler) (vector),
- int (*print) (char *, int, void *), int unique);
-#define install_keyword(str, vec, pri) _install_keyword(str, vec, pri, 1)
-#define install_keyword_multi(str, vec, pri) _install_keyword(str, vec, pri, 0)
+extern int _install_keyword(vector keywords, char *string,
+ int (*handler) (struct config *, vector),
+ int (*print) (struct config *, char *, int, void *), int unique);
+#define install_keyword(str, vec, pri) _install_keyword(keywords, str, vec, pri, 1)
+#define install_keyword_multi(str, vec, pri) _install_keyword(keywords, str, vec, pri, 0)
extern void dump_keywords(vector keydump, int level);
extern void free_keywords(vector keywords);
extern vector alloc_strvec(char *string);
extern void *set_value(vector strvec);
-extern int alloc_keywords(void);
-extern int process_file(char *conf_file);
-extern struct keyword * find_keyword(vector v, char * name);
-void set_current_keywords (vector *k);
+extern int process_file(struct config *conf, char *conf_file);
+extern struct keyword * find_keyword(vector keywords, vector v, char * name);
int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
void *data);
diff --git a/libmultipath/pgpolicies.c b/libmultipath/pgpolicies.c
index 2981d51..f440441 100644
--- a/libmultipath/pgpolicies.c
+++ b/libmultipath/pgpolicies.c
@@ -341,8 +341,10 @@ group_by_prio (struct multipath * mp)
if (!pgp)
goto out;
- if (store_path(pgp->paths, VECTOR_SLOT(mp->paths, 0)))
- goto out;
+ if (store_path(pgp->paths, VECTOR_SLOT(mp->paths, 0))) {
+ free_pathgroup(pgp, KEEP_PATHS);
+ goto out;
+ }
vector_del_slot(mp->paths, 0);
@@ -350,11 +352,15 @@ group_by_prio (struct multipath * mp)
* Store the new path group into the vector.
*/
if (i < VECTOR_SIZE(mp->pg)) {
- if (!vector_insert_slot(mp->pg, i, pgp))
+ if (!vector_insert_slot(mp->pg, i, pgp)) {
+ free_pathgroup(pgp, KEEP_PATHS);
goto out;
+ }
} else {
- if (store_pathgroup(mp->pg, pgp))
+ if (store_pathgroup(mp->pg, pgp)) {
+ free_pathgroup(pgp, KEEP_PATHS);
goto out;
+ }
}
/*
diff --git a/libmultipath/pgpolicies.h b/libmultipath/pgpolicies.h
index 1f010a3..c0eaa7f 100644
--- a/libmultipath/pgpolicies.h
+++ b/libmultipath/pgpolicies.h
@@ -10,7 +10,7 @@
#define POLICY_NAME_SIZE 32
/* Storage controllers capabilities */
-enum iopolicies {
+enum iopolicies {
IOPOLICY_UNDEF,
FAILOVER,
MULTIBUS,
diff --git a/libmultipath/print.c b/libmultipath/print.c
index 7fec6e9..7c556b3 100644
--- a/libmultipath/print.c
+++ b/libmultipath/print.c
@@ -16,11 +16,11 @@
#include "vector.h"
#include "structs.h"
#include "structs_vec.h"
-#include "print.h"
#include "dmparser.h"
#include "config.h"
#include "configure.h"
#include "pgpolicies.h"
+#include "print.h"
#include "defaults.h"
#include "parser.h"
#include "blacklist.h"
@@ -274,6 +274,61 @@ snprint_multipath_vpr (char * buff, size_t len, struct multipath * mpp)
return snprintf(buff, len, "##,##");
}
+
+static int
+snprint_multipath_vend (char * buff, size_t len, struct multipath * mpp)
+{
+ struct pathgroup * pgp;
+ struct path * pp;
+ int i, j;
+
+ vector_foreach_slot(mpp->pg, pgp, i) {
+ if (!pgp)
+ continue;
+ vector_foreach_slot(pgp->paths, pp, j) {
+ if (strlen(pp->vendor_id))
+ return snprintf(buff, len, "%s", pp->vendor_id);
+ }
+ }
+ return snprintf(buff, len, "##");
+}
+
+static int
+snprint_multipath_prod (char * buff, size_t len, struct multipath * mpp)
+{
+ struct pathgroup * pgp;
+ struct path * pp;
+ int i, j;
+
+ vector_foreach_slot(mpp->pg, pgp, i) {
+ if (!pgp)
+ continue;
+ vector_foreach_slot(pgp->paths, pp, j) {
+ if (strlen(pp->product_id))
+ return snprintf(buff, len, "%s", pp->product_id);
+ }
+ }
+ return snprintf(buff, len, "##");
+}
+
+static int
+snprint_multipath_rev (char * buff, size_t len, struct multipath * mpp)
+{
+ struct pathgroup * pgp;
+ struct path * pp;
+ int i, j;
+
+ vector_foreach_slot(mpp->pg, pgp, i) {
+ if (!pgp)
+ continue;
+ vector_foreach_slot(pgp->paths, pp, j) {
+ if (strlen(pp->rev))
+ return snprintf(buff, len, "%s", pp->rev);
+ }
+ }
+ return snprintf(buff, len, "##");
+}
+
static int
snprint_action (char * buff, size_t len, struct multipath * mpp)
{
@@ -475,7 +530,7 @@ snprint_host_attr (char * buff, size_t len, struct path * pp, char *attr)
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_dev = udev_device_new_from_subsystem_sysname(udev, "fc_host",
host_id);
if (!host_dev) {
condlog(1, "%s: No fc_host device for '%s'", pp->dev, host_id);
@@ -515,7 +570,7 @@ snprint_tgt_wwpn (char * buff, size_t len, struct path * pp)
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,
+ rport_dev = udev_device_new_from_subsystem_sysname(udev,
"fc_remote_ports", rport_id);
if (!rport_dev) {
condlog(1, "%s: No fc_remote_port device for '%s'", pp->dev,
@@ -577,6 +632,9 @@ struct multipath_data mpd[] = {
{'3', "total_q_time", 0, snprint_total_q_time},
{'4', "q_timeouts", 0, snprint_q_timeouts},
{'s', "vend/prod/rev", 0, snprint_multipath_vpr},
+ {'v', "vend", 0, snprint_multipath_vend},
+ {'p', "prod", 0, snprint_multipath_prod},
+ {'e', "rev", 0, snprint_multipath_rev},
{0, NULL, 0 , NULL}
};
@@ -724,8 +782,6 @@ snprint_multipath_header (char * line, int len, char * format)
int fwd;
struct multipath_data * data;
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
@@ -759,8 +815,6 @@ snprint_multipath (char * line, int len, char * format,
struct multipath_data * data;
char buff[MAX_FIELD_LEN] = {};
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
@@ -795,8 +849,6 @@ snprint_path_header (char * line, int len, char * format)
int fwd;
struct path_data * data;
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
@@ -830,8 +882,6 @@ snprint_path (char * line, int len, char * format,
struct path_data * data;
char buff[MAX_FIELD_LEN];
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
@@ -867,8 +917,6 @@ snprint_pathgroup (char * line, int len, char * format,
struct pathgroup_data * data;
char buff[MAX_FIELD_LEN];
- memset(line, 0, len);
-
do {
if (!TAIL)
break;
@@ -1000,19 +1048,183 @@ snprint_multipath_topology (char * buff, int len, struct multipath * mpp,
}
static int
-snprint_hwentry (char * buff, int len, struct hwentry * hwe)
+snprint_json (char * buff, int len, int indent, char *json_str)
+{
+ int fwd = 0, i;
+
+ for (i = 0; i < indent; i++) {
+ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_INDENT);
+ if (fwd > len)
+ return fwd;
+ }
+
+ fwd += snprintf(buff + fwd, len - fwd, "%s", json_str);
+ return fwd;
+}
+
+static int
+snprint_json_header (char * buff, int len)
+{
+ int fwd = 0;
+
+ fwd += snprint_json(buff, len, 0, PRINT_JSON_START_ELEM);
+ if (fwd > len)
+ return fwd;
+
+ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_START_VERSION,
+ PRINT_JSON_MAJOR_VERSION, PRINT_JSON_MINOR_VERSION);
+ return fwd;
+}
+
+static int
+snprint_json_elem_footer (char * buff, int len, int indent, int last)
+{
+ int fwd = 0, i;
+
+ for (i = 0; i < indent; i++) {
+ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_INDENT);
+ if (fwd > len)
+ return fwd;
+ }
+
+ if (last == 1)
+ fwd += snprintf(buff + fwd, len - fwd, "%s", PRINT_JSON_END_LAST_ELEM);
+ else
+ fwd += snprintf(buff + fwd, len - fwd, "%s", PRINT_JSON_END_ELEM);
+ return fwd;
+}
+
+static int
+snprint_multipath_fields_json (char * buff, int len,
+ struct multipath * mpp, int last)
+{
+ int i, j, fwd = 0;
+ struct path *pp;
+ struct pathgroup *pgp;
+
+ fwd += snprint_multipath(buff, len, PRINT_JSON_MAP, mpp, 0);
+ if (fwd > len)
+ return fwd;
+
+ fwd += snprint_json(buff + fwd, len - fwd, 2, PRINT_JSON_START_GROUPS);
+ if (fwd > len)
+ return fwd;
+
+ vector_foreach_slot (mpp->pg, pgp, i) {
+
+ pgp->selector = mpp->selector;
+ fwd += snprint_pathgroup(buff + fwd, len - fwd, PRINT_JSON_GROUP, pgp);
+ if (fwd > len)
+ return fwd;
+
+ fwd += snprintf(buff + fwd, len - fwd, PRINT_JSON_GROUP_NUM, i + 1);
+ if (fwd > len)
+ return fwd;
+
+ fwd += snprint_json(buff + fwd, len - fwd, 3, PRINT_JSON_START_PATHS);
+ if (fwd > len)
+ return fwd;
+
+ vector_foreach_slot (pgp->paths, pp, j) {
+ fwd += snprint_path(buff + fwd, len - fwd, PRINT_JSON_PATH, pp, 0);
+ if (fwd > len)
+ return fwd;
+
+ fwd += snprint_json_elem_footer(buff + fwd,
+ len - fwd, 3, j + 1 == VECTOR_SIZE(pgp->paths));
+ if (fwd > len)
+ return fwd;
+ }
+ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY);
+ if (fwd > len)
+ return fwd;
+
+ fwd += snprint_json_elem_footer(buff + fwd,
+ len - fwd, 2, i + 1 == VECTOR_SIZE(mpp->pg));
+ if (fwd > len)
+ return fwd;
+ }
+
+ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY);
+ if (fwd > len)
+ return fwd;
+
+ fwd += snprint_json_elem_footer(buff + fwd, len - fwd, 1, last);
+ return fwd;
+}
+
+int
+snprint_multipath_map_json (char * buff, int len,
+ struct multipath * mpp, int last){
+ int fwd = 0;
+
+ fwd += snprint_json_header(buff, len);
+ if (fwd > len)
+ return len;
+
+ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_START_MAP);
+ if (fwd > len)
+ return len;
+
+ fwd += snprint_multipath_fields_json(buff + fwd, len - fwd, mpp, 1);
+ if (fwd > len)
+ return len;
+
+ fwd += snprint_json(buff + fwd, len - fwd, 0, "\n");
+ if (fwd > len)
+ return len;
+
+ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_LAST);
+ if (fwd > len)
+ return len;
+ return fwd;
+}
+
+int
+snprint_multipath_topology_json (char * buff, int len, struct vectors * vecs)
+{
+ int i, fwd = 0;
+ struct multipath * mpp;
+
+ fwd += snprint_json_header(buff, len);
+ if (fwd > len)
+ return len;
+
+ fwd += snprint_json(buff + fwd, len - fwd, 1, PRINT_JSON_START_MAPS);
+ if (fwd > len)
+ return len;
+
+ vector_foreach_slot(vecs->mpvec, mpp, i) {
+ fwd += snprint_multipath_fields_json(buff + fwd, len - fwd,
+ mpp, i + 1 == VECTOR_SIZE(vecs->mpvec));
+ if (fwd > len)
+ return len;
+ }
+
+ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_ARRAY);
+ if (fwd > len)
+ return len;
+
+ fwd += snprint_json(buff + fwd, len - fwd, 0, PRINT_JSON_END_LAST);
+ if (fwd > len)
+ return len;
+ return fwd;
+}
+
+static int
+snprint_hwentry (struct config *conf, char * buff, int len, struct hwentry * hwe)
{
int i;
int fwd = 0;
struct keyword * kw;
struct keyword * rootkw;
- rootkw = find_keyword(NULL, "devices");
+ rootkw = find_keyword(conf->keywords, NULL, "devices");
if (!rootkw || !rootkw->sub)
return 0;
- rootkw = find_keyword(rootkw->sub, "device");
+ rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
if (!rootkw)
return 0;
@@ -1033,14 +1245,14 @@ snprint_hwentry (char * buff, int len, struct hwentry * hwe)
}
extern int
-snprint_hwtable (char * buff, int len, vector hwtable)
+snprint_hwtable (struct config *conf, char * buff, int len, vector hwtable)
{
int fwd = 0;
int i;
struct hwentry * hwe;
struct keyword * rootkw;
- rootkw = find_keyword(NULL, "devices");
+ rootkw = find_keyword(conf->keywords, NULL, "devices");
if (!rootkw)
return 0;
@@ -1048,7 +1260,7 @@ snprint_hwtable (char * buff, int len, vector hwtable)
if (fwd > len)
return len;
vector_foreach_slot (hwtable, hwe, i) {
- fwd += snprint_hwentry(buff + fwd, len - fwd, hwe);
+ fwd += snprint_hwentry(conf, buff + fwd, len - fwd, hwe);
if (fwd > len)
return len;
}
@@ -1059,14 +1271,14 @@ snprint_hwtable (char * buff, int len, vector hwtable)
}
static int
-snprint_mpentry (char * buff, int len, struct mpentry * mpe)
+snprint_mpentry (struct config *conf, char * buff, int len, struct mpentry * mpe)
{
int i;
int fwd = 0;
struct keyword * kw;
struct keyword * rootkw;
- rootkw = find_keyword(NULL, "multipath");
+ rootkw = find_keyword(conf->keywords, NULL, "multipath");
if (!rootkw)
return 0;
@@ -1086,14 +1298,14 @@ snprint_mpentry (char * buff, int len, struct mpentry * mpe)
}
extern int
-snprint_mptable (char * buff, int len, vector mptable)
+snprint_mptable (struct config *conf, char * buff, int len, vector mptable)
{
int fwd = 0;
int i;
struct mpentry * mpe;
struct keyword * rootkw;
- rootkw = find_keyword(NULL, "multipaths");
+ rootkw = find_keyword(conf->keywords, NULL, "multipaths");
if (!rootkw)
return 0;
@@ -1101,7 +1313,7 @@ snprint_mptable (char * buff, int len, vector mptable)
if (fwd > len)
return len;
vector_foreach_slot (mptable, mpe, i) {
- fwd += snprint_mpentry(buff + fwd, len - fwd, mpe);
+ fwd += snprint_mpentry(conf, buff + fwd, len - fwd, mpe);
if (fwd > len)
return len;
}
@@ -1112,14 +1324,14 @@ snprint_mptable (char * buff, int len, vector mptable)
}
extern int
-snprint_overrides (char * buff, int len, struct hwentry *overrides)
+snprint_overrides (struct config *conf, char * buff, int len, struct hwentry *overrides)
{
int fwd = 0;
int i;
struct keyword *rootkw;
struct keyword *kw;
- rootkw = find_keyword(NULL, "overrides");
+ rootkw = find_keyword(conf->keywords, NULL, "overrides");
if (!rootkw)
return 0;
@@ -1142,14 +1354,14 @@ out:
}
extern int
-snprint_defaults (char * buff, int len)
+snprint_defaults (struct config *conf, char * buff, int len)
{
int fwd = 0;
int i;
struct keyword *rootkw;
struct keyword *kw;
- rootkw = find_keyword(NULL, "defaults");
+ rootkw = find_keyword(conf->keywords, NULL, "defaults");
if (!rootkw)
return 0;
@@ -1224,7 +1436,7 @@ snprint_blacklist_devgroup (char *buff, int len, int *fwd, vector *vec)
}
extern int
-snprint_blacklist_report (char * buff, int len)
+snprint_blacklist_report (struct config *conf, char * buff, int len)
{
int threshold = MAX_LINE_LEN;
int fwd = 0;
@@ -1287,7 +1499,7 @@ snprint_blacklist_report (char * buff, int len)
}
extern int
-snprint_blacklist (char * buff, int len)
+snprint_blacklist (struct config *conf, char * buff, int len)
{
int i;
struct blentry * ble;
@@ -1296,7 +1508,7 @@ snprint_blacklist (char * buff, int len)
struct keyword *rootkw;
struct keyword *kw;
- rootkw = find_keyword(NULL, "blacklist");
+ rootkw = find_keyword(conf->keywords, NULL, "blacklist");
if (!rootkw)
return 0;
@@ -1305,7 +1517,7 @@ snprint_blacklist (char * buff, int len)
return len;
vector_foreach_slot (conf->blist_devnode, ble, i) {
- kw = find_keyword(rootkw->sub, "devnode");
+ kw = find_keyword(conf->keywords, rootkw->sub, "devnode");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
@@ -1314,7 +1526,7 @@ snprint_blacklist (char * buff, int len)
return len;
}
vector_foreach_slot (conf->blist_wwid, ble, i) {
- kw = find_keyword(rootkw->sub, "wwid");
+ kw = find_keyword(conf->keywords, rootkw->sub, "wwid");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
@@ -1323,7 +1535,7 @@ snprint_blacklist (char * buff, int len)
return len;
}
vector_foreach_slot (conf->blist_property, ble, i) {
- kw = find_keyword(rootkw->sub, "property");
+ kw = find_keyword(conf->keywords, rootkw->sub, "property");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
@@ -1331,7 +1543,7 @@ snprint_blacklist (char * buff, int len)
if (fwd > len)
return len;
}
- rootkw = find_keyword(rootkw->sub, "device");
+ rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
if (!rootkw)
return 0;
@@ -1339,14 +1551,14 @@ snprint_blacklist (char * buff, int len)
fwd += snprintf(buff + fwd, len - fwd, "\tdevice {\n");
if (fwd > len)
return len;
- kw = find_keyword(rootkw->sub, "vendor");
+ kw = find_keyword(conf->keywords, rootkw->sub, "vendor");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t\t%k %v\n",
kw, bled);
if (fwd > len)
return len;
- kw = find_keyword(rootkw->sub, "product");
+ kw = find_keyword(conf->keywords, rootkw->sub, "product");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t\t%k %v\n",
@@ -1364,7 +1576,7 @@ snprint_blacklist (char * buff, int len)
}
extern int
-snprint_blacklist_except (char * buff, int len)
+snprint_blacklist_except (struct config *conf, char * buff, int len)
{
int i;
struct blentry * ele;
@@ -1373,7 +1585,7 @@ snprint_blacklist_except (char * buff, int len)
struct keyword *rootkw;
struct keyword *kw;
- rootkw = find_keyword(NULL, "blacklist_exceptions");
+ rootkw = find_keyword(conf->keywords, NULL, "blacklist_exceptions");
if (!rootkw)
return 0;
@@ -1382,7 +1594,7 @@ snprint_blacklist_except (char * buff, int len)
return len;
vector_foreach_slot (conf->elist_devnode, ele, i) {
- kw = find_keyword(rootkw->sub, "devnode");
+ kw = find_keyword(conf->keywords, rootkw->sub, "devnode");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
@@ -1391,7 +1603,7 @@ snprint_blacklist_except (char * buff, int len)
return len;
}
vector_foreach_slot (conf->elist_wwid, ele, i) {
- kw = find_keyword(rootkw->sub, "wwid");
+ kw = find_keyword(conf->keywords, rootkw->sub, "wwid");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
@@ -1400,7 +1612,7 @@ snprint_blacklist_except (char * buff, int len)
return len;
}
vector_foreach_slot (conf->elist_property, ele, i) {
- kw = find_keyword(rootkw->sub, "property");
+ kw = find_keyword(conf->keywords, rootkw->sub, "property");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t%k %v\n",
@@ -1408,7 +1620,7 @@ snprint_blacklist_except (char * buff, int len)
if (fwd > len)
return len;
}
- rootkw = find_keyword(rootkw->sub, "device");
+ rootkw = find_keyword(conf->keywords, rootkw->sub, "device");
if (!rootkw)
return 0;
@@ -1416,14 +1628,14 @@ snprint_blacklist_except (char * buff, int len)
fwd += snprintf(buff + fwd, len - fwd, "\tdevice {\n");
if (fwd > len)
return len;
- kw = find_keyword(rootkw->sub, "vendor");
+ kw = find_keyword(conf->keywords, rootkw->sub, "vendor");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t\t%k %v\n",
kw, eled);
if (fwd > len)
return len;
- kw = find_keyword(rootkw->sub, "product");
+ kw = find_keyword(conf->keywords, rootkw->sub, "product");
if (!kw)
return 0;
fwd += snprint_keyword(buff + fwd, len - fwd, "\t\t%k %v\n",
@@ -1459,12 +1671,12 @@ snprint_status (char * buff, int len, struct vectors *vecs)
checker_state_name(i), count[i]);
}
- int monitored_count = 0;
+ int monitored_count = 0;
- vector_foreach_slot(vecs->pathvec, pp, i)
- if (pp->fd != -1)
- monitored_count++;
- fwd += snprintf(buff + fwd, len - fwd, "\npaths: %d\nbusy: %s\n",
+ vector_foreach_slot(vecs->pathvec, pp, i)
+ if (pp->fd != -1)
+ monitored_count++;
+ fwd += snprintf(buff + fwd, len - fwd, "\npaths: %d\nbusy: %s\n",
monitored_count, is_uevent_busy()? "True" : "False");
if (fwd > len)
@@ -1473,7 +1685,7 @@ snprint_status (char * buff, int len, struct vectors *vecs)
}
extern int
-snprint_devices (char * buff, int len, struct vectors *vecs)
+snprint_devices (struct config *conf, char * buff, int len, struct vectors *vecs)
{
DIR *blkdir;
struct dirent *blkdev;
@@ -1615,4 +1827,3 @@ print_all_paths_custo (vector pathvec, int banner, char *fmt)
vector_foreach_slot (pathvec, pp, i)
print_path(pp, fmt);
}
-
diff --git a/libmultipath/print.h b/libmultipath/print.h
index 8bd0bbc..9306e50 100644
--- a/libmultipath/print.h
+++ b/libmultipath/print.h
@@ -7,6 +7,63 @@
#define PRINT_MAP_PROPS "size=%S features='%f' hwhandler='%h' wp=%r"
#define PRINT_PG_INDENT "policy='%s' prio=%p status=%t"
+#define PRINT_JSON_MULTIPLIER 5
+#define PRINT_JSON_MAJOR_VERSION 0
+#define PRINT_JSON_MINOR_VERSION 1
+#define PRINT_JSON_START_VERSION " \"major_version\": %d,\n" \
+ " \"minor_version\": %d,\n"
+#define PRINT_JSON_START_ELEM "{\n"
+#define PRINT_JSON_START_MAP " \"map\":"
+#define PRINT_JSON_START_MAPS "\"maps\": ["
+#define PRINT_JSON_START_PATHS "\"paths\": ["
+#define PRINT_JSON_START_GROUPS "\"path_groups\": ["
+#define PRINT_JSON_END_ELEM "},"
+#define PRINT_JSON_END_LAST_ELEM "}"
+#define PRINT_JSON_END_LAST "}\n"
+#define PRINT_JSON_END_ARRAY "]\n"
+#define PRINT_JSON_INDENT " "
+#define PRINT_JSON_MAP "{\n" \
+ " \"name\" : \"%n\",\n" \
+ " \"uuid\" : \"%w\",\n" \
+ " \"sysfs\" : \"%d\",\n" \
+ " \"failback\" : \"%F\",\n" \
+ " \"queueing\" : \"%Q\",\n" \
+ " \"paths\" : %N,\n" \
+ " \"write_prot\" : \"%r\",\n" \
+ " \"dm_st\" : \"%t\",\n" \
+ " \"features\" : \"%f\",\n" \
+ " \"hwhandler\" : \"%h\",\n" \
+ " \"action\" : \"%A\",\n" \
+ " \"path_faults\" : %0,\n" \
+ " \"vend\" : \"%v\",\n" \
+ " \"prod\" : \"%p\",\n" \
+ " \"rev\" : \"%e\",\n" \
+ " \"switch_grp\" : %1,\n" \
+ " \"map_loads\" : %2,\n" \
+ " \"total_q_time\" : %3,\n" \
+ " \"q_timeouts\" : %4,"
+
+#define PRINT_JSON_GROUP "{\n" \
+ " \"selector\" : \"%s\",\n" \
+ " \"pri\" : %p,\n" \
+ " \"dm_st\" : \"%t\","
+
+#define PRINT_JSON_GROUP_NUM " \"group\" : %d,\n"
+
+#define PRINT_JSON_PATH "{\n" \
+ " \"dev\" : \"%d\",\n"\
+ " \"dev_t\" : \"%D\",\n" \
+ " \"dm_st\" : \"%t\",\n" \
+ " \"dev_st\" : \"%o\",\n" \
+ " \"chk_st\" : \"%T\",\n" \
+ " \"checker\" : \"%c\",\n" \
+ " \"pri\" : %p,\n" \
+ " \"host_wwnn\" : \"%N\",\n" \
+ " \"target_wwnn\" : \"%n\",\n" \
+ " \"host_wwpn\" : \"%R\",\n" \
+ " \"target_wwpn\" : \"%r\",\n" \
+ " \"host_adapter\" : \"%a\""
+
#define MAX_LINE_LEN 80
#define MAX_LINES 64
#define MAX_FIELD_LEN 64
@@ -41,16 +98,20 @@ int snprint_path (char *, int, char *, struct path *, int);
int snprint_multipath (char *, int, char *, struct multipath *, int);
int snprint_multipath_topology (char *, int, struct multipath * mpp,
int verbosity);
-int snprint_defaults (char *, int);
-int snprint_blacklist (char *, int);
-int snprint_blacklist_except (char *, int);
-int snprint_blacklist_report (char *, int);
+int snprint_multipath_topology_json (char * buff, int len,
+ struct vectors * vecs);
+int snprint_multipath_map_json (char * buff, int len,
+ struct multipath * mpp, int last);
+int snprint_defaults (struct config *, char *, int);
+int snprint_blacklist (struct config *, char *, int);
+int snprint_blacklist_except (struct config *, char *, int);
+int snprint_blacklist_report (struct config *, char *, int);
int snprint_wildcards (char *, int);
int snprint_status (char *, int, struct vectors *);
-int snprint_devices (char *, int, struct vectors *);
-int snprint_hwtable (char *, int, vector);
-int snprint_mptable (char *, int, vector);
-int snprint_overrides (char *, int, struct hwentry *);
+int snprint_devices (struct config *, char *, int, struct vectors *);
+int snprint_hwtable (struct config *, char *, int, vector);
+int snprint_mptable (struct config *, char *, int, vector);
+int snprint_overrides (struct config *, char *, int, struct hwentry *);
int snprint_host_wwnn (char *, size_t, struct path *);
int snprint_host_wwpn (char *, size_t, struct path *);
int snprint_tgt_wwnn (char *, size_t, struct path *);
@@ -64,4 +125,3 @@ void print_map (struct multipath * mpp, char * params);
void print_all_paths (vector pathvec, int banner);
void print_all_paths_custo (vector pathvec, int banner, char *fmt);
void print_hwtable (vector hwtable);
-
diff --git a/libmultipath/prio.c b/libmultipath/prio.c
index ab8eca9..7fce921 100644
--- a/libmultipath/prio.c
+++ b/libmultipath/prio.c
@@ -6,20 +6,20 @@
#include "debug.h"
#include "prio.h"
-#include "config.h"
static LIST_HEAD(prioritizers);
-unsigned int get_prio_timeout(unsigned int default_timeout)
+unsigned int get_prio_timeout(unsigned int checker_timeout,
+ unsigned int default_timeout)
{
- if (conf->checker_timeout)
- return conf->checker_timeout * 1000;
+ if (checker_timeout)
+ return checker_timeout * 1000;
return default_timeout;
}
-int init_prio (void)
+int init_prio (char *multipath_dir)
{
- if (!add_prio(DEFAULT_PRIO))
+ if (!add_prio(multipath_dir, DEFAULT_PRIO))
return 1;
return 0;
}
@@ -67,7 +67,7 @@ void cleanup_prio(void)
}
}
-struct prio * prio_lookup (char * name)
+static struct prio * prio_lookup (char * name)
{
struct prio * p;
@@ -78,7 +78,7 @@ struct prio * prio_lookup (char * name)
if (!strncmp(name, p->name, PRIO_NAME_LEN))
return p;
}
- return add_prio(name);
+ return NULL;
}
int prio_set_args (struct prio * p, char * args)
@@ -86,7 +86,7 @@ int prio_set_args (struct prio * p, char * args)
return snprintf(p->args, PRIO_ARGS_LEN, "%s", args);
}
-struct prio * add_prio (char * name)
+struct prio * add_prio (char *multipath_dir, char * name)
{
char libname[LIB_PRIO_NAMELEN];
struct stat stbuf;
@@ -98,10 +98,10 @@ struct prio * add_prio (char * name)
return NULL;
snprintf(p->name, PRIO_NAME_LEN, "%s", name);
snprintf(libname, LIB_PRIO_NAMELEN, "%s/libprio%s.so",
- conf->multipath_dir, name);
+ multipath_dir, name);
if (stat(libname,&stbuf) < 0) {
condlog(0,"Prioritizer '%s' not found in %s",
- name, conf->multipath_dir);
+ name, multipath_dir);
goto out;
}
condlog(3, "loading %s prioritizer", libname);
@@ -112,7 +112,7 @@ struct prio * add_prio (char * name)
errstr);
goto out;
}
- p->getprio = (int (*)(struct path *, char *)) dlsym(p->handle, "getprio");
+ p->getprio = (int (*)(struct path *, char *, unsigned int)) dlsym(p->handle, "getprio");
errstr = dlerror();
if (errstr != NULL)
condlog(0, "A dynamic linking error occurred: (%s)", errstr);
@@ -125,9 +125,9 @@ out:
return NULL;
}
-int prio_getprio (struct prio * p, struct path * pp)
+int prio_getprio (struct prio * p, struct path * pp, unsigned int timeout)
{
- return p->getprio(pp, p->args);
+ return p->getprio(pp, p->args, timeout);
}
int prio_selected (struct prio * p)
@@ -147,10 +147,18 @@ char * prio_args (struct prio * p)
return p->args;
}
-void prio_get (struct prio * dst, char * name, char * args)
+void prio_get (char *multipath_dir, struct prio * dst, char * name, char * args)
{
- struct prio * src = prio_lookup(name);
+ struct prio * src = NULL;
+
+ if (!dst)
+ return;
+ if (name && strlen(name)) {
+ src = prio_lookup(name);
+ if (!src)
+ src = add_prio(multipath_dir, name);
+ }
if (!src) {
dst->getprio = NULL;
return;
@@ -158,7 +166,7 @@ void prio_get (struct prio * dst, char * name, char * args)
strncpy(dst->name, src->name, PRIO_NAME_LEN);
if (args)
- strncpy(dst->args, args, PRIO_ARGS_LEN);
+ strncpy(dst->args, args, PRIO_ARGS_LEN - 1);
dst->getprio = src->getprio;
dst->handle = NULL;
diff --git a/libmultipath/prio.h b/libmultipath/prio.h
index 495688f..032028e 100644
--- a/libmultipath/prio.h
+++ b/libmultipath/prio.h
@@ -19,16 +19,18 @@ struct path;
/*
* Known prioritizers for use in hwtable.c
*/
-#define PRIO_ALUA "alua"
-#define PRIO_CONST "const"
-#define PRIO_EMC "emc"
-#define PRIO_HDS "hds"
-#define PRIO_HP_SW "hp_sw"
-#define PRIO_ONTAP "ontap"
-#define PRIO_RANDOM "random"
-#define PRIO_RDAC "rdac"
-#define PRIO_DATACORE "datacore"
-#define PRIO_WEIGHTED_PATH "weightedpath"
+#define PRIO_ALUA "alua"
+#define PRIO_CONST "const"
+#define PRIO_DATACORE "datacore"
+#define PRIO_EMC "emc"
+#define PRIO_HDS "hds"
+#define PRIO_HP_SW "hp_sw"
+#define PRIO_IET "iet"
+#define PRIO_ONTAP "ontap"
+#define PRIO_RANDOM "random"
+#define PRIO_RDAC "rdac"
+#define PRIO_WEIGHTED_PATH "weightedpath"
+#define PRIO_SYSFS "sysfs"
/*
* Value used to mark the fact prio was not defined
@@ -48,16 +50,16 @@ struct prio {
struct list_head node;
char name[PRIO_NAME_LEN];
char args[PRIO_ARGS_LEN];
- int (*getprio)(struct path *, char *);
+ int (*getprio)(struct path *, char *, unsigned int);
};
-unsigned int get_prio_timeout(unsigned int default_timeout);
-int init_prio (void);
+unsigned int get_prio_timeout(unsigned int checker_timeout,
+ unsigned int default_timeout);
+int init_prio (char *);
void cleanup_prio (void);
-struct prio * add_prio (char *);
-struct prio * prio_lookup (char *);
-int prio_getprio (struct prio *, struct path *);
-void prio_get (struct prio *, char *, char *);
+struct prio * add_prio (char *, char *);
+int prio_getprio (struct prio *, struct path *, unsigned int);
+void prio_get (char *, struct prio *, char *, char *);
void prio_put (struct prio *);
int prio_selected (struct prio *);
char * prio_name (struct prio *);
diff --git a/libmultipath/prioritizers/Makefile b/libmultipath/prioritizers/Makefile
index 6cfac88..bb76700 100644
--- a/libmultipath/prioritizers/Makefile
+++ b/libmultipath/prioritizers/Makefile
@@ -5,17 +5,18 @@
include ../../Makefile.inc
LIBS = \
- libpriorandom.so \
- libprioconst.so \
- libpriohp_sw.so \
- libprioemc.so \
- libpriordac.so \
libprioalua.so \
- libprioontap.so \
+ libprioconst.so \
libpriodatacore.so \
+ libprioemc.so \
libpriohds.so \
+ libpriohp_sw.so \
+ libprioiet.so \
+ libprioontap.so \
+ libpriorandom.so \
+ libpriordac.so \
libprioweightedpath.so \
- libprioiet.so
+ libpriosysfs.so
CFLAGS += -I..
@@ -31,7 +32,7 @@ install: $(LIBS)
$(INSTALL_PROGRAM) -m 755 libprio*.so $(DESTDIR)$(libdir)
uninstall:
- for file in $(LIBS); do rm -f $(DESTDIR)$(libdir)/$$file; done
+ for file in $(LIBS); do $(RM) $(DESTDIR)$(libdir)/$$file; done
clean:
- rm -f core *.a *.o *.gz *.so
+ $(RM) core *.a *.o *.gz *.so
diff --git a/libmultipath/prioritizers/alua.c b/libmultipath/prioritizers/alua.c
index cd4aafc..a1c59fd 100644
--- a/libmultipath/prioritizers/alua.c
+++ b/libmultipath/prioritizers/alua.c
@@ -9,14 +9,14 @@
*
* Author(s): Jan Kunigk
* S. Bader <shbader@de.ibm.com>
- *
+ *
* This file is released under the GPL.
*/
#include <stdio.h>
-#include <debug.h>
-#include <prio.h>
-#include <structs.h>
+#include "debug.h"
+#include "prio.h"
+#include "structs.h"
#include "alua.h"
@@ -51,14 +51,14 @@ static const char *aas_print_string(int rc)
}
int
-get_alua_info(struct path * pp)
+get_alua_info(struct path * pp, unsigned int timeout)
{
int rc;
int tpg;
- tpg = get_target_port_group(pp);
+ tpg = get_target_port_group(pp, timeout);
if (tpg < 0) {
- rc = get_target_port_group_support(pp->fd);
+ rc = get_target_port_group_support(pp->fd, timeout);
if (rc < 0)
return -ALUA_PRIO_TPGS_FAILED;
if (rc == TPGS_NONE)
@@ -66,7 +66,7 @@ get_alua_info(struct path * pp)
return -ALUA_PRIO_RTPG_FAILED;
}
condlog(3, "reported target port group is %i", tpg);
- rc = get_asymmetric_access_state(pp->fd, tpg);
+ rc = get_asymmetric_access_state(pp->fd, tpg, timeout);
if (rc < 0)
return -ALUA_PRIO_GETAAS_FAILED;
@@ -75,7 +75,7 @@ get_alua_info(struct path * pp)
return rc;
}
-int get_exclusive_perf_arg(char *args)
+int get_exclusive_pref_arg(char *args)
{
char *ptr;
@@ -91,18 +91,18 @@ int get_exclusive_perf_arg(char *args)
return 1;
}
-int getprio (struct path * pp, char * args)
+int getprio (struct path * pp, char * args, unsigned int timeout)
{
int rc;
int aas;
int priopath;
- int exclusive_perf;
+ int exclusive_pref;
if (pp->fd < 0)
return -ALUA_PRIO_NO_INFORMATION;
- exclusive_perf = get_exclusive_perf_arg(args);
- rc = get_alua_info(pp);
+ exclusive_pref = get_exclusive_pref_arg(args);
+ rc = get_alua_info(pp, timeout);
if (rc >= 0) {
aas = (rc & 0x0f);
priopath = (rc & 0x80);
@@ -122,7 +122,7 @@ int getprio (struct path * pp, char * args)
default:
rc = 0;
}
- if (priopath && (aas != AAS_OPTIMIZED || exclusive_perf))
+ if (priopath && (aas != AAS_OPTIMIZED || exclusive_pref))
rc += 80;
} else {
switch(-rc) {
diff --git a/libmultipath/prioritizers/alua_rtpg.c b/libmultipath/prioritizers/alua_rtpg.c
index 636aae5..e9d8328 100644
--- a/libmultipath/prioritizers/alua_rtpg.c
+++ b/libmultipath/prioritizers/alua_rtpg.c
@@ -9,12 +9,13 @@
*
* Author(s): Jan Kunigk
* S. Bader <shbader@de.ibm.com>
- *
+ *
* This file is released under the GPL.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <sys/ioctl.h>
#include <inttypes.h>
#include <libudev.h>
@@ -114,7 +115,8 @@ scsi_error(struct sg_io_hdr *hdr)
* Helper function to setup and run a SCSI inquiry command.
*/
int
-do_inquiry(int fd, int evpd, unsigned int codepage, void *resp, int resplen)
+do_inquiry(int fd, int evpd, unsigned int codepage,
+ void *resp, int resplen, unsigned int timeout)
{
struct inquiry_command cmd;
struct sg_io_hdr hdr;
@@ -138,7 +140,7 @@ do_inquiry(int fd, int evpd, unsigned int codepage, void *resp, int resplen)
hdr.dxfer_len = resplen;
hdr.sbp = sense;
hdr.mx_sb_len = sizeof(sense);
- hdr.timeout = get_prio_timeout(SGIO_TIMEOUT);
+ hdr.timeout = get_prio_timeout(timeout, SGIO_TIMEOUT);
if (ioctl(fd, SG_IO, &hdr) < 0) {
PRINT_DEBUG("do_inquiry: IOCTL failed!\n");
@@ -159,13 +161,13 @@ do_inquiry(int fd, int evpd, unsigned int codepage, void *resp, int resplen)
* data returned by the standard inquiry command.
*/
int
-get_target_port_group_support(int fd)
+get_target_port_group_support(int fd, unsigned int timeout)
{
struct inquiry_data inq;
int rc;
memset((unsigned char *)&inq, 0, sizeof(inq));
- rc = do_inquiry(fd, 0, 0x00, &inq, sizeof(inq));
+ rc = do_inquiry(fd, 0, 0x00, &inq, sizeof(inq), timeout);
if (!rc) {
rc = inquiry_data_get_tpgs(&inq);
}
@@ -193,7 +195,7 @@ get_sysfs_pg83(struct path *pp, unsigned char *buff, int buflen)
}
int
-get_target_port_group(struct path * pp)
+get_target_port_group(struct path * pp, unsigned int timeout)
{
unsigned char *buf;
struct vpd83_data * vpd83;
@@ -214,11 +216,14 @@ get_target_port_group(struct path * pp)
rc = get_sysfs_pg83(pp, buf, buflen);
if (rc < 0) {
- rc = do_inquiry(pp->fd, 1, 0x83, buf, buflen);
+ rc = do_inquiry(pp->fd, 1, 0x83, buf, buflen, timeout);
if (rc < 0)
goto out;
scsi_buflen = (buf[2] << 8 | buf[3]) + 4;
+ /* Paranoia */
+ if (scsi_buflen >= USHRT_MAX)
+ scsi_buflen = USHRT_MAX;
if (buflen < scsi_buflen) {
free(buf);
buf = (unsigned char *)malloc(scsi_buflen);
@@ -229,7 +234,7 @@ get_target_port_group(struct path * pp)
}
buflen = scsi_buflen;
memset(buf, 0, buflen);
- rc = do_inquiry(pp->fd, 1, 0x83, buf, buflen);
+ rc = do_inquiry(pp->fd, 1, 0x83, buf, buflen, timeout);
if (rc < 0)
goto out;
}
@@ -260,7 +265,7 @@ out:
}
int
-do_rtpg(int fd, void* resp, long resplen)
+do_rtpg(int fd, void* resp, long resplen, unsigned int timeout)
{
struct rtpg_command cmd;
struct sg_io_hdr hdr;
@@ -281,7 +286,7 @@ do_rtpg(int fd, void* resp, long resplen)
hdr.dxfer_len = resplen;
hdr.mx_sb_len = sizeof(sense);
hdr.sbp = sense;
- hdr.timeout = get_prio_timeout(SGIO_TIMEOUT);
+ hdr.timeout = get_prio_timeout(timeout, SGIO_TIMEOUT);
if (ioctl(fd, SG_IO, &hdr) < 0)
return -RTPG_RTPG_FAILED;
@@ -296,14 +301,14 @@ 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, unsigned int timeout)
{
unsigned char *buf;
struct rtpg_data * tpgd;
struct rtpg_tpg_dscr * dscr;
int rc;
int buflen;
- uint32_t scsi_buflen;
+ uint64_t scsi_buflen;
buflen = 4096;
buf = (unsigned char *)malloc(buflen);
@@ -313,10 +318,12 @@ get_asymmetric_access_state(int fd, unsigned int tpg)
return -RTPG_RTPG_FAILED;
}
memset(buf, 0, buflen);
- rc = do_rtpg(fd, buf, buflen);
+ rc = do_rtpg(fd, buf, buflen, timeout);
if (rc < 0)
goto out;
scsi_buflen = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]) + 4;
+ if (scsi_buflen > UINT_MAX)
+ scsi_buflen = UINT_MAX;
if (buflen < scsi_buflen) {
free(buf);
buf = (unsigned char *)malloc(scsi_buflen);
@@ -327,7 +334,7 @@ get_asymmetric_access_state(int fd, unsigned int tpg)
}
buflen = scsi_buflen;
memset(buf, 0, buflen);
- rc = do_rtpg(fd, buf, buflen);
+ rc = do_rtpg(fd, buf, buflen, timeout);
if (rc < 0)
goto out;
}
@@ -350,4 +357,3 @@ out:
free(buf);
return rc;
}
-
diff --git a/libmultipath/prioritizers/alua_rtpg.h b/libmultipath/prioritizers/alua_rtpg.h
index 91a15a4..35cffaf 100644
--- a/libmultipath/prioritizers/alua_rtpg.h
+++ b/libmultipath/prioritizers/alua_rtpg.h
@@ -9,7 +9,7 @@
*
* Author(s): Jan Kunigk
* S. Bader <shbader@de.ibm.com>
- *
+ *
* This file is released under the GPL.
*/
#ifndef __RTPG_H__
@@ -22,9 +22,8 @@
#define RTPG_RTPG_FAILED 3
#define RTPG_TPG_NOT_FOUND 4
-int get_target_port_group_support(int fd);
-int get_target_port_group(struct path * pp);
-int get_asymmetric_access_state(int fd, unsigned int tpg);
+int get_target_port_group_support(int fd, unsigned int timeout);
+int get_target_port_group(struct path * pp, unsigned int timeout);
+int get_asymmetric_access_state(int fd, unsigned int tpg, unsigned int timeout);
#endif /* __RTPG_H__ */
-
diff --git a/libmultipath/prioritizers/alua_spc3.h b/libmultipath/prioritizers/alua_spc3.h
index e78b6c3..4d4969b 100644
--- a/libmultipath/prioritizers/alua_spc3.h
+++ b/libmultipath/prioritizers/alua_spc3.h
@@ -9,7 +9,7 @@
*
* Author(s): Jan Kunigk
* S. Bader <shbader@de.ibm.com>
- *
+ *
* This file is released under the GPL.
*/
#ifndef __SPC3_H__
@@ -323,4 +323,3 @@ struct rtpg_data {
)
#endif /* __SPC3_H__ */
-
diff --git a/libmultipath/prioritizers/const.c b/libmultipath/prioritizers/const.c
index bf689cd..9d9d003 100644
--- a/libmultipath/prioritizers/const.c
+++ b/libmultipath/prioritizers/const.c
@@ -1,6 +1,6 @@
#include <stdio.h>
-#include <prio.h>
+#include "prio.h"
int getprio (struct path * pp, char * args)
{
diff --git a/libmultipath/prioritizers/datacore.c b/libmultipath/prioritizers/datacore.c
index e3e6a51..050a94c 100644
--- a/libmultipath/prioritizers/datacore.c
+++ b/libmultipath/prioritizers/datacore.c
@@ -21,10 +21,10 @@
#include <sys/ioctl.h>
#include <sys/stat.h>
-#include <sg_include.h>
-#include <debug.h>
-#include <prio.h>
-#include <structs.h>
+#include "sg_include.h"
+#include "debug.h"
+#include "prio.h"
+#include "structs.h"
#define INQ_REPLY_LEN 255
#define INQ_CMD_CODE 0x12
@@ -46,7 +46,7 @@ int datacore_prio (const char *dev, int sg_fd, char * args)
unsigned char sense_buffer[32];
sg_io_hdr_t io_hdr;
- int timeout = 2000;
+ int timeout = 2000;
char preferredsds_buff[255] = "";
char * preferredsds = &preferredsds_buff[0];
@@ -56,7 +56,7 @@ int datacore_prio (const char *dev, int sg_fd, char * args)
}
if (sscanf(args, "timeout=%i preferredsds=%s",
- &timeout, preferredsds) == 2) {}
+ &timeout, preferredsds) == 2) {}
else if (sscanf(args, "preferredsds=%s timeout=%i",
preferredsds, &timeout) == 2) {}
else if (sscanf(args, "preferredsds=%s",
@@ -108,6 +108,5 @@ int datacore_prio (const char *dev, int sg_fd, char * args)
int getprio (struct path * pp, char * args)
{
- return datacore_prio(pp->dev, pp->fd, args);
+ return datacore_prio(pp->dev, pp->fd, args);
}
-
diff --git a/libmultipath/prioritizers/emc.c b/libmultipath/prioritizers/emc.c
index e49809c..a2f7487 100644
--- a/libmultipath/prioritizers/emc.c
+++ b/libmultipath/prioritizers/emc.c
@@ -2,17 +2,17 @@
#include <string.h>
#include <sys/ioctl.h>
-#include <sg_include.h>
-#include <debug.h>
-#include <prio.h>
-#include <structs.h>
+#include "sg_include.h"
+#include "debug.h"
+#include "prio.h"
+#include "structs.h"
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
#define pp_emc_log(prio, msg) condlog(prio, "%s: emc prio: " msg, dev)
-int emc_clariion_prio(const char *dev, int fd)
+int emc_clariion_prio(const char *dev, int fd, unsigned int timeout)
{
unsigned char sense_buffer[128];
unsigned char sb[128];
@@ -31,7 +31,7 @@ int emc_clariion_prio(const char *dev, int fd)
io_hdr.dxferp = sense_buffer;
io_hdr.cmdp = inqCmdBlk;
io_hdr.sbp = sb;
- io_hdr.timeout = get_prio_timeout(60000);
+ io_hdr.timeout = get_prio_timeout(timeout, 60000);
io_hdr.pack_id = 0;
if (ioctl(fd, SG_IO, &io_hdr) < 0) {
pp_emc_log(0, "sending query command failed");
@@ -81,7 +81,7 @@ out:
return(ret);
}
-int getprio (struct path * pp, char * args)
+int getprio (struct path * pp, char * args, unsigned int timeout)
{
- return emc_clariion_prio(pp->dev, pp->fd);
+ return emc_clariion_prio(pp->dev, pp->fd, timeout);
}
diff --git a/libmultipath/prioritizers/hds.c b/libmultipath/prioritizers/hds.c
index 8043b5b..d161e68 100644
--- a/libmultipath/prioritizers/hds.c
+++ b/libmultipath/prioritizers/hds.c
@@ -6,15 +6,15 @@
*
* Prioritizer for Device Mapper Multipath and HDS Storage
*
- * Hitachis Modular Storage contains two controllers for redundancy. The
- * Storage internal LUN (LDEV) will normally allocated via two pathes to the
- * server (one path per controller). For performance reasons should the server
+ * Hitachis Modular Storage contains two controllers for redundancy. The
+ * Storage internal LUN (LDEV) will normally allocated via two pathes to the
+ * server (one path per controller). For performance reasons should the server
* access to a LDEV only via one controller. The other path to the other
- * controller is stand-by. It is also possible to allocate more as one path
- * for a LDEV per controller. Here is active/active access allowed. The other
+ * controller is stand-by. It is also possible to allocate more as one path
+ * for a LDEV per controller. Here is active/active access allowed. The other
* pathes via the other controller are stand-by.
*
- * This prioritizer checks with inquiry command the represented LDEV and
+ * This prioritizer checks with inquiry command the represented LDEV and
* Controller number and gives back a priority followed by this scheme:
*
* CONTROLLER ODD and LDEV ODD: PRIORITY 1
@@ -22,19 +22,19 @@
* CONTROLLER EVEN and LDEV ODD: PRIORITY 0
* CONTROLLER EVEN and LDEV EVEN: PRIORITY 1
*
- * In the storage you can define for each LDEV a owner controller. If the
- * server makes IOs via the other controller the storage will switch the
- * ownership automatically. In this case you can see in the storage that the
+ * In the storage you can define for each LDEV a owner controller. If the
+ * server makes IOs via the other controller the storage will switch the
+ * ownership automatically. In this case you can see in the storage that the
* current controller is different from the default controller, but this is
* absolutely no problem.
*
- * With this prioritizer it is possible to establish a static load balancing.
- * Half of the LUNs are accessed via one HBA/storage controller and the other
+ * With this prioritizer it is possible to establish a static load balancing.
+ * Half of the LUNs are accessed via one HBA/storage controller and the other
* half via the other HBA/storage controller.
*
* In cluster environmemnts (RAC) it also guarantees that all cluster nodes have
* access to the LDEVs via the same controller.
- *
+ *
* You can run the prioritizer manually in verbose mode:
* # pp_hds_modular -v 8:224
* VENDOR: HITACHI
@@ -50,7 +50,7 @@
* Changes 2006-07-16:
* - Changed to forward declaration of functions
* - The switch-statement was changed to a logical expression
- * - unlinking of the devpath now also occurs at the end of
+ * - unlinking of the devpath now also occurs at the end of
* hds_modular_prio to avoid old /tmp/.pp_balance.%u.%u.devnode
* entries in /tmp-Directory
* - The for-statements for passing variables where changed to
@@ -72,19 +72,19 @@
#include <sys/ioctl.h>
#include <stdlib.h>
-#include <sg_include.h>
-#include <debug.h>
-#include <prio.h>
-#include <structs.h>
+#include "sg_include.h"
+#include "debug.h"
+#include "prio.h"
+#include "structs.h"
#define INQ_REPLY_LEN 255
#define INQ_CMD_CODE 0x12
#define INQ_CMD_LEN 6
#define pp_hds_log(prio, fmt, args...) \
- condlog(prio, "%s: hds prio: " fmt, dev, ##args)
+ condlog(prio, "%s: hds prio: " fmt, dev, ##args)
-int hds_modular_prio (const char *dev, int fd)
+int hds_modular_prio (const char *dev, int fd, unsigned int timeout)
{
int k;
char vendor[9];
@@ -114,7 +114,7 @@ int hds_modular_prio (const char *dev, int fd)
io_hdr.dxferp = inqBuff;
io_hdr.cmdp = inqCmdBlk;
io_hdr.sbp = sense_buffer;
- io_hdr.timeout = get_prio_timeout(2000); /* TimeOut = 2 seconds */
+ io_hdr.timeout = get_prio_timeout(timeout, 2000); /* TimeOut = 2 seconds */
if (ioctl (fd, SG_IO, &io_hdr) < 0) {
pp_hds_log(0, "SG_IO error");
@@ -151,6 +151,7 @@ int hds_modular_prio (const char *dev, int fd)
return 0;
break;
}
+ break;
case '1': case '3': case '5': case '7': case '9':
switch (ldev[3]) {
case '0': case '2': case '4': case '6': case '8': case 'A': case 'C': case 'E':
@@ -162,11 +163,12 @@ int hds_modular_prio (const char *dev, int fd)
return 1;
break;
}
+ break;
}
return -1;
}
-int getprio (struct path * pp, char * args)
+int getprio (struct path * pp, char * args, unsigned int timeout)
{
- return hds_modular_prio(pp->dev, pp->fd);
+ return hds_modular_prio(pp->dev, pp->fd, timeout);
}
diff --git a/libmultipath/prioritizers/hp_sw.c b/libmultipath/prioritizers/hp_sw.c
index 4950cf7..253fd51 100644
--- a/libmultipath/prioritizers/hp_sw.c
+++ b/libmultipath/prioritizers/hp_sw.c
@@ -12,10 +12,10 @@
#include <sys/ioctl.h>
#include <errno.h>
-#include <sg_include.h>
-#include <debug.h>
-#include <prio.h>
-#include <structs.h>
+#include "sg_include.h"
+#include "debug.h"
+#include "prio.h"
+#include "structs.h"
#define TUR_CMD_LEN 6
#define SCSI_CHECK_CONDITION 0x2
@@ -30,11 +30,11 @@
#define HP_PATH_FAILED 0x00
#define pp_hp_sw_log(prio, fmt, args...) \
- condlog(prio, "%s: hp_sw prio: " fmt, dev, ##args)
+ condlog(prio, "%s: hp_sw prio: " fmt, dev, ##args)
-int hp_sw_prio(const char *dev, int fd)
+int hp_sw_prio(const char *dev, int fd, unsigned int timeout)
{
- unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
+ unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
unsigned char sb[128];
struct sg_io_hdr io_hdr;
int ret = HP_PATH_FAILED;
@@ -46,37 +46,37 @@ 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 = get_prio_timeout(60000);
+ io_hdr.timeout = get_prio_timeout(timeout, 60000);
io_hdr.pack_id = 0;
retry:
if (ioctl(fd, SG_IO, &io_hdr) < 0) {
pp_hp_sw_log(0, "sending tur command failed");
goto out;
}
- io_hdr.status &= 0x7e;
- if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
- (0 == io_hdr.driver_status)) {
+ io_hdr.status &= 0x7e;
+ if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
+ (0 == io_hdr.driver_status)) {
/* Command completed normally, path is active */
- ret = HP_PATH_ACTIVE;
+ ret = HP_PATH_ACTIVE;
}
- if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
- (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
- (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
- if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
- int sense_key, asc, asq;
- unsigned char * sense_buffer = io_hdr.sbp;
- if (sense_buffer[0] & 0x2) {
- sense_key = sense_buffer[1] & 0xf;
+ if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
+ (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
+ (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
+ if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
+ int sense_key, asc, asq;
+ unsigned char * sense_buffer = io_hdr.sbp;
+ if (sense_buffer[0] & 0x2) {
+ sense_key = sense_buffer[1] & 0xf;
asc = sense_buffer[2];
asq = sense_buffer[3];
} else {
- sense_key = sense_buffer[2] & 0xf;
+ sense_key = sense_buffer[2] & 0xf;
asc = sense_buffer[12];
asq = sense_buffer[13];
}
- if(RECOVERED_ERROR == sense_key)
- ret = HP_PATH_ACTIVE;
+ if(RECOVERED_ERROR == sense_key)
+ ret = HP_PATH_ACTIVE;
if(NOT_READY == sense_key) {
if (asc == 0x04 && asq == 0x02) {
/* This is a standby path */
@@ -89,13 +89,13 @@ int hp_sw_prio(const char *dev, int fd)
goto retry;
}
}
- }
- }
+ }
+ }
out:
return(ret);
}
-int getprio (struct path * pp, char * args)
+int getprio (struct path * pp, char * args, unsigned int timeout)
{
- return hp_sw_prio(pp->dev, pp->fd);
+ return hp_sw_prio(pp->dev, pp->fd, timeout);
}
diff --git a/libmultipath/prioritizers/iet.c b/libmultipath/prioritizers/iet.c
index 0bcc48b..aa852a0 100644
--- a/libmultipath/prioritizers/iet.c
+++ b/libmultipath/prioritizers/iet.c
@@ -5,10 +5,10 @@
#include <stdio.h>
#include <string.h>
#include <regex.h>
-#include <prio.h>
-#include <debug.h>
+#include "prio.h"
+#include "debug.h"
#include <unistd.h>
-#include <structs.h>
+#include "structs.h"
//
// This prioritizer suits iSCSI needs, makes it possible to prefer one path.
@@ -16,7 +16,7 @@
// (It's a bit of a misnomer since supports the client side [eg. open-iscsi]
// instead of just "iet".)
//
-// Usage:
+// Usage:
// prio "iet"
// prio_args "preferredip=10.11.12.13"
//
@@ -59,10 +59,11 @@ char *find_regex(char * string, char * regex)
if (result) {
strncpy(result, &string[start], size);
result[size] = '\0';
+ free(pmatch);
return result;
}
}
- else return NULL;
+ free(pmatch);
}
}
return NULL;
diff --git a/libmultipath/prioritizers/ontap.c b/libmultipath/prioritizers/ontap.c
index 5e82a17..747dfb5 100644
--- a/libmultipath/prioritizers/ontap.c
+++ b/libmultipath/prioritizers/ontap.c
@@ -19,10 +19,10 @@
#include <errno.h>
#include <assert.h>
-#include <sg_include.h>
-#include <debug.h>
-#include <prio.h>
-#include <structs.h>
+#include "sg_include.h"
+#include "debug.h"
+#include "prio.h"
+#include "structs.h"
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
@@ -31,7 +31,7 @@
#define SG_TIMEOUT 60000
#define pp_ontap_log(prio, fmt, args...) \
- condlog(prio, "%s: ontap prio: " fmt, dev, ##args)
+ condlog(prio, "%s: ontap prio: " fmt, dev, ##args)
static void dump_cdb(unsigned char *cdb, int size)
{
@@ -71,7 +71,8 @@ static void process_sg_error(struct sg_io_hdr *io_hdr)
* 0: success
*/
static int send_gva(const char *dev, int fd, unsigned char pg,
- unsigned char *results, int *results_size)
+ unsigned char *results, int *results_size,
+ unsigned int timeout)
{
unsigned char sb[128];
unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa,
@@ -89,7 +90,7 @@ static int send_gva(const char *dev, int fd, unsigned char pg,
io_hdr.dxferp = results;
io_hdr.cmdp = cdb;
io_hdr.sbp = sb;
- io_hdr.timeout = get_prio_timeout(SG_TIMEOUT);
+ io_hdr.timeout = get_prio_timeout(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);
@@ -122,7 +123,7 @@ static int send_gva(const char *dev, int fd, unsigned char pg,
* 0: Device _not_ proxy path
* 1: Device _is_ proxy path
*/
-static int get_proxy(const char *dev, int fd)
+static int get_proxy(const char *dev, int fd, unsigned int timeout)
{
unsigned char results[256];
unsigned char sb[128];
@@ -141,7 +142,7 @@ static int get_proxy(const char *dev, int fd)
io_hdr.dxferp = results;
io_hdr.cmdp = cdb;
io_hdr.sbp = sb;
- io_hdr.timeout = get_prio_timeout(SG_TIMEOUT);
+ io_hdr.timeout = get_prio_timeout(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, "
@@ -182,7 +183,7 @@ static int get_proxy(const char *dev, int fd)
* 2: iSCSI software
* 1: FCP proxy
*/
-static int ontap_prio(const char *dev, int fd)
+static int ontap_prio(const char *dev, int fd, unsigned int timeout)
{
unsigned char results[RESULTS_MAX];
int results_size=RESULTS_MAX;
@@ -195,7 +196,7 @@ static int ontap_prio(const char *dev, int fd)
is_iscsi_software = is_iscsi_hardware = is_proxy = 0;
memset(&results, 0, sizeof (results));
- rc = send_gva(dev, fd, 0x41, results, &results_size);
+ rc = send_gva(dev, fd, 0x41, results, &results_size, timeout);
if (rc >= 0) {
tot_len = results[0] << 24 | results[1] << 16 |
results[2] << 8 | results[3];
@@ -221,7 +222,7 @@ static int ontap_prio(const char *dev, int fd)
}
try_fcp_proxy:
- rc = get_proxy(dev, fd);
+ rc = get_proxy(dev, fd, timeout);
if (rc >= 0) {
is_proxy = rc;
}
@@ -241,7 +242,7 @@ static int ontap_prio(const char *dev, int fd)
}
}
-int getprio (struct path * pp, char * args)
+int getprio (struct path * pp, char * args, unsigned int timeout)
{
- return ontap_prio(pp->dev, pp->fd);
+ return ontap_prio(pp->dev, pp->fd, timeout);
}
diff --git a/libmultipath/prioritizers/random.c b/libmultipath/prioritizers/random.c
index 281a0d1..c3ea3ac 100644
--- a/libmultipath/prioritizers/random.c
+++ b/libmultipath/prioritizers/random.c
@@ -3,7 +3,7 @@
#include <sys/time.h>
#include <time.h>
-#include <prio.h>
+#include "prio.h"
int getprio (struct path * pp, char * args)
{
diff --git a/libmultipath/prioritizers/rdac.c b/libmultipath/prioritizers/rdac.c
index a210055..f5df032 100644
--- a/libmultipath/prioritizers/rdac.c
+++ b/libmultipath/prioritizers/rdac.c
@@ -2,17 +2,17 @@
#include <string.h>
#include <sys/ioctl.h>
-#include <sg_include.h>
-#include <debug.h>
-#include <prio.h>
-#include <structs.h>
+#include "sg_include.h"
+#include "debug.h"
+#include "prio.h"
+#include "structs.h"
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
#define pp_rdac_log(prio, msg) condlog(prio, "%s: rdac prio: " msg, dev)
-int rdac_prio(const char *dev, int fd)
+int rdac_prio(const char *dev, int fd, unsigned int timeout)
{
unsigned char sense_buffer[128];
unsigned char sb[128];
@@ -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 = get_prio_timeout(60000);
+ io_hdr.timeout = get_prio_timeout(timeout, 60000);
io_hdr.pack_id = 0;
if (ioctl(fd, SG_IO, &io_hdr) < 0) {
pp_rdac_log(0, "sending inquiry command failed");
@@ -91,7 +91,7 @@ out:
return(ret);
}
-int getprio (struct path * pp, char * args)
+int getprio (struct path * pp, char * args, unsigned int timeout)
{
- return rdac_prio(pp->dev, pp->fd);
+ return rdac_prio(pp->dev, pp->fd, timeout);
}
diff --git a/libmultipath/prioritizers/sysfs.c b/libmultipath/prioritizers/sysfs.c
new file mode 100644
index 0000000..ff567df
--- /dev/null
+++ b/libmultipath/prioritizers/sysfs.c
@@ -0,0 +1,61 @@
+/*
+ * sysfs.c
+ *
+ * Copyright(c) 2016 Hannes Reinecke, SUSE Linux GmbH
+ */
+
+#include <stdio.h>
+
+#include "structs.h"
+#include "discovery.h"
+#include "prio.h"
+
+static const struct {
+ unsigned char value;
+ char *name;
+} sysfs_access_state_map[] = {
+ { 50, "active/optimized" },
+ { 10, "active/non-optimized" },
+ { 5, "lba-dependent" },
+ { 1, "standby" },
+};
+
+int get_exclusive_pref_arg(char *args)
+{
+ char *ptr;
+
+ if (args == NULL)
+ return 0;
+ ptr = strstr(args, "exclusive_pref_bit");
+ if (!ptr)
+ return 0;
+ if (ptr[18] != '\0' && ptr[18] != ' ' && ptr[18] != '\t')
+ return 0;
+ if (ptr != args && ptr[-1] != ' ' && ptr[-1] != '\t')
+ return 0;
+ return 1;
+}
+
+int getprio (struct path * pp, char * args, unsigned int timeout)
+{
+ int prio = 0, rc, i;
+ char buff[512];
+ int exclusive_pref;
+
+ exclusive_pref = get_exclusive_pref_arg(args);
+ rc = sysfs_get_asymmetric_access_state(pp, buff, 512);
+ if (rc < 0)
+ return PRIO_UNDEF;
+ prio = 0;
+ for (i = 0; i < 4; i++) {
+ if (!strncmp(buff, sysfs_access_state_map[i].name,
+ strlen(sysfs_access_state_map[i].name))) {
+ prio = sysfs_access_state_map[i].value;
+ break;
+ }
+ }
+ if (rc > 0 && (prio != 50 || exclusive_pref))
+ prio += 80;
+
+ return prio;
+}
diff --git a/libmultipath/prioritizers/weightedpath.c b/libmultipath/prioritizers/weightedpath.c
index ba8c555..e8168fe 100644
--- a/libmultipath/prioritizers/weightedpath.c
+++ b/libmultipath/prioritizers/weightedpath.c
@@ -25,15 +25,15 @@
#include <stdio.h>
#include <string.h>
-#include <prio.h>
+#include "prio.h"
#include "weightedpath.h"
-#include <config.h>
-#include <structs.h>
-#include <memory.h>
-#include <debug.h>
+#include "config.h"
+#include "structs.h"
+#include "memory.h"
+#include "debug.h"
#include <regex.h>
-#include <structs_vec.h>
-#include <print.h>
+#include "structs_vec.h"
+#include "print.h"
char *get_next_string(char **temp, char *split_char)
{
@@ -140,4 +140,3 @@ int getprio(struct path *pp, char *args)
{
return prio_path_weight(pp, args);
}
-
diff --git a/libmultipath/propsel.c b/libmultipath/propsel.c
index 8abe360..0caf269 100644
--- a/libmultipath/propsel.c
+++ b/libmultipath/propsel.c
@@ -82,7 +82,7 @@ do_attr_set(var, mp->mpe, shift, "(LUN setting)")
do_attr_set(var, conf, shift, "(config file default)")
extern int
-select_mode (struct multipath *mp)
+select_mode (struct config *conf, struct multipath *mp)
{
char *origin;
@@ -96,7 +96,7 @@ out:
}
extern int
-select_uid (struct multipath *mp)
+select_uid (struct config *conf, struct multipath *mp)
{
char *origin;
@@ -110,7 +110,7 @@ out:
}
extern int
-select_gid (struct multipath *mp)
+select_gid (struct config *conf, struct multipath *mp)
{
char *origin;
@@ -129,7 +129,7 @@ out:
* stop at first explicit setting found
*/
extern int
-select_rr_weight (struct multipath * mp)
+select_rr_weight (struct config *conf, struct multipath * mp)
{
char *origin, buff[13];
@@ -145,7 +145,7 @@ out:
}
extern int
-select_pgfailback (struct multipath * mp)
+select_pgfailback (struct config *conf, struct multipath * mp)
{
char *origin, buff[13];
@@ -161,7 +161,7 @@ out:
}
extern int
-select_pgpolicy (struct multipath * mp)
+select_pgpolicy (struct config *conf, struct multipath * mp)
{
char *origin, buff[POLICY_NAME_SIZE];
@@ -183,7 +183,7 @@ out:
}
extern int
-select_selector (struct multipath * mp)
+select_selector (struct config *conf, struct multipath * mp)
{
char *origin;
@@ -200,7 +200,7 @@ out:
}
static void
-select_alias_prefix (struct multipath * mp)
+select_alias_prefix (struct config *conf, struct multipath * mp)
{
char *origin;
@@ -214,7 +214,7 @@ out:
}
static int
-want_user_friendly_names(struct multipath * mp)
+want_user_friendly_names(struct config *conf, struct multipath * mp)
{
char *origin;
@@ -237,7 +237,7 @@ out:
}
extern int
-select_alias (struct multipath * mp)
+select_alias (struct config *conf, struct multipath * mp)
{
char *origin = NULL;
@@ -248,10 +248,10 @@ select_alias (struct multipath * mp)
}
mp->alias = NULL;
- if (!want_user_friendly_names(mp))
+ if (!want_user_friendly_names(conf, mp))
goto out;
- select_alias_prefix(mp);
+ select_alias_prefix(conf, mp);
if (strlen(mp->alias_old) > 0) {
mp->alias = use_existing_alias(mp->wwid, conf->bindings_file,
@@ -277,7 +277,7 @@ out:
}
extern int
-select_features (struct multipath * mp)
+select_features (struct config *conf, struct multipath * mp)
{
char *origin;
@@ -303,7 +303,7 @@ out:
}
extern int
-select_hwhandler (struct multipath * mp)
+select_hwhandler (struct config *conf, struct multipath * mp)
{
char *origin;
@@ -318,7 +318,7 @@ out:
}
extern int
-select_checker(struct path *pp)
+select_checker(struct config *conf, struct path *pp)
{
char *origin, *checker_name;
struct checker * c = &pp->checker;
@@ -328,7 +328,7 @@ select_checker(struct path *pp)
do_set(checker_name, conf, checker_name, "(config file setting)");
do_default(checker_name, DEFAULT_CHECKER);
out:
- checker_get(c, checker_name);
+ checker_get(conf->multipath_dir, c, checker_name);
condlog(3, "%s: path_checker = %s %s", pp->dev, c->name, origin);
if (conf->checker_timeout) {
c->timeout = conf->checker_timeout;
@@ -347,7 +347,7 @@ out:
}
extern int
-select_getuid (struct path * pp)
+select_getuid (struct config *conf, struct path * pp)
{
char *origin;
@@ -369,52 +369,57 @@ out:
}
void
-detect_prio(struct path * pp)
+detect_prio(struct config *conf, struct path * pp)
{
int ret;
struct prio *p = &pp->prio;
int tpgs = 0;
+ unsigned int timeout = conf->checker_timeout;
+ char buff[512];
+ char *default_prio = PRIO_ALUA;
- if ((tpgs = get_target_port_group_support(pp->fd)) <= 0)
+ if ((tpgs = get_target_port_group_support(pp->fd, timeout)) <= 0)
return;
pp->tpgs = tpgs;
- ret = get_target_port_group(pp);
+ ret = get_target_port_group(pp, timeout);
if (ret < 0)
return;
- if (get_asymmetric_access_state(pp->fd, ret) < 0)
+ if (get_asymmetric_access_state(pp->fd, ret, timeout) < 0)
return;
- prio_get(p, PRIO_ALUA, DEFAULT_PRIO_ARGS);
+ if (sysfs_get_asymmetric_access_state(pp, buff, 512) >= 0)
+ default_prio = PRIO_SYSFS;
+ prio_get(conf->multipath_dir, p, default_prio, DEFAULT_PRIO_ARGS);
}
-#define set_prio(src, msg) \
+#define set_prio(dir, src, msg) \
do { \
if (src && src->prio_name) { \
- prio_get(p, src->prio_name, src->prio_args); \
+ prio_get(dir, p, src->prio_name, src->prio_args); \
origin = msg; \
goto out; \
} \
} while(0)
extern int
-select_prio (struct path * pp)
+select_prio (struct config *conf, struct path * pp)
{
char *origin;
struct mpentry * mpe;
struct prio * p = &pp->prio;
if (pp->detect_prio == DETECT_PRIO_ON) {
- detect_prio(pp);
+ detect_prio(conf, pp);
if (prio_selected(p)) {
origin = "(detected setting)";
goto out;
}
}
- mpe = find_mpe(pp->wwid);
- set_prio(mpe, "(LUN setting)");
- set_prio(conf->overrides, "(overrides setting)");
- set_prio(pp->hwe, "controller setting)");
- set_prio(conf, "(config file default)");
- prio_get(p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS);
+ mpe = find_mpe(conf->mptable, pp->wwid);
+ set_prio(conf->multipath_dir, mpe, "(LUN setting)");
+ set_prio(conf->multipath_dir, conf->overrides, "(overrides setting)");
+ set_prio(conf->multipath_dir, pp->hwe, "controller setting)");
+ set_prio(conf->multipath_dir, conf, "(config file default)");
+ prio_get(conf->multipath_dir, p, DEFAULT_PRIO, DEFAULT_PRIO_ARGS);
origin = "(internal default)";
out:
/*
@@ -422,8 +427,10 @@ out:
*/
if (!strncmp(prio_name(p), PRIO_ALUA, PRIO_NAME_LEN)) {
int tpgs = 0;
- if(!pp->tpgs &&
- (tpgs = get_target_port_group_support(pp->fd)) >= 0)
+ unsigned int timeout = conf->checker_timeout;
+
+ if(!pp->tpgs &&
+ (tpgs = get_target_port_group_support(pp->fd, timeout)) >= 0)
pp->tpgs = tpgs;
}
condlog(3, "%s: prio = %s %s", pp->dev, prio_name(p), origin);
@@ -432,7 +439,7 @@ out:
}
extern int
-select_no_path_retry(struct multipath *mp)
+select_no_path_retry(struct config *conf, struct multipath *mp)
{
char *origin = NULL;
char buff[12];
@@ -461,7 +468,7 @@ out:
}
int
-select_minio_rq (struct multipath * mp)
+select_minio_rq (struct config *conf, struct multipath * mp)
{
char *origin;
@@ -476,7 +483,7 @@ out:
}
int
-select_minio_bio (struct multipath * mp)
+select_minio_bio (struct config *conf, struct multipath * mp)
{
char *origin;
@@ -491,18 +498,18 @@ out:
}
extern int
-select_minio (struct multipath * mp)
+select_minio (struct config *conf, struct multipath * mp)
{
unsigned int minv_dmrq[3] = {1, 1, 0};
if (VERSION_GE(conf->version, minv_dmrq))
- return select_minio_rq(mp);
+ return select_minio_rq(conf, mp);
else
- return select_minio_bio(mp);
+ return select_minio_bio(conf, mp);
}
extern int
-select_fast_io_fail(struct multipath *mp)
+select_fast_io_fail(struct config *conf, struct multipath *mp)
{
char *origin, buff[12];
@@ -517,7 +524,7 @@ out:
}
extern int
-select_dev_loss(struct multipath *mp)
+select_dev_loss(struct config *conf, struct multipath *mp)
{
char *origin, buff[12];
@@ -533,7 +540,7 @@ out:
}
extern int
-select_flush_on_last_del(struct multipath *mp)
+select_flush_on_last_del(struct config *conf, struct multipath *mp)
{
char *origin;
@@ -551,7 +558,7 @@ out:
}
extern int
-select_reservation_key (struct multipath * mp)
+select_reservation_key (struct config *conf, struct multipath * mp)
{
char *origin, buff[12];
@@ -566,7 +573,7 @@ out:
}
extern int
-select_retain_hwhandler (struct multipath * mp)
+select_retain_hwhandler (struct config *conf, struct multipath * mp)
{
char *origin;
unsigned int minv_dm_retain[3] = {1, 5, 0};
@@ -588,7 +595,7 @@ out:
}
extern int
-select_detect_prio (struct path * pp)
+select_detect_prio (struct config *conf, struct path * pp)
{
char *origin;
@@ -603,7 +610,7 @@ out:
}
extern int
-select_deferred_remove (struct multipath *mp)
+select_deferred_remove (struct config *conf, struct multipath *mp)
{
char *origin;
@@ -629,7 +636,7 @@ out:
}
extern int
-select_delay_watch_checks(struct multipath *mp)
+select_delay_watch_checks(struct config *conf, struct multipath *mp)
{
char *origin, buff[12];
@@ -645,7 +652,7 @@ out:
}
extern int
-select_delay_wait_checks(struct multipath *mp)
+select_delay_wait_checks(struct config *conf, struct multipath *mp)
{
char *origin, buff[12];
diff --git a/libmultipath/propsel.h b/libmultipath/propsel.h
index f9598e7..5941a5f 100644
--- a/libmultipath/propsel.h
+++ b/libmultipath/propsel.h
@@ -1,24 +1,24 @@
-int select_rr_weight (struct multipath * mp);
-int select_pgfailback (struct multipath * mp);
-int select_pgpolicy (struct multipath * mp);
-int select_selector (struct multipath * mp);
-int select_alias (struct multipath * mp);
-int select_features (struct multipath * mp);
-int select_hwhandler (struct multipath * mp);
-int select_checker(struct path *pp);
-int select_getuid (struct path * pp);
-int select_prio (struct path * pp);
-int select_no_path_retry(struct multipath *mp);
-int select_flush_on_last_del(struct multipath *mp);
-int select_minio(struct multipath *mp);
-int select_mode(struct multipath *mp);
-int select_uid(struct multipath *mp);
-int select_gid(struct multipath *mp);
-int select_fast_io_fail(struct multipath *mp);
-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);
-int select_delay_watch_checks (struct multipath * mp);
-int select_delay_wait_checks (struct multipath * mp);
+int select_rr_weight (struct config *conf, struct multipath * mp);
+int select_pgfailback (struct config *conf, struct multipath * mp);
+int select_pgpolicy (struct config *conf, struct multipath * mp);
+int select_selector (struct config *conf, struct multipath * mp);
+int select_alias (struct config *conf, struct multipath * mp);
+int select_features (struct config *conf, struct multipath * mp);
+int select_hwhandler (struct config *conf, struct multipath * mp);
+int select_checker(struct config *conf, struct path *pp);
+int select_getuid (struct config *conf, struct path * pp);
+int select_prio (struct config *conf, struct path * pp);
+int select_no_path_retry(struct config *conf, struct multipath *mp);
+int select_flush_on_last_del(struct config *conf, struct multipath *mp);
+int select_minio(struct config *conf, struct multipath *mp);
+int select_mode(struct config *conf, struct multipath *mp);
+int select_uid(struct config *conf, struct multipath *mp);
+int select_gid(struct config *conf, struct multipath *mp);
+int select_fast_io_fail(struct config *conf, struct multipath *mp);
+int select_dev_loss(struct config *conf, struct multipath *mp);
+int select_reservation_key(struct config *conf, struct multipath *mp);
+int select_retain_hwhandler (struct config *conf, struct multipath * mp);
+int select_detect_prio(struct config *conf, struct path * pp);
+int select_deferred_remove(struct config *conf, struct multipath *mp);
+int select_delay_watch_checks (struct config *conf, struct multipath * mp);
+int select_delay_wait_checks (struct config *conf, struct multipath * mp);
diff --git a/libmultipath/structs.c b/libmultipath/structs.c
index 502d98e..fee58e5 100644
--- a/libmultipath/structs.c
+++ b/libmultipath/structs.c
@@ -653,9 +653,11 @@ remove_feature(char **f, char *o)
* about to be removed
*/
p = strchr(*f, ' ');
- if (!p)
+ if (!p) {
/* Internal error, feature string inconsistent */
+ FREE(n);
return 1;
+ }
while (*p == ' ')
p++;
p--;
@@ -687,4 +689,3 @@ out:
return 0;
}
-
diff --git a/libmultipath/structs.h b/libmultipath/structs.h
index ab7dc25..9f216df 100644
--- a/libmultipath/structs.h
+++ b/libmultipath/structs.h
@@ -272,7 +272,7 @@ struct multipath {
/* checkers shared data */
void * mpcontext;
-
+
/* persistent management data*/
unsigned char * reservation_key;
unsigned char prflag;
@@ -328,7 +328,7 @@ struct multipath * find_mp_by_alias (vector mp, char * alias);
struct multipath * find_mp_by_wwid (vector mp, char * wwid);
struct multipath * find_mp_by_str (vector mp, char * wwid);
struct multipath * find_mp_by_minor (vector mp, int minor);
-
+
struct path * find_path_by_devt (vector pathvec, char * devt);
struct path * find_path_by_dev (vector pathvec, char * dev);
struct path * first_path (struct multipath * mpp);
diff --git a/libmultipath/structs_vec.c b/libmultipath/structs_vec.c
index 7d46d42..adb1911 100644
--- a/libmultipath/structs_vec.c
+++ b/libmultipath/structs_vec.c
@@ -6,13 +6,13 @@
#include "vector.h"
#include "defaults.h"
#include "debug.h"
+#include "config.h"
#include "structs.h"
#include "structs_vec.h"
#include "sysfs.h"
#include "waiter.h"
#include "devmapper.h"
#include "dmparser.h"
-#include "config.h"
#include "propsel.h"
#include "discovery.h"
#include "prio.h"
@@ -48,8 +48,9 @@ update_mpp_paths(struct multipath * mpp, vector pathvec)
extern int
adopt_paths (vector pathvec, struct multipath * mpp)
{
- int i;
+ int i, ret;
struct path * pp;
+ struct config *conf;
if (!mpp)
return 0;
@@ -69,8 +70,11 @@ adopt_paths (vector pathvec, struct multipath * mpp)
if (!find_path_by_dev(mpp->paths, pp->dev) &&
store_path(mpp->paths, pp))
return 1;
- if (pathinfo(pp, conf->hwtable,
- DI_PRIO | DI_CHECKER))
+ conf = get_multipath_config();
+ ret = pathinfo(pp, conf,
+ DI_PRIO | DI_CHECKER);
+ put_multipath_config(conf);
+ if (ret)
return 1;
}
}
@@ -237,9 +241,12 @@ extract_hwe_from_path(struct multipath * mpp)
condlog(3, "%s: product = %s", pp->dev, pp->product_id);
condlog(3, "%s: rev = %s", pp->dev, pp->rev);
if (!pp->hwe) {
+ struct config *conf = get_multipath_config();
+
condlog(3, "searching hwtable");
pp->hwe = find_hwe(conf->hwtable, pp->vendor_id,
pp->product_id, pp->rev);
+ put_multipath_config(conf);
}
}
@@ -247,7 +254,7 @@ extract_hwe_from_path(struct multipath * mpp)
}
static int
-update_multipath_table (struct multipath *mpp, vector pathvec)
+update_multipath_table (struct multipath *mpp, vector pathvec, int is_daemon)
{
char params[PARAMS_SIZE] = {0};
@@ -259,7 +266,7 @@ update_multipath_table (struct multipath *mpp, vector pathvec)
return 1;
}
- if (disassemble_map(pathvec, params, mpp)) {
+ if (disassemble_map(pathvec, params, mpp, is_daemon)) {
condlog(3, "%s: cannot disassemble map", mpp->alias);
return 1;
}
@@ -314,7 +321,7 @@ void sync_paths(struct multipath *mpp, vector pathvec)
}
extern int
-update_multipath_strings (struct multipath *mpp, vector pathvec)
+update_multipath_strings (struct multipath *mpp, vector pathvec, int is_daemon)
{
if (!mpp)
return 1;
@@ -326,7 +333,7 @@ update_multipath_strings (struct multipath *mpp, vector pathvec)
free_pgvec(mpp->pg, KEEP_PATHS);
mpp->pg = NULL;
- if (update_multipath_table(mpp, pathvec))
+ if (update_multipath_table(mpp, pathvec, is_daemon))
return 1;
sync_paths(mpp, pathvec);
@@ -337,11 +344,11 @@ update_multipath_strings (struct multipath *mpp, vector pathvec)
}
extern void
-set_no_path_retry(struct multipath *mpp)
+set_no_path_retry(struct config *conf, struct multipath *mpp)
{
mpp->retry_tick = 0;
mpp->nr_active = pathcount(mpp, PATH_UP) + pathcount(mpp, PATH_GHOST);
- select_no_path_retry(mpp);
+ select_no_path_retry(conf, mpp);
switch (mpp->no_path_retry) {
case NO_PATH_RETRY_UNDEF:
@@ -355,18 +362,23 @@ set_no_path_retry(struct multipath *mpp)
default:
dm_queue_if_no_path(mpp->alias, 1);
if (mpp->nr_active == 0) {
+ struct config *conf = get_multipath_config();
/* Enter retry mode */
mpp->retry_tick = mpp->no_path_retry * conf->checkint;
condlog(1, "%s: Entering recovery mode: max_retries=%d",
mpp->alias, mpp->no_path_retry);
+ put_multipath_config(conf);
}
break;
}
}
extern int
-__setup_multipath (struct vectors * vecs, struct multipath * mpp, int reset)
+__setup_multipath (struct vectors * vecs, struct multipath * mpp,
+ int reset, int is_daemon)
{
+ struct config *conf;
+
if (dm_get_info(mpp->alias, &mpp->dmi)) {
/* Error accessing table */
condlog(3, "%s: cannot access table", mpp->alias);
@@ -379,13 +391,15 @@ __setup_multipath (struct vectors * vecs, struct multipath * mpp, int reset)
goto out;
}
- if (update_multipath_strings(mpp, vecs->pathvec)) {
+ if (update_multipath_strings(mpp, vecs->pathvec, is_daemon)) {
condlog(0, "%s: failed to setup multipath", mpp->alias);
goto out;
}
set_multipath_wwid(mpp);
- mpp->mpe = find_mpe(mpp->wwid);
+ conf = get_multipath_config();
+ mpp->mpe = find_mpe(conf->mptable, mpp->wwid);
+ put_multipath_config(conf);
condlog(3, "%s: discover", mpp->alias);
if (!mpp->hwe)
@@ -395,10 +409,10 @@ __setup_multipath (struct vectors * vecs, struct multipath * mpp, int reset)
mpp->alias);
}
if (reset) {
- select_rr_weight(mpp);
- select_pgfailback(mpp);
- set_no_path_retry(mpp);
- select_flush_on_last_del(mpp);
+ select_rr_weight(conf, mpp);
+ select_pgfailback(conf, mpp);
+ set_no_path_retry(conf, mpp);
+ select_flush_on_last_del(conf, mpp);
if (VECTOR_SIZE(mpp->paths) != 0)
dm_cancel_deferred_remove(mpp);
}
@@ -414,8 +428,12 @@ add_map_without_path (struct vectors * vecs, char * alias)
{
struct multipath * mpp = alloc_multipath();
- if (!mpp || !alias)
+ if (!mpp)
+ return NULL;
+ if (!alias) {
+ FREE(mpp);
return NULL;
+ }
mpp->alias = STRDUP(alias);
@@ -447,8 +465,8 @@ find_existing_alias (struct multipath * mpp,
int i;
vector_foreach_slot (vecs->mpvec, mp, i)
- if (strcmp(mp->wwid, mpp->wwid) == 0) {
- strncpy(mpp->alias_old, mp->alias, WWID_SIZE);
+ if (strncmp(mp->wwid, mpp->wwid, WWID_SIZE - 1) == 0) {
+ strncpy(mpp->alias_old, mp->alias, WWID_SIZE - 1);
return;
}
}
@@ -458,6 +476,7 @@ add_map_with_path (struct vectors * vecs,
struct path * pp, int add_vec)
{
struct multipath * mpp;
+ struct config *conf = NULL;
if (!strlen(pp->wwid))
return NULL;
@@ -465,12 +484,14 @@ add_map_with_path (struct vectors * vecs,
if (!(mpp = alloc_multipath()))
return NULL;
- mpp->mpe = find_mpe(pp->wwid);
+ conf = get_multipath_config();
+ mpp->mpe = find_mpe(conf->mptable, pp->wwid);
mpp->hwe = pp->hwe;
+ put_multipath_config(conf);
strcpy(mpp->wwid, pp->wwid);
find_existing_alias(mpp, vecs);
- if (select_alias(mpp))
+ if (select_alias(conf, mpp))
goto out;
mpp->size = pp->size;
@@ -544,7 +565,7 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset)
return 2;
}
- if (__setup_multipath(vecs, mpp, reset))
+ if (__setup_multipath(vecs, mpp, reset, 1))
return 1; /* mpp freed in setup_multipath */
/*
@@ -556,6 +577,7 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset)
continue;
if (pp->state != PATH_DOWN) {
+ struct config *conf = get_multipath_config();
int oldstate = pp->state;
condlog(2, "%s: mark as failed", pp->dev);
mpp->stat_path_failures++;
@@ -570,6 +592,7 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset)
*/
if (pp->tick > conf->checkint)
pp->tick = conf->checkint;
+ put_multipath_config(conf);
}
}
}
@@ -586,6 +609,8 @@ int update_multipath (struct vectors *vecs, char *mapname, int reset)
void update_queue_mode_del_path(struct multipath *mpp)
{
if (--mpp->nr_active == 0 && mpp->no_path_retry > 0) {
+ struct config *conf = get_multipath_config();
+
/*
* Enter retry mode.
* meaning of +1: retry_tick may be decremented in
@@ -595,6 +620,7 @@ void update_queue_mode_del_path(struct multipath *mpp)
mpp->retry_tick = mpp->no_path_retry * conf->checkint + 1;
condlog(1, "%s: Entering recovery mode: max_retries=%d",
mpp->alias, mpp->no_path_retry);
+ put_multipath_config(conf);
}
condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
}
@@ -610,4 +636,3 @@ void update_queue_mode_add_path(struct multipath *mpp)
}
condlog(2, "%s: remaining active paths: %d", mpp->alias, mpp->nr_active);
}
-
diff --git a/libmultipath/structs_vec.h b/libmultipath/structs_vec.h
index 2e06beb..8ef547d 100644
--- a/libmultipath/structs_vec.h
+++ b/libmultipath/structs_vec.h
@@ -1,6 +1,8 @@
#ifndef _STRUCTS_VEC_H
#define _STRUCTS_VEC_H
+#include "vector.h"
+#include "config.h"
#include "lock.h"
/*
struct mutex_lock {
@@ -13,7 +15,7 @@ struct vectors {
vector mpvec;
};
-void set_no_path_retry(struct multipath *mpp);
+void set_no_path_retry(struct config *conf, struct multipath *mpp);
int adopt_paths (vector pathvec, struct multipath * mpp);
void orphan_paths (vector pathvec, struct multipath * mpp);
@@ -22,10 +24,11 @@ void orphan_path (struct path * pp, const char *reason);
int verify_paths(struct multipath * mpp, struct vectors * vecs);
int update_mpp_paths(struct multipath * mpp, vector pathvec);
int __setup_multipath (struct vectors * vecs, struct multipath * mpp,
- int reset);
-#define setup_multipath(vecs, mpp) __setup_multipath(vecs, mpp, 1)
-int update_multipath_strings (struct multipath *mpp, vector pathvec);
-
+ int reset, int is_daemon);
+#define setup_multipath(vecs, mpp) __setup_multipath(vecs, mpp, 1, 1)
+int update_multipath_strings (struct multipath *mpp, vector pathvec,
+ int is_daemon);
+
void remove_map (struct multipath * mpp, struct vectors * vecs, int purge_vec);
void remove_map_and_stop_waiter (struct multipath * mpp, struct vectors * vecs, int purge_vec);
void remove_maps (struct vectors * vecs);
diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
index de7df40..9cf0311 100644
--- a/libmultipath/sysfs.c
+++ b/libmultipath/sysfs.c
@@ -11,8 +11,7 @@
* General Public License for more details.
*
* 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -57,44 +56,46 @@ ssize_t sysfs_attr_get_value(struct udev_device *dev, const char *attr_name,
snprintf(devpath, PATH_SIZE, "%s/%s", udev_device_get_syspath(dev),
attr_name);
condlog(4, "open '%s'", devpath);
- if (stat(devpath, &statbuf) != 0) {
+ /* 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;
+ }
+ if (fstat(fd, &statbuf) < 0) {
condlog(4, "stat '%s' failed: %s", devpath, strerror(errno));
+ close(fd);
return -ENXIO;
}
-
/* skip directories */
if (S_ISDIR(statbuf.st_mode)) {
condlog(4, "%s is a directory", devpath);
+ close(fd);
return -EISDIR;
}
-
/* skip non-writeable files */
if ((statbuf.st_mode & S_IRUSR) == 0) {
condlog(4, "%s is not readable", devpath);
+ close(fd);
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;
+ value[0] = '\0';
} else if (size == value_len) {
+ value[size - 1] = '\0';
condlog(4, "overflow while reading from %s", devpath);
size = 0;
} else {
value[size] = '\0';
+ size = strchop(value);
}
close(fd);
- if (size > 0)
- size = strchop(value);
return size;
}
@@ -112,30 +113,33 @@ ssize_t sysfs_bin_attr_get_value(struct udev_device *dev, const char *attr_name,
snprintf(devpath, PATH_SIZE, "%s/%s", udev_device_get_syspath(dev),
attr_name);
condlog(4, "open '%s'", devpath);
- if (stat(devpath, &statbuf) != 0) {
+ /* 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;
+ }
+ if (fstat(fd, &statbuf) != 0) {
condlog(4, "stat '%s' failed: %s", devpath, strerror(errno));
+ close(fd);
return -ENXIO;
}
/* skip directories */
if (S_ISDIR(statbuf.st_mode)) {
condlog(4, "%s is a directory", devpath);
+ close(fd);
return -EISDIR;
}
/* skip non-writeable files */
if ((statbuf.st_mode & S_IRUSR) == 0) {
condlog(4, "%s is not readable", devpath);
+ close(fd);
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));
@@ -163,30 +167,33 @@ ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
snprintf(devpath, PATH_SIZE, "%s/%s", udev_device_get_syspath(dev),
attr_name);
condlog(4, "open '%s'", devpath);
- if (stat(devpath, &statbuf) != 0) {
+ /* write attribute value */
+ fd = open(devpath, O_WRONLY);
+ if (fd < 0) {
+ condlog(4, "attribute '%s' can not be opened: %s",
+ devpath, strerror(errno));
+ return -errno;
+ }
+ if (fstat(fd, &statbuf) != 0) {
condlog(4, "stat '%s' failed: %s", devpath, strerror(errno));
+ close(fd);
return -errno;
}
/* skip directories */
if (S_ISDIR(statbuf.st_mode)) {
condlog(4, "%s is a directory", devpath);
+ close(fd);
return -EISDIR;
}
/* skip non-writeable files */
if ((statbuf.st_mode & S_IWUSR) == 0) {
condlog(4, "%s is not writeable", devpath);
+ close(fd);
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 -errno;
- }
size = write(fd, value, value_len);
if (size < 0) {
condlog(4, "write to %s failed: %s", devpath, strerror(errno));
diff --git a/libmultipath/uevent.c b/libmultipath/uevent.c
index fbe9c44..5f3204b 100644
--- a/libmultipath/uevent.c
+++ b/libmultipath/uevent.c
@@ -18,8 +18,7 @@
* General Public License for more details.
*
* 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -34,7 +33,7 @@
#include <sys/socket.h>
#include <sys/user.h>
#include <sys/un.h>
-#include <sys/poll.h>
+#include <poll.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <pthread.h>
@@ -291,8 +290,12 @@ int failback_listen(void)
}
/* enable receiving of the sender credentials */
- setsockopt(sock, SOL_SOCKET, SO_PASSCRED,
- &feature_on, sizeof(feature_on));
+ retval = setsockopt(sock, SOL_SOCKET, SO_PASSCRED,
+ &feature_on, sizeof(feature_on));
+ if (retval < 0) {
+ condlog(0, "failed to enable credential passing, exit");
+ goto exit;
+ }
} else {
/* Fallback to read kernel netlink events */
@@ -330,8 +333,11 @@ int failback_listen(void)
condlog(3, "receive buffer size for socket is %u.", rcvsz);
/* enable receiving of the sender credentials */
- setsockopt(sock, SOL_SOCKET, SO_PASSCRED,
- &feature_on, sizeof(feature_on));
+ if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED,
+ &feature_on, sizeof(feature_on)) < 0) {
+ condlog(0, "error on enabling credential passing for socket");
+ exit(1);
+ }
retval = bind(sock, (struct sockaddr *) &snl,
sizeof(struct sockaddr_nl));
@@ -474,10 +480,9 @@ int uevent_listen(struct udev *udev)
{
int err = 2;
struct udev_monitor *monitor = NULL;
- int fd, fd_ep = -1, socket_flags, events;
+ int fd, socket_flags, events;
int need_failback = 1;
int timeout = 30;
- sigset_t mask;
LIST_HEAD(uevlisten_tmp);
/*
@@ -528,22 +533,20 @@ int uevent_listen(struct udev *udev)
goto out;
}
- pthread_sigmask(SIG_SETMASK, NULL, &mask);
events = 0;
while (1) {
struct uevent *uev;
struct udev_device *dev;
struct pollfd ev_poll;
- struct timespec poll_timeout;
+ int poll_timeout;
int fdcount;
memset(&ev_poll, 0, sizeof(struct pollfd));
ev_poll.fd = fd;
ev_poll.events = POLLIN;
- memset(&poll_timeout, 0, sizeof(struct timespec));
- poll_timeout.tv_sec = timeout;
+ poll_timeout = timeout * 1000;
errno = 0;
- fdcount = ppoll(&ev_poll, 1, &poll_timeout, &mask);
+ fdcount = poll(&ev_poll, 1, poll_timeout);
if (fdcount && ev_poll.revents & POLLIN) {
timeout = 0;
dev = udev_monitor_receive_device(monitor);
@@ -582,8 +585,6 @@ int uevent_listen(struct udev *udev)
}
need_failback = 0;
out:
- if (fd_ep >= 0)
- close(fd_ep);
if (monitor)
udev_monitor_unref(monitor);
if (need_failback)
diff --git a/libmultipath/uxsock.c b/libmultipath/uxsock.c
index e91abd9..775e278 100644
--- a/libmultipath/uxsock.c
+++ b/libmultipath/uxsock.c
@@ -13,13 +13,13 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/poll.h>
+#include <poll.h>
#include <signal.h>
#include <errno.h>
#ifdef USE_SYSTEMD
#include <systemd/sd-daemon.h>
#endif
-#include <mpath_cmd.h>
+#include "mpath_cmd.h"
#include "memory.h"
#include "uxsock.h"
diff --git a/libmultipath/vector.h b/libmultipath/vector.h
index 7612b4c..5cfd4d0 100644
--- a/libmultipath/vector.h
+++ b/libmultipath/vector.h
@@ -1,10 +1,10 @@
-/*
+/*
* Soft: Keepalived is a failover program for the LVS project
* <www.linuxvirtualserver.org>. It monitor & manipulate
* a loadbalanced server pool using multi-layer checks.
- *
+ *
* Part: vector.c include file.
- *
+ *
* Version: $Id: vector.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
diff --git a/libmultipath/version.h b/libmultipath/version.h
index afad174..09d725d 100644
--- a/libmultipath/version.h
+++ b/libmultipath/version.h
@@ -20,8 +20,8 @@
#ifndef _VERSION_H
#define _VERSION_H
-#define VERSION_CODE 0x000601
-#define DATE_CODE 0x050a10
+#define VERSION_CODE 0x000602
+#define DATE_CODE 0x071610
#define PROG "multipath-tools"
diff --git a/libmultipath/waiter.c b/libmultipath/waiter.c
index 7cedd4b..06995b6 100644
--- a/libmultipath/waiter.c
+++ b/libmultipath/waiter.c
@@ -9,10 +9,12 @@
#include <sys/mman.h>
#include <pthread.h>
#include <signal.h>
+#include <urcu.h>
#include "vector.h"
#include "memory.h"
#include "checkers.h"
+#include "config.h"
#include "structs.h"
#include "structs_vec.h"
#include "devmapper.h"
@@ -40,6 +42,7 @@ void free_waiter (void *data)
if (wp->dmt)
dm_task_destroy(wp->dmt);
+ rcu_unregister_thread();
FREE(wp);
}
@@ -166,6 +169,7 @@ void *waitevent (void *et)
waiter = (struct event_thread *)et;
pthread_cleanup_push(free_waiter, et);
+ rcu_register_thread();
while (1) {
r = waiteventloop(waiter);
@@ -191,7 +195,7 @@ int start_waiter_thread (struct multipath *mpp, struct vectors *vecs)
if (!wp)
goto out;
- strncpy(wp->mapname, mpp->alias, WWID_SIZE);
+ strncpy(wp->mapname, mpp->alias, WWID_SIZE - 1);
wp->vecs = vecs;
if (pthread_create(&wp->thread, &waiter_attr, waitevent, wp)) {
@@ -209,4 +213,3 @@ out:
condlog(0, "failed to start waiter thread");
return 1;
}
-
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index 567c93d..a7c3249 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -89,8 +89,11 @@ replace_wwids(vector mp)
struct multipath * mpp;
size_t len;
int ret = -1;
+ struct config *conf;
+ conf = get_multipath_config();
fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
+ put_multipath_config(conf);
if (fd < 0)
goto out;
if (!can_write) {
@@ -188,6 +191,7 @@ remove_wwid(char *wwid) {
int fd, len, can_write;
char *str;
int ret = -1;
+ struct config *conf;
len = strlen(wwid) + 4; /* two slashes the newline and a zero byte */
str = malloc(len);
@@ -201,7 +205,9 @@ remove_wwid(char *wwid) {
goto out;
}
condlog(3, "removing line '%s' from wwids file", str);
+ conf = get_multipath_config();
fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
+ put_multipath_config(conf);
if (fd < 0)
goto out;
if (!can_write) {
@@ -222,7 +228,11 @@ check_wwids_file(char *wwid, int write_wwid)
{
int fd, can_write, found, ret;
FILE *f;
+ struct config *conf;
+
+ conf = get_multipath_config();
fd = open_file(conf->wwids_file, &can_write, WWIDS_FILE_HEADER);
+ put_multipath_config(conf);
if (fd < 0)
return -1;
@@ -263,14 +273,20 @@ out:
int
should_multipath(struct path *pp1, vector pathvec)
{
- int i;
+ int i, ignore_new_devs;;
struct path *pp2;
+ struct config *conf;
- if (!conf->find_multipaths && !conf->ignore_new_devs)
+ conf = get_multipath_config();
+ ignore_new_devs = conf->ignore_new_devs;
+ if (!conf->find_multipaths && !ignore_new_devs) {
+ put_multipath_config(conf);
return 1;
+ }
+ put_multipath_config(conf);
condlog(4, "checking if %s should be multipathed", pp1->dev);
- if (!conf->ignore_new_devs) {
+ if (!ignore_new_devs) {
vector_foreach_slot(pathvec, pp2, i) {
if (pp1->dev == pp2->dev)
continue;
diff --git a/mpathpersist/Makefile b/mpathpersist/Makefile
index 6f7a5cf..a458c4d 100644
--- a/mpathpersist/Makefile
+++ b/mpathpersist/Makefile
@@ -2,9 +2,9 @@
#
include ../Makefile.inc
-OBJS = main.o
+OBJS = main.o
-CFLAGS += -I$(multipathdir) -I$(mpathpersistdir)
+CFLAGS += -I$(multipathdir) -I$(mpathpersistdir)
LDFLAGS += -lpthread -ldevmapper -L$(mpathpersistdir) -lmpathpersist -L$(multipathdir) -L$(mpathcmddir) -lmpathcmd -lmultipath -ludev
EXEC = mpathpersist
@@ -14,17 +14,17 @@ all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) -g $(OBJS) -o $(EXEC) $(LDFLAGS) $(CFLAGS)
$(GZIP) $(EXEC).8 > $(EXEC).8.gz
-
+
install:
- install -d $(DESTDIR)$(bindir)
- install -m 755 $(EXEC) $(DESTDIR)$(bindir)/
- install -d $(DESTDIR)$(mandir)
- install -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
-
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
+ $(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+ $(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
+ $(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
+
clean:
- rm -f *.o $(EXEC)
- rm -f mpathpersist.8.gz
+ $(RM) *.o $(EXEC)
+ $(RM) mpathpersist.8.gz
uninstall:
- rm $(DESTDIR)$(bindir)/$(EXEC)
- rm $(DESTDIR)$(mandir)/$(EXEC).8.gz
+ $(RM) $(DESTDIR)$(bindir)/$(EXEC)
+ $(RM) $(DESTDIR)$(mandir)/$(EXEC).8.gz
diff --git a/mpathpersist/main.c b/mpathpersist/main.c
index e3484b5..bf9c721 100644
--- a/mpathpersist/main.c
+++ b/mpathpersist/main.c
@@ -3,12 +3,13 @@
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
-#include <checkers.h>
-#include <vector.h>
-#include <structs.h>
+#include "checkers.h"
+#include "vector.h"
+#include "config.h"
+#include "structs.h"
#include <getopt.h>
#include <libudev.h>
-#include <mpath_persist.h>
+#include "mpath_persist.h"
#include "main.h"
#include <pthread.h>
#include <ctype.h>
@@ -29,17 +30,32 @@ static const char * pr_type_strs[] = {
};
int get_transportids_length(unsigned char * transportid_arr, int max_transportid, int num_transportids);
-void mpath_print_buf_readcap(struct prin_resp *pr_buff);
+void mpath_print_buf_readcap(struct prin_resp *pr_buff);
void mpath_print_buf_readfullstat(struct prin_resp *pr_buff);
void mpath_print_buf_readresv(struct prin_resp *pr_buff);
void mpath_print_buf_readkeys(struct prin_resp *pr_buff);
void dumpHex(const char* str, int len, int no_ascii);
-void * mpath_alloc_prin_response(int prin_sa);
+void * mpath_alloc_prin_response(int prin_sa);
void mpath_print_transport_id(struct prin_fulldescr *fdesc);
int construct_transportid(const char * inp, struct transportid transid[], int num_transportids);
int logsink;
unsigned int mpath_mx_alloc_len;
+struct config *multipath_conf;
+
+struct config *get_multipath_config(void)
+{
+ return multipath_conf;
+}
+
+void put_multipath_config(struct config *conf)
+{
+ /* Noop for now */
+}
+
+void rcu_register_thread_memb(void) {}
+
+void rcu_unregister_thread_memb(void) {}
int main (int argc, char * argv[])
{
@@ -71,6 +87,7 @@ int main (int argc, char * argv[])
void *resp = NULL;
struct transportid * tmp;
struct udev *udev = NULL;
+ struct config *conf;
if (optind == argc)
{
@@ -87,8 +104,9 @@ int main (int argc, char * argv[])
}
udev = udev_new();
- mpath_lib_init(udev);
+ conf = mpath_lib_init(udev);
memset(transportids,0,MPATH_MX_TIDS);
+ multipath_conf = conf;
while (1)
{
@@ -225,18 +243,18 @@ int main (int argc, char * argv[])
break;
case 'l':
- if (1 != sscanf(optarg, "%u", &mpath_mx_alloc_len)) {
- fprintf(stderr, "bad argument to '--alloc-length'\n");
- return MPATH_PR_SYNTAX_ERROR;
- } else if (MPATH_MAX_PARAM_LEN < mpath_mx_alloc_len) {
- fprintf(stderr, "'--alloc-length' argument exceeds maximum"
- " limit(%d)\n", MPATH_MAX_PARAM_LEN);
- return MPATH_PR_SYNTAX_ERROR;
- }
- break;
+ if (1 != sscanf(optarg, "%u", &mpath_mx_alloc_len)) {
+ fprintf(stderr, "bad argument to '--alloc-length'\n");
+ return MPATH_PR_SYNTAX_ERROR;
+ } else if (MPATH_MAX_PARAM_LEN < mpath_mx_alloc_len) {
+ fprintf(stderr, "'--alloc-length' argument exceeds maximum"
+ " limit(%d)\n", MPATH_MAX_PARAM_LEN);
+ return MPATH_PR_SYNTAX_ERROR;
+ }
+ break;
default:
- fprintf(stderr, "unrecognised switch " "code 0x%x ??\n", c);
+ fprintf(stderr, "unrecognised switch " "code 0x%x ??\n", c);
usage ();
ret = MPATH_PR_SYNTAX_ERROR;
goto out;
@@ -379,33 +397,33 @@ int main (int argc, char * argv[])
if (ret != MPATH_PR_SUCCESS )
{
fprintf (stderr, "Persistent Reserve IN command failed\n");
- goto out;
+ goto out;
}
switch(prin_sa)
- {
- case MPATH_PRIN_RKEY_SA:
- mpath_print_buf_readkeys(resp);
+ {
+ case MPATH_PRIN_RKEY_SA:
+ mpath_print_buf_readkeys(resp);
break;
- case MPATH_PRIN_RRES_SA:
+ case MPATH_PRIN_RRES_SA:
mpath_print_buf_readresv(resp);
break;
case MPATH_PRIN_RCAP_SA:
- mpath_print_buf_readcap(resp);
+ mpath_print_buf_readcap(resp);
break;
case MPATH_PRIN_RFSTAT_SA:
- mpath_print_buf_readfullstat(resp);
+ mpath_print_buf_readfullstat(resp);
break;
}
free(resp);
}
else if (prout)
{
- int j;
+ int j;
struct prout_param_descriptor *paramp;
paramp= malloc(sizeof(struct prout_param_descriptor) + (sizeof(struct transportid *)*(MPATH_MX_TIDS )));
-
+
memset(paramp, 0, sizeof(struct prout_param_descriptor) + (sizeof(struct transportid *)*(MPATH_MX_TIDS)));
for (j = 7; j >= 0; --j) {
@@ -423,7 +441,7 @@ int main (int argc, char * argv[])
if (param_aptpl)
paramp->sa_flags |= 0x1;
- if (num_transport)
+ if (num_transport)
{
paramp->sa_flags |= MPATH_F_SPEC_I_PT_MASK;
paramp->num_transportid = num_transport;
@@ -462,13 +480,13 @@ int main (int argc, char * argv[])
res = close (fd);
if (res < 0)
{
- mpath_lib_exit();
+ mpath_lib_exit(conf);
udev_unref(udev);
return MPATH_PR_FILE_ERROR;
}
out :
- mpath_lib_exit();
+ mpath_lib_exit(conf);
udev_unref(udev);
return (ret >= 0) ? ret : MPATH_PR_OTHER;
}
@@ -538,7 +556,7 @@ void mpath_print_buf_readresv( struct prin_resp *pr_buff)
{
int j, num, scope=0, type=0;
unsigned char *keyp;
- uint64_t prkey;
+ uint64_t prkey;
num = pr_buff->prin_descriptor.prin_readresv.additional_length / 8;
if (0 == num)
@@ -548,7 +566,7 @@ void mpath_print_buf_readresv( struct prin_resp *pr_buff)
}
else
printf(" PR generation=0x%x, Reservation follows:\n", pr_buff->prin_descriptor.prin_readresv.prgeneration);
- keyp = (unsigned char *)&pr_buff->prin_descriptor.prin_readkeys.key_list[0];
+ keyp = (unsigned char *)&pr_buff->prin_descriptor.prin_readkeys.key_list[0];
prkey = 0;
for (j = 0; j < 8; ++j) {
if (j > 0)
@@ -561,7 +579,7 @@ void mpath_print_buf_readresv( struct prin_resp *pr_buff)
scope = (pr_buff->prin_descriptor.prin_readresv.scope_type >> 4) & 0x0f;
type = pr_buff->prin_descriptor.prin_readresv.scope_type & 0x0f;
- if (scope == 0)
+ if (scope == 0)
printf(" scope = LU_SCOPE, type = %s", pr_type_strs[type]);
else
printf(" scope = %d, type = %s", scope, pr_type_strs[type]);
@@ -610,7 +628,7 @@ void mpath_print_buf_readfullstat( struct prin_resp *pr_buff)
uint16_t rel_pt_addr;
unsigned char * keyp;
- num = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
+ num = pr_buff->prin_descriptor.prin_readfd.number_of_descriptor;
if (0 == num)
{
printf(" PR generation=0x%x \n", pr_buff->prin_descriptor.prin_readfd.prgeneration);
@@ -632,7 +650,7 @@ void mpath_print_buf_readfullstat( struct prin_resp *pr_buff)
}
printf(" Key = 0x%" PRIx64 "\n", prkey);
- if (pr_buff->prin_descriptor.prin_readfd.descriptors[i]->flag & 0x02)
+ if (pr_buff->prin_descriptor.prin_readfd.descriptors[i]->flag & 0x02)
printf(" All target ports bit set\n");
else {
printf(" All target ports bit clear\n");
@@ -705,7 +723,7 @@ mpath_print_transport_id(struct prin_fulldescr *fdesc)
case MPATH_PROTOCOL_ID_FC:
printf(" FCP-2 ");
if (0 != fdesc->trnptid.format_code)
- printf(" [Unexpected format code: %d]\n",
+ printf(" [Unexpected format code: %d]\n",
fdesc->trnptid.format_code);
dumpHex((const char *)fdesc->trnptid.n_port_name, 8, 0);
break;
@@ -727,9 +745,9 @@ mpath_print_transport_id(struct prin_fulldescr *fdesc)
case MPATH_PROTOCOL_ID_SAS:
printf(" SAS ");
if (0 != fdesc->trnptid.format_code)
- printf(" [Unexpected format code: %d]\n",
- fdesc->trnptid.format_code);
- dumpHex((const char *)fdesc->trnptid.sas_address, 8, 0);
+ printf(" [Unexpected format code: %d]\n",
+ fdesc->trnptid.format_code);
+ dumpHex((const char *)fdesc->trnptid.sas_address, 8, 0);
break;
default:
return;
@@ -816,4 +834,3 @@ my_cont_b:
}
return 0;
}
-
diff --git a/mpathpersist/main.h b/mpathpersist/main.h
index 64686ec..7c31262 100644
--- a/mpathpersist/main.h
+++ b/mpathpersist/main.h
@@ -18,7 +18,7 @@ static struct option long_options[] = {
{"register", 0, 0, 'G'},
{"register-ignore", 0, 0, 'I'},
{"release", 0, 0, 'L'},
- {"report-capabilities", 0, 0, 'c'},
+ {"report-capabilities", 0, 0, 'c'},
{"reserve", 0, 0, 'R'},
{"transport-id", 1, 0, 'X'},
{"alloc-length", 1, 0, 'l'},
@@ -26,4 +26,3 @@ static struct option long_options[] = {
};
static void usage(void);
-
diff --git a/multipath-tools.spec.in b/multipath-tools.spec.in
deleted file mode 100644
index 832006d..0000000
--- a/multipath-tools.spec.in
+++ /dev/null
@@ -1,58 +0,0 @@
-%define _rpmdir rpms
-%define _builddir .
-
-Summary: Tools to manage multipathed devices with the device-mapper.
-Name: multipath-tools
-Version: __VERSION__
-Release: 1
-License: GPL
-Group: Utilities/System
-URL: http://christophe.varoqui.free.fr
-Source: /dev/null
-BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
-Packager: Christophe Varoqui <christophe.varoqui@opensvc.com>
-Prefix: /
-Vendor: Starving Linux Artists (tm Brian O'Sullivan)
-ExclusiveOS: linux
-
-%description
-%{name} provides the tools to manage multipathed devices by
-instructing the device-mapper multipath module what to do. The tools
-are :
-* multipath : scan the system for multipathed devices, assembles them
- and update the device-mapper's maps
-* multipathd : wait for maps events, then execs multipath
-* kpartx : maps linear devmaps upon device partitions, which makes
- multipath maps partionable
-
-%prep
-mkdir -p %{buildroot} %{_rpmdir}
-
-%build
-make
-
-%install
-rm -rf %{buildroot}
-make DESTDIR=%{buildroot} install
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%defattr(-,root,root,-)
-%{prefix}/sbin/multipath
-%{prefix}/sbin/kpartx
-%{prefix}/usr/share/man/man8/multipath.8.gz
-%{prefix}/usr/share/man/man8/kpartx.8.gz
-%{prefix}/usr/share/man/man8/multipathd.8.gz
-%{prefix}/usr/share/man/man5/multipath.conf.5.gz
-%{prefix}/sbin/multipathd
-%{prefix}/etc/udev/rules.d/multipath.rules
-%{prefix}/etc/udev/rules.d/kpartx.rules
-%{prefix}/lib/udev/kpartx_id
-%{prefix}/lib/multipath/*.so
-
-
-%changelog
-* Sat May 14 2004 Christophe Varoqui
-- Initial build.
diff --git a/multipath/01_udev b/multipath/01_udev
index 0f68996..c4e4c53 100755
--- a/multipath/01_udev
+++ b/multipath/01_udev
@@ -7,7 +7,7 @@ cp /bin/readlink $INITRDDIR/bin/
PROGS="/sbin/udev /sbin/udevstart /bin/mountpoint /bin/readlink"
LIBS=`ldd $PROGS | grep -v linux-gate.so | sort -u | \
-awk '{print $3}'`
+awk '{print $3}'`
for i in $LIBS
do
mkdir -p `dirname $INITRDDIR/$i`
diff --git a/multipath/02_multipath b/multipath/02_multipath
index 467a7cb..523f0ef 100755
--- a/multipath/02_multipath
+++ b/multipath/02_multipath
@@ -16,7 +16,7 @@ cp /bin/mountpoint $INITRDDIR/bin
PROGS="/lib/udev/scsi_id /bin/mountpoint"
LIBS=`ldd $PROGS | grep -v linux-gate.so | sort -u | \
-awk '{print $3}'`
+awk '{print $3}'`
for i in $LIBS
do
mkdir -p `dirname $INITRDDIR/$i`
@@ -30,4 +30,3 @@ if [ -f /etc/multipath.conf ]
then
cp /etc/multipath.conf $INITRDDIR/etc/
fi
-
diff --git a/multipath/Makefile b/multipath/Makefile
index 3707235..9c57d3b 100644
--- a/multipath/Makefile
+++ b/multipath/Makefile
@@ -31,11 +31,11 @@ install:
$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
uninstall:
- rm $(DESTDIR)$(bindir)/$(EXEC)
- rm $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
- rm $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
- rm $(DESTDIR)$(mandir)/$(EXEC).8.gz
- rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
+ $(RM) $(DESTDIR)$(bindir)/$(EXEC)
+ $(RM) $(DESTDIR)$(udevrulesdir)/11-dm-mpath.rules
+ $(RM) $(DESTDIR)$(libudevdir)/rules.d/56-multipath.rules
+ $(RM) $(DESTDIR)$(mandir)/$(EXEC).8.gz
+ $(RM) $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
clean:
- rm -f core *.o $(EXEC) *.gz
+ $(RM) core *.o $(EXEC) *.gz
diff --git a/multipath/main.c b/multipath/main.c
index c33f689..6ccece7 100644
--- a/multipath/main.c
+++ b/multipath/main.c
@@ -30,36 +30,52 @@
#include <libudev.h>
#include <syslog.h>
-#include <checkers.h>
-#include <prio.h>
-#include <vector.h>
-#include <memory.h>
+#include "checkers.h"
+#include "prio.h"
+#include "vector.h"
+#include "memory.h"
#include <libdevmapper.h>
-#include <devmapper.h>
-#include <util.h>
-#include <defaults.h>
-#include <structs.h>
-#include <structs_vec.h>
-#include <dmparser.h>
-#include <sysfs.h>
-#include <config.h>
-#include <blacklist.h>
-#include <discovery.h>
-#include <debug.h>
-#include <switchgroup.h>
-#include <print.h>
-#include <alias.h>
-#include <configure.h>
-#include <pgpolicies.h>
-#include <version.h>
+#include "devmapper.h"
+#include "util.h"
+#include "defaults.h"
+#include "config.h"
+#include "structs.h"
+#include "structs_vec.h"
+#include "dmparser.h"
+#include "sysfs.h"
+#include "blacklist.h"
+#include "discovery.h"
+#include "debug.h"
+#include "switchgroup.h"
+#include "print.h"
+#include "alias.h"
+#include "configure.h"
+#include "pgpolicies.h"
+#include "version.h"
#include <errno.h>
#include <sys/time.h>
#include <sys/resource.h>
-#include <wwids.h>
-#include <uxsock.h>
-#include <mpath_cmd.h>
+#include "wwids.h"
+#include "uxsock.h"
+#include "mpath_cmd.h"
int logsink;
+struct udev *udev;
+struct config *multipath_conf;
+
+struct config *get_multipath_config(void)
+{
+ return multipath_conf;
+}
+
+void put_multipath_config(struct config *conf)
+{
+ /* Noop for now */
+}
+
+void rcu_register_thread_memb(void) {}
+
+void rcu_unregister_thread_memb(void) {}
static int
filter_pathvec (vector pathvec, char * refwwid)
@@ -94,38 +110,38 @@ usage (char * progname)
fprintf (stderr,
"\n"
"Where:\n"
- " -h print this usage text\n" \
- " -l show multipath topology (sysfs and DM info)\n" \
- " -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" \
- " -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" \
- " -r force devmap reload\n" \
- " -i ignore wwids file\n" \
- " -B treat the bindings file as read only\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" \
- " . group_by_serial one priority group per serial\n" \
- " . group_by_prio one priority group per priority lvl\n" \
- " . group_by_node_name one priority group per target node\n" \
- " -v lvl verbosity level\n" \
- " . 0 no output\n" \
- " . 1 print created devmap names only\n" \
- " . 2 default verbosity\n" \
- " . 3 print debug information\n" \
- " dev action limited to:\n" \
- " . multipath named 'dev' (ex: mpath0) or\n" \
- " . multipath whose wwid is 'dev' (ex: 60051..)\n" \
- " . multipath including the path named 'dev' (ex: /dev/sda)\n" \
- " . multipath including the path with maj:min 'dev' (ex: 8:0)\n" \
+ " -h print this usage text\n"
+ " -l show multipath topology (sysfs and DM info)\n"
+ " -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"
+ " -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"
+ " -r force devmap reload\n"
+ " -i ignore wwids file\n"
+ " -B treat the bindings file as read only\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"
+ " . group_by_serial one priority group per serial\n"
+ " . group_by_prio one priority group per priority lvl\n"
+ " . group_by_node_name one priority group per target node\n"
+ " -v lvl verbosity level\n"
+ " . 0 no output\n"
+ " . 1 print created devmap names only\n"
+ " . 2 default verbosity\n"
+ " . 3 print debug information\n"
+ " dev action limited to:\n"
+ " . multipath named 'dev' (ex: mpath0) or\n"
+ " . multipath whose wwid is 'dev' (ex: 60051..)\n"
+ " . multipath including the path named 'dev' (ex: /dev/sda)\n"
+ " . multipath including the path with maj:min 'dev' (ex: 8:0)\n"
);
}
@@ -136,6 +152,7 @@ update_paths (struct multipath * mpp)
int i, j;
struct pathgroup * pgp;
struct path * pp;
+ struct config *conf;
if (!mpp->pg)
return 0;
@@ -155,20 +172,26 @@ update_paths (struct multipath * mpp)
continue;
}
pp->mpp = mpp;
- if (pathinfo(pp, conf->hwtable, DI_ALL))
+ conf = get_multipath_config();
+ if (pathinfo(pp, conf, DI_ALL))
pp->state = PATH_UNCHECKED;
+ put_multipath_config(conf);
continue;
}
pp->mpp = mpp;
if (pp->state == PATH_UNCHECKED ||
pp->state == PATH_WILD) {
- if (pathinfo(pp, conf->hwtable, DI_CHECKER))
+ conf = get_multipath_config();
+ if (pathinfo(pp, conf, DI_CHECKER))
pp->state = PATH_UNCHECKED;
+ put_multipath_config(conf);
}
if (pp->priority == PRIO_UNDEF) {
- if (pathinfo(pp, conf->hwtable, DI_PRIO))
+ conf = get_multipath_config();
+ if (pathinfo(pp, conf, DI_PRIO))
pp->priority = PRIO_UNDEF;
+ put_multipath_config(conf);
}
}
}
@@ -176,7 +199,7 @@ update_paths (struct multipath * mpp)
}
static int
-get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
+get_dm_mpvec (enum mpath_cmds cmd, vector curmp, vector pathvec, char * refwwid)
{
int i;
struct multipath * mpp;
@@ -198,7 +221,7 @@ get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
continue;
}
- if (conf->cmd == CMD_VALID_PATH)
+ if (cmd == CMD_VALID_PATH)
continue;
dm_get_map(mpp->alias, &mpp->size, params);
@@ -206,26 +229,29 @@ get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
dm_get_status(mpp->alias, status);
condlog(3, "status = %s", status);
- disassemble_map(pathvec, params, mpp);
+ disassemble_map(pathvec, params, mpp, 0);
/*
* disassemble_map() can add new paths to pathvec.
* If not in "fast list mode", we need to fetch information
* about them
*/
- if (conf->cmd != CMD_LIST_SHORT)
+ if (cmd != CMD_LIST_SHORT)
update_paths(mpp);
- if (conf->cmd == CMD_LIST_LONG)
+ if (cmd == CMD_LIST_LONG)
mpp->bestpg = select_path_group(mpp);
disassemble_status(status, mpp);
- if (conf->cmd == CMD_LIST_SHORT ||
- conf->cmd == CMD_LIST_LONG)
+ if (cmd == CMD_LIST_SHORT ||
+ cmd == CMD_LIST_LONG) {
+ struct config *conf = get_multipath_config();
print_multipath_topology(mpp, conf->verbosity);
+ put_multipath_config(conf);
+ }
- if (conf->cmd == CMD_CREATE)
+ if (cmd == CMD_CREATE)
reinstate_paths(mpp);
}
return 0;
@@ -239,7 +265,7 @@ get_dm_mpvec (vector curmp, vector pathvec, char * refwwid)
* 1: Failure
*/
static int
-configure (void)
+configure (enum mpath_cmds cmd, enum devtypes dev_type, char *devpath)
{
vector curmp = NULL;
vector pathvec = NULL;
@@ -248,6 +274,7 @@ configure (void)
int di_flag = 0;
char * refwwid = NULL;
char * dev = NULL;
+ struct config *conf;
/*
* allocate core vectors to store paths and multipaths
@@ -262,36 +289,40 @@ configure (void)
vecs.pathvec = pathvec;
vecs.mpvec = curmp;
- dev = convert_dev(conf->dev, (conf->dev_type == DEV_DEVNODE));
+ dev = convert_dev(devpath, (dev_type == DEV_DEVNODE));
/*
* if we have a blacklisted device parameter, exit early
*/
- if (dev && conf->dev_type == DEV_DEVNODE &&
- conf->cmd != CMD_REMOVE_WWID &&
+ conf = get_multipath_config();
+ if (dev && (dev_type == DEV_DEVNODE ||
+ dev_type == DEV_UEVENT) &&
+ cmd != CMD_REMOVE_WWID &&
(filter_devnode(conf->blist_devnode,
conf->elist_devnode, dev) > 0)) {
- if (conf->cmd == CMD_VALID_PATH)
+ if (cmd == CMD_VALID_PATH)
printf("%s is not a valid multipath device path\n",
- conf->dev);
+ devpath);
+ put_multipath_config(conf);
goto out;
}
+ put_multipath_config(conf);
/*
* scope limiting must be translated into a wwid
* failing the translation is fatal (by policy)
*/
- if (conf->dev) {
- int failed = get_refwwid(conf->dev, conf->dev_type, pathvec,
- &refwwid);
+ if (devpath) {
+ int failed = get_refwwid(cmd, devpath, dev_type,
+ pathvec, &refwwid);
if (!refwwid) {
- condlog(4, "%s: failed to get wwid", conf->dev);
- if (failed == 2 && conf->cmd == CMD_VALID_PATH)
- printf("%s is not a valid multipath device path\n", conf->dev);
+ condlog(4, "%s: failed to get wwid", devpath);
+ if (failed == 2 && cmd == CMD_VALID_PATH)
+ printf("%s is not a valid multipath device path\n", devpath);
else
- condlog(3, "scope is nul");
+ condlog(3, "scope is null");
goto out;
}
- if (conf->cmd == CMD_REMOVE_WWID) {
+ if (cmd == CMD_REMOVE_WWID) {
r = remove_wwid(refwwid);
if (r == 0)
printf("wwid '%s' removed\n", refwwid);
@@ -302,7 +333,7 @@ configure (void)
}
goto out;
}
- if (conf->cmd == CMD_ADD_WWID) {
+ if (cmd == CMD_ADD_WWID) {
r = remember_wwid(refwwid);
if (r == 0)
printf("wwid '%s' added\n", refwwid);
@@ -317,14 +348,14 @@ configure (void)
* 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 &&
+ if (cmd == CMD_VALID_PATH &&
(!conf->find_multipaths || !conf->ignore_wwids)) {
if (conf->ignore_wwids ||
check_wwids_file(refwwid, 0) == 0)
r = 0;
printf("%s %s a valid multipath device path\n",
- conf->dev, r == 0 ? "is" : "is not");
+ devpath, r == 0 ? "is" : "is not");
goto out;
}
}
@@ -332,20 +363,20 @@ configure (void)
/*
* get a path list
*/
- if (conf->dev)
+ if (devpath)
di_flag = DI_WWID;
- if (conf->cmd == CMD_LIST_LONG)
+ if (cmd == CMD_LIST_LONG)
/* extended path info '-ll' */
di_flag |= DI_SYSFS | DI_CHECKER;
- else if (conf->cmd == CMD_LIST_SHORT)
+ else if (cmd == CMD_LIST_SHORT)
/* minimum path info '-l' */
di_flag |= DI_SYSFS;
else
/* maximum info */
di_flag = DI_ALL;
- if (path_discovery(pathvec, conf, di_flag) < 0)
+ if (path_discovery(pathvec, di_flag) < 0)
goto out;
if (conf->verbosity > 2)
@@ -353,14 +384,14 @@ configure (void)
get_path_layout(pathvec, 0);
- if (get_dm_mpvec(curmp, pathvec, refwwid))
+ if (get_dm_mpvec(cmd, curmp, pathvec, refwwid))
goto out;
filter_pathvec(pathvec, refwwid);
- if (conf->cmd == CMD_VALID_PATH) {
- /* This only happens if find_multipaths is and
+ if (cmd == CMD_VALID_PATH) {
+ /* This only happens if find_multipaths and
* ignore_wwids is set.
* If there is currently a multipath device matching
* the refwwid, or there is more than one path matching
@@ -368,11 +399,11 @@ configure (void)
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");
+ devpath, r == 0 ? "is" : "is not");
goto out;
}
- if (conf->cmd != CMD_CREATE && conf->cmd != CMD_DRY_RUN) {
+ if (cmd != CMD_CREATE && cmd != CMD_DRY_RUN) {
r = 0;
goto out;
}
@@ -380,7 +411,8 @@ configure (void)
/*
* core logic entry point
*/
- r = coalesce_paths(&vecs, NULL, refwwid, conf->force_reload);
+ r = coalesce_paths(&vecs, NULL, refwwid,
+ conf->force_reload, cmd);
out:
if (refwwid)
@@ -393,7 +425,7 @@ out:
}
static int
-dump_config (void)
+dump_config (struct config *conf)
{
char * c, * tmp = NULL;
char * reply;
@@ -409,38 +441,39 @@ dump_config (void)
return 1;
}
c = tmp = reply;
- c += snprint_defaults(c, reply + maxlen - c);
+ c += snprint_defaults(conf, c, reply + maxlen - c);
again = ((c - reply) == maxlen);
if (again) {
reply = REALLOC(reply, maxlen *= 2);
continue;
}
- c += snprint_blacklist(c, reply + maxlen - c);
+ c += snprint_blacklist(conf, c, reply + maxlen - c);
again = ((c - reply) == maxlen);
if (again) {
reply = REALLOC(reply, maxlen *= 2);
continue;
}
- c += snprint_blacklist_except(c, reply + maxlen - c);
+ c += snprint_blacklist_except(conf, c, reply + maxlen - c);
again = ((c - reply) == maxlen);
if (again) {
reply = REALLOC(reply, maxlen *= 2);
continue;
}
- c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable);
+ c += snprint_hwtable(conf, c, reply + maxlen - c, conf->hwtable);
again = ((c - reply) == maxlen);
if (again) {
reply = REALLOC(reply, maxlen *= 2);
continue;
}
- c += snprint_overrides(c, reply + maxlen - c, conf->overrides);
+ c += snprint_overrides(conf, c, reply + maxlen - c,
+ conf->overrides);
again = ((c - reply) == maxlen);
if (again) {
reply = REALLOC(reply, maxlen *= 2);
continue;
}
if (VECTOR_SIZE(conf->mptable) > 0) {
- c += snprint_mptable(c, reply + maxlen - c,
+ c += snprint_mptable(conf, c, reply + maxlen - c,
conf->mptable);
again = ((c - reply) == maxlen);
if (again)
@@ -465,24 +498,29 @@ get_dev_type(char *dev) {
}
else if (sscanf(dev, "%d:%d", &i, &i) == 2)
return DEV_DEVT;
- else
+ else if (valid_alias(dev))
return DEV_DEVMAP;
+ return DEV_NONE;
}
int
main (int argc, char *argv[])
{
- struct udev *udev;
int arg;
extern char *optarg;
extern int optind;
int r = 1;
+ enum mpath_cmds cmd = CMD_CREATE;
+ enum devtypes dev_type;
+ char *dev = NULL;
+ struct config *conf;
udev = udev_new();
logsink = 0;
- if (load_config(DEFAULT_CONFIGFILE, udev))
+ conf = load_config(DEFAULT_CONFIGFILE);
+ if (!conf)
exit(1);
-
+ multipath_conf = conf;
while ((arg = getopt(argc, argv, ":adchl::FfM:v:p:b:BritquwW")) != EOF ) {
switch(arg) {
case 1: printf("optarg : %s\n",optarg);
@@ -506,11 +544,11 @@ main (int argc, char *argv[])
conf->allow_queueing = 1;
break;
case 'c':
- conf->cmd = CMD_VALID_PATH;
+ cmd = CMD_VALID_PATH;
break;
case 'd':
- if (conf->cmd == CMD_CREATE)
- conf->cmd = CMD_DRY_RUN;
+ if (cmd == CMD_CREATE)
+ cmd = CMD_DRY_RUN;
break;
case 'f':
conf->remove = FLUSH_ONE;
@@ -520,9 +558,9 @@ main (int argc, char *argv[])
break;
case 'l':
if (optarg && !strncmp(optarg, "l", 1))
- conf->cmd = CMD_LIST_LONG;
+ cmd = CMD_LIST_LONG;
else
- conf->cmd = CMD_LIST_SHORT;
+ cmd = CMD_LIST_SHORT;
break;
case 'M':
@@ -532,7 +570,7 @@ main (int argc, char *argv[])
break;
case 'p':
conf->pgpolicy_flag = get_pgpolicy_id(optarg);
- if (conf->pgpolicy_flag == -1) {
+ if (conf->pgpolicy_flag == IOPOLICY_UNDEF) {
printf("'%s' is not a valid policy\n", optarg);
usage(argv[0]);
exit(1);
@@ -545,23 +583,23 @@ main (int argc, char *argv[])
conf->ignore_wwids = 1;
break;
case 't':
- r = dump_config();
+ r = dump_config(conf);
goto out_free_config;
case 'h':
usage(argv[0]);
exit(0);
case 'u':
- conf->cmd = CMD_VALID_PATH;
- conf->dev_type = DEV_UEVENT;
+ cmd = CMD_VALID_PATH;
+ dev_type = DEV_UEVENT;
break;
case 'w':
- conf->cmd = CMD_REMOVE_WWID;
+ cmd = CMD_REMOVE_WWID;
break;
case 'W':
- conf->cmd = CMD_RESET_WWIDS;
+ cmd = CMD_RESET_WWIDS;
break;
case 'a':
- conf->cmd = CMD_ADD_WWID;
+ cmd = CMD_ADD_WWID;
break;
case ':':
fprintf(stderr, "Missing option argument\n");
@@ -582,23 +620,27 @@ main (int argc, char *argv[])
exit(1);
}
+ dm_init(conf->verbosity);
if (dm_prereq())
exit(1);
dm_drv_version(conf->version, TGT_MPATH);
dm_udev_set_sync_support(1);
if (optind < argc) {
- conf->dev = MALLOC(FILE_NAME_SIZE);
+ dev = MALLOC(FILE_NAME_SIZE);
- if (!conf->dev)
+ if (!dev)
goto out;
- strncpy(conf->dev, argv[optind], FILE_NAME_SIZE);
- if (conf->dev_type != DEV_UEVENT)
- conf->dev_type = get_dev_type(conf->dev);
+ strncpy(dev, argv[optind], FILE_NAME_SIZE);
+ if (dev_type != DEV_UEVENT)
+ dev_type = get_dev_type(dev);
+ if (dev_type == DEV_NONE) {
+ condlog(0, "'%s' is not a valid argument\n", dev);
+ goto out;
+ }
}
- conf->daemon = 0;
- if (conf->dev_type == DEV_UEVENT) {
+ if (dev_type == DEV_UEVENT) {
openlog("multipath", 0, LOG_DAEMON);
setlogmask(LOG_UPTO(conf->verbosity + 3));
logsink = 1;
@@ -614,38 +656,37 @@ main (int argc, char *argv[])
conf->max_fds, strerror(errno));
}
- if (init_checkers()) {
+ if (init_checkers(conf->multipath_dir)) {
condlog(0, "failed to initialize checkers");
goto out;
}
- if (init_prio()) {
+ if (init_prio(conf->multipath_dir)) {
condlog(0, "failed to initialize prioritizers");
goto out;
}
- dm_init();
- if (conf->cmd == CMD_VALID_PATH &&
- (!conf->dev || conf->dev_type == DEV_DEVMAP)) {
+ if (cmd == CMD_VALID_PATH &&
+ (!dev || dev_type == DEV_DEVMAP)) {
condlog(0, "the -c option requires a path to check");
goto out;
}
- if (conf->cmd == CMD_VALID_PATH &&
- conf->dev_type == DEV_UEVENT) {
+ if (cmd == CMD_VALID_PATH &&
+ dev_type == DEV_UEVENT) {
int fd;
fd = mpath_connect();
if (fd == -1) {
printf("%s is not a valid multipath device path\n",
- conf->dev);
+ dev);
goto out;
}
mpath_disconnect(fd);
}
- if (conf->cmd == CMD_REMOVE_WWID && !conf->dev) {
+ if (cmd == CMD_REMOVE_WWID && !dev) {
condlog(0, "the -w option requires a device");
goto out;
}
- if (conf->cmd == CMD_RESET_WWIDS) {
+ if (cmd == CMD_RESET_WWIDS) {
struct multipath * mpp;
int i;
vector curmp;
@@ -667,8 +708,8 @@ main (int argc, char *argv[])
goto out;
}
if (conf->remove == FLUSH_ONE) {
- if (conf->dev_type == DEV_DEVMAP) {
- r = dm_suspend_and_flush_map(conf->dev);
+ if (dev_type == DEV_DEVMAP) {
+ r = dm_suspend_and_flush_map(dev);
} else
condlog(0, "must provide a map name to remove");
@@ -678,7 +719,7 @@ main (int argc, char *argv[])
r = dm_flush_maps();
goto out;
}
- while ((r = configure()) < 0)
+ while ((r = configure(cmd, dev_type, dev)) < 0)
condlog(3, "restart multipath configuration process");
out:
@@ -688,7 +729,7 @@ out:
cleanup_prio();
cleanup_checkers();
- if (conf->dev_type == DEV_UEVENT)
+ if (dev_type == DEV_UEVENT)
closelog();
out_free_config:
@@ -700,6 +741,8 @@ out_free_config:
free_config(conf);
conf = NULL;
udev_unref(udev);
+ if (dev)
+ FREE(dev);
#ifdef _DEBUG_
dbg_free_final(NULL);
#endif
diff --git a/multipath/multipath.conf.5 b/multipath/multipath.conf.5
index 2ff88c4..f542d3f 100644
--- a/multipath/multipath.conf.5
+++ b/multipath/multipath.conf.5
@@ -1,8 +1,8 @@
-.TH MULTIPATH.CONF 5 "30 November 2006"
+.TH MULTIPATH.CONF 5 2016-07-08 "Linux"
.SH NAME
-multipath.conf \- multipath daemon configuration file
+multipath.conf \- multipath daemon configuration file.
.SH DESCRIPTION
-.B "multipath.conf"
+.B "/etc/multipath.conf"
is the configuration file for the multipath daemon. It is used to
overwrite the built-in configuration table of \fBmultipathd\fP.
Any line whose first non-white-space character is a '#' is considered
@@ -25,8 +25,10 @@ The configuration file contains entries of the form:
<attribute> <value>
.I "..."
.RE
+.ft B
}
.RE
+.ft B
}
.ft R
.fi
@@ -55,8 +57,8 @@ section.
.TP
.B multipaths
This section defines the multipath topologies. They are indexed by a
-\fIWorld Wide Identifier\fR(wwid). For details on the wwid generation
-see section \fBWWID generation\fR below.
+\fIWorld Wide Identifier\fR(WWID). For details on the WWID generation
+see section \fIWWID generation\fR below.
.TP
.B devices
This section defines the device-specific settings.
@@ -68,114 +70,110 @@ device-specific settings for all devices.
.LP
.SH "defaults section"
The
-.B defaults
+.I defaults
section recognizes the following keywords:
.TP 17
+.B verbosity
+Default verbosity. Higher values increase the verbosity level. Valid
+levels are between 0 and 6.
+.RS
+.TP
+Default value is: \fB2\fR
+.RE
+.TP
.B polling_interval
-interval between two path checks in seconds. For properly functioning paths,
+Interval between two path checks in seconds. For properly functioning paths,
the interval between checks will gradually increase to
-.B max_polling_interval.
+.I max_polling_interval.
This value will be overridden by the
-.B WatchdogSec
+.I WatchdogSec
setting in the multipathd.service definition if systemd is used.
-Default is
-.I 5
-.TP
-.B max_polling_interval
-maximal interval between two path checks in seconds; default is
-.I 4 * polling_interval
+.RS
.TP
-.B multipath_dir
-directory where the dynamic shared objects are stored; default is system
-dependent, commonly
-.I /lib/multipath
+Default value is: \fB5\fR
+.RE
.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
+.B max_polling_interval
+Maximal interval between two path checks in seconds.
+.RS
.TP
-.B verbosity
-default verbosity. Higher values increase the verbosity level. Valid
-levels are between 0 and 6; default is
-.I 2
+Default value is: \fB4 * polling_interval\fR
+.RE
.TP
.B reassign_maps
-enable reassigning of device-mapper maps. With this option multipathd
+Enable reassigning of device-mapper maps. With this option multipathd
will remap existing device-mapper maps to always point to multipath
device, not the underlying block devices. Possible values are
-\fIyes\fR and \fIno\fR. Default is
-.I yes
+\fIyes\fR and \fIno\fR.
+.RS
+.TP
+Default value is: \fBno\fR
+.RE
+.TP
+.B multipath_dir
+Directory where the dynamic shared objects are stored.
+.RS
+.TP
+Default value is: \fB<system dependent>\fR, commonly \fI/lib64/multipath/\fR
+.RE
.TP
.B path_selector
The default path selector algorithm to use; they are offered by the
-kernel multipath target. There are three selector algorithms.
+kernel multipath target. There are three selector algorithms:
.RS
.TP 12
-.B "round-robin 0"
+.I "round-robin 0"
Loop through every path in the path group, sending the same amount of IO to
each.
.TP
-.B "queue-length 0"
+.I "queue-length 0"
Send the next bunch of IO down the path with the least amount of outstanding IO.
.TP
-.B "service-time 0"
+.I "service-time 0"
Choose the path for the next bunch of IO based on the amount of outstanding IO
to the path and its relative throughput.
+.TP
+Default value is: \fBservice-time 0\fR
.RE
.TP
.B path_grouping_policy
The default path grouping policy to apply to unspecified
-multipaths. Possible values are
+multipaths. Possible values are:
.RS
.TP 12
-.B failover
-1 path per priority group
+.I failover
+One path per priority group.
.TP
-.B multibus
-all paths in 1 priority group
+.I multibus
+All paths in one priority group.
.TP
-.B group_by_serial
-1 priority group per serial number
+.I group_by_serial
+One priority group per serial number.
.TP
-.B group_by_prio
-1 priority group per priority value. Priorities are determined by
+.I group_by_prio
+One priority group per priority value. Priorities are determined by
callout programs specified as a global, per-controller or
per-multipath option in the configuration file.
.TP
-.B group_by_node_name
-1 priority group per target node name. Target node names are fetched
-in /sys/class/fc_transport/target*/node_name.
+.I group_by_node_name
+One priority group per target node name. Target node names are fetched
+in \fI/sys/class/fc_transport/target*/node_name\fR.
.TP
-Default value is \fIfailover\fR.
+Default value is: \fBgroup_by_prio\fR
.RE
.TP
.B uid_attribute
-The udev attribute providing a unique path
-identifier. Default value is
-.I ID_SERIAL
+The udev attribute providing a unique path identifier.
+.RS
+.TP
+Default value is: \fBID_SERIAL\fR for SCSI devices
+.TP
+Default value is: \fBID_UID\fR for DASD devices
+.RE
.TP
.B getuid_callout
-The default program and args to callout to obtain a unique path
+(Deprecated) The default program and args to callout to obtain a unique path
identifier. Should be specified with an absolute path.
-This parameter is deprecated.
.TP
.B prio
The name of the path priority routine. The specified routine
@@ -186,46 +184,64 @@ is a valid value. Currently the following path priority routines
are implemented:
.RS
.TP 12
-.B const
+.I const
Return a constant priority of \fI1\fR.
.TP
-.B emc
-Generate the path priority for EMC arrays.
+.I sysfs
+Use the sysfs attributes \fIaccess_state\fR and \fIpreferred_path\fR to
+generate the path priority. This prioritizer accepts the optional prio_arg
+.I exclusive_pref_bit
.TP
-.B alua
+.I emc
+(Hardware-dependent)
+Generate the path priority for DGC class arrays as CLARiiON CX/AX and
+EMC VNX families.
+.TP
+.I alua
+(Hardware-dependent)
Generate the path priority based on the SCSI-3 ALUA settings. This prioritizer
-accepts the optional prio_arg
-.I exclusive_pref_bit
+accepts the optional prio_arg \fIexclusive_pref_bit\fR.
.TP
-.B ontap
-Generate the path priority for NetApp arrays.
+.I ontap
+(Hardware-dependent)
+Generate the path priority for NetApp ONTAP class and OEM arrays as IBM NSeries.
.TP
-.B rdac
-Generate the path priority for LSI/Engenio/NetApp E-Series RDAC controller.
+.I rdac
+(Hardware-dependent)
+Generate the path priority for LSI/Engenio/NetApp RDAC class as NetApp E/EF
+Series, and OEM arrays from IBM DELL SGI STK and SUN.
.TP
-.B hp_sw
-Generate the path priority for Compaq/HP controller in
-active/standby mode.
+.I hp_sw
+(Hardware-dependent)
+Generate the path priority for HP/COMPAQ/DEC HSG80 and MSA/HSV arrays with
+Active/Standby mode exclusively.
.TP
-.B hds
+.I hds
+(Hardware-dependent)
Generate the path priority for Hitachi HDS Modular storage arrays.
.TP
-.B random
+.I random
Generate a random priority between 1 and 10.
.TP 12
-.B weightedpath
-Generate the path priority based on the regular expression and the
-priority provided as argument. requires prio_args keyword.
+.I weightedpath
+Generate the path priority based on the regular expression and the
+priority provided as argument. Requires prio_args keyword.
+.TP
+.I datacore
+???. Requires prio_args keyword.
.TP
-Default value is \fBnone\fR.
+.I iet
+???. Requires prio_args keyword.
+.TP
+Default value is: \fBconst\fR
.RE
.TP
.B prio_args
Arguments to pass to to the prio function. This only applies to certain
-prioritizers
+prioritizers:
.RS
.TP 12
-.B weighted
+.I weighted
Needs a value of the form
.I "<hbtl|devname|wwn> <regex1> <prio1> <regex2> <prio2> ..."
.I hbtl
@@ -238,11 +254,21 @@ regex can be of the form
these values can be looked up through sysfs or by running
.I mulitpathd show paths format "%N:%R:%n:%r" Ex: 0x200100e08ba0aea0:0x210100e08ba0aea0:.*:.* , .*:.*:iqn.2009-10.com.redhat.msp.lab.ask-06:.*
.TP
-.B alua
+.I alua
If
.I exclusive_pref_bit
-is set, paths with the TPGS pref bit set will always be in their own path
-group.
+is set, paths with the \fIpreferred path\fR bit set will always
+be in their own path group.
+.TP
+.I datacore
+.I preferredsds
+???.
+.TP
+.I iet
+.I preferredip
+???.
+.TP
+Default value is: \fB<unset>\fR
.RE
.TP
.B features
@@ -250,82 +276,125 @@ Specify any device-mapper features to be used. Syntax is
.I num list
where
.I num
-is the number of features in
+is the number, between 0 and 6, of features in
.I list.
-Possible values for the feature list are
+Possible values for the feature list are:
.RS
.TP 12
-.B queue_if_no_path
+.I queue_if_no_path
Queue IO if no path is active; identical to the
.I no_path_retry
keyword.
.TP
-.B no_partitions
+.I no_partitions
Disable automatic partitions generation via kpartx.
+.TP
+.I pg_init_retries
+Number of times to retry pg_init, it must be between 1 and 50.
+.TP
+.I pg_init_delay_msecs
+Number of msecs before pg_init retry, it must be between 0 and 60000.
+.TP
+Default value is: \fB0\fR
.RE
.TP
.B path_checker
The default method used to determine the paths state. Possible values
-are
+are:
.RS
.TP 12
-.B readsector0
+.I readsector0
(Deprecated) Read the first sector of the device. This checker is being
-deprecated, please use \fIdirectio\fR instead
+deprecated, please use \fItur\fR instead.
.TP
-.B tur
+.I tur
Issue a
.I TEST UNIT READY
command to the device.
.TP
-.B emc_clariion
-Query the EMC Clariion specific EVPD page 0xC0 to determine the path
-state.
+.I emc_clariion
+(Hardware-dependent)
+Query the DGC/EMC specific EVPD page 0xC0 to determine the path state
+for CLARiiON CX/AX and EMC VNX arrays families.
+.TP
+.I hp_sw
+(Hardware-dependent)
+Check the path state for HP/COMPAQ/DEC HSG80 and MSA/HSV arrays with
+Active/Standby mode exclusively.
.TP
-.B hp_sw
-Check the path state for HP storage arrays with Active/Standby firmware.
+.I rdac
+(Hardware-dependent)
+Check the path state for LSI/Engenio/NetApp RDAC class as NetApp E/EF
+Series, and OEM arrays from IBM DELL SGI STK and SUN.
.TP
-.B rdac
-Check the path state for LSI/Engenio/NetApp E-Series RDAC storage controller.
+.I directio
+(Deprecated) Read the first sector with direct I/O. This checker is being
+deprecated, it could cause spurious path failures under high load.
+Please use \fItur\fR instead.
.TP
-.B directio
-Read the first sector with direct I/O.
+.I cciss_tur
+(Hardware-dependent)
+Check the path state for HP/COMPAQ Smart Array(CCISS) controllers.
.TP
-Default value is \fIdirectio\fR.
+Default value is: \fBtur\fR
+.RE
+.TP
+.B alias_prefix
+The \fIuser_friendly_names\fR prefix.
+.RS
+.TP
+Default value is: \fBmpath\fR
.RE
.TP
.B failback
Tell multipathd how to manage path group failback.
.RS
.TP 12
-.B immediate
+.I immediate
Immediately failback to the highest priority pathgroup that contains
active paths.
.TP
-.B manual
+.I manual
Do not perform automatic failback.
.TP
-.B followover
+.I followover
Only perform automatic failback when the first path of a pathgroup
becomes active. This keeps a node from automatically failing back when
another node requested the failover.
.TP
-.B values > 0
-deferred failback (time to defer in seconds)
+.I values > 0
+Deferred failback (time to defer in seconds).
.TP
-Default value is \fImanual\fR.
+Default value is: \fBimmediate\fR
.RE
.TP
.B rr_min_io
The number of IO to route to a path before switching to the next in
-the same path group. This is only for BIO based multipath. Default is
-.I 1000
+the same path group. This is only for BIO based multipath.
+.RS
+.TP
+Default value is: \fB1000\fR
+.RE
.TP
.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
-.I 1
+.RS
+.TP
+Default value is: \fB1\fR
+.RE
+.TP
+.B max_fds
+Specify the maximum number of file descriptors that can be opened by multipath
+and multipathd. This is equivalent to ulimit \-n. A value of \fImax\fR will set
+this to the system limit from \fI/proc/sys/fs/nr_open\fR. If this is not set, the
+maximum number of open fds is taken from the calling process. It is usually
+1024. To be safe, this should be set to the maximum number of paths plus 32,
+if that number is greated than 1024.
+.RS
+.TP
+Default value is: \fBmax\fR
+.RE
.TP
.B rr_weight
If set to \fIpriorities\fR the multipath configurator will assign
@@ -333,8 +402,10 @@ path weights as "path prio * rr_min_io". Possible values are
.I priorities
or
.IR uniform .
-Default is
-.IR uniform .
+.RS
+.TP
+Default value is: \fBuniform\fR
+.RE
.TP
.B no_path_retry
Specify the number of retries until disable queueing, or
@@ -342,50 +413,73 @@ Specify the number of retries until disable queueing, or
for immediate failure (no queueing),
.I queue
for never stop queueing. If unset no queueing is attempted.
-Default is unset.
+.RS
.TP
-.B user_friendly_names
-If set to
-.I yes
-, using the bindings file
-.I /etc/multipath/bindings
-to assign a persistent and unique alias to the multipath, in the form of mpath<n>.
-If set to
+Default value is: \fB<unset>\fR
+.RE
+.TP
+.B queue_without_daemon
+If set to
.I no
-use the WWID as the alias. In either case this be will
-be overridden by any specific aliases in the \fImultipaths\fR section.
-Default is
+, when multipathd stops, queueing will be turned off for all devices.
+This is useful for devices that set no_path_retry. If a machine is
+shut down while all paths to a device are down, it is possible to hang waiting
+for IO to return from the device after multipathd has been stopped. Without
+multipathd running, access to the paths cannot be restored, and the kernel
+cannot be told to stop queueing IO. Setting queue_without_daemon to
.I no
+, avoids this problem.
+.RS
+.TP
+Default value is: \fBno\fR
+.RE
+.TP
+.B checker_timeout
+Specify the timeout to use for path checkers and prioritizers that issue SCSI
+commands with an explicit timeout, in seconds.
+.RS
+.TP
+Default value is: in \fB/sys/block/sd<x>/device/timeout\fR
+.RE
.TP
.B flush_on_last_del
If set to
.I yes
, multipathd will disable queueing when the last path to a device has been
-deleted. Default is
-.I no
+deleted.
+.RS
.TP
-.B max_fds
-Specify the maximum number of file descriptors that can be opened by multipath
-and multipathd. This is equivalent to ulimit \-n. A value of \fImax\fR will set
-this to the system limit from /proc/sys/fs/nr_open. If this is not set, the
-maximum number of open fds is taken from the calling process. It is usually
-1024. To be safe, this should be set to the maximum number of paths plus 32,
-if that number is greated than 1024.
+Default value is: \fBno\fR
+.RE
.TP
-.B checker_timeout
-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<x>/device/timeout
+.B user_friendly_names
+If set to
+.I yes
+, using the bindings file
+.I /etc/multipath/bindings
+to assign a persistent and unique alias to the multipath, in the form of mpath<n>.
+If set to
+.I no
+use the WWID as the alias. In either case this be will
+be overridden by any specific aliases in the \fImultipaths\fR section.
+.RS
+.TP
+Default value is: \fBno\fR
+.RE
.TP
.B fast_io_fail_tmo
-Specify the number of seconds the scsi layer will wait after a problem has been
+Specify the number of seconds the SCSI layer will wait after a problem has been
detected on a FC remote port before failing IO to devices on that remote port.
This should be smaller than dev_loss_tmo. Setting this to
.I off
will disable the timeout.
+.RS
+.TP
+Default value is: in \fB5\fR
+.RE
.TP
.B dev_loss_tmo
-Specify the number of seconds the scsi layer will wait after a problem has
+Specify the number of seconds the SCSI layer will wait after a problem has
been detected on a FC remote port before removing it from the system. This
can be set to "infinity" which sets it to the max value of 2147483647
seconds, or 68 years. It will be automatically adjusted to the overall
@@ -393,31 +487,27 @@ retry interval
\fIno_path_retry\fR * \fIpolling_interval\fR
if a number of retries is given with \fIno_path_retry\fR and the
overall retry interval is longer than the specified \fIdev_loss_tmo\fR value.
-The linux kernel will cap this value to \fI300\fR if \fBfast_io_fail_tmo\fR
-is not set. Default is 600.
+The Linux kernel will cap this value to \fI300\fR if \fIfast_io_fail_tmo\fR
+is not set.
+.RS
.TP
-.B queue_without_daemon
-If set to
-.I no
-, when multipathd stops, queueing will be turned off for all devices.
-This is useful for devices that set no_path_retry. If a machine is
-shut down while all paths to a device are down, it is possible to hang waiting
-for IO to return from the device after multipathd has been stopped. Without
-multipathd running, access to the paths cannot be restored, and the kernel
-cannot be told to stop queueing IO. Setting queue_without_daemon to
-.I no
-, avoids this problem. Default is
-.I no
+Default value is: \fB600\fR
+.RE
.TP
.B bindings_file
-The full pathname of the binding file to be used when the user_friendly_names option is set. Defaults to
-.I /etc/multipath/bindings
+The full pathname of the binding file to be used when the user_friendly_names option is set.
+.RS
+.TP
+Default value is: \fB/etc/multipath/bindings\fR
+.RE
.TP
.B wwids_file
-The full pathname of the wwids file, which is used by multipath to keep track
-of the wwids for LUNs it has created multipath devices on in the past.
-Defaults to
-.I /etc/multipath/wwids
+The full pathname of the WWIDs file, which is used by multipath to keep track
+of the WWIDs for LUNs it has created multipath devices on in the past.
+.RS
+.TP
+Default value is: \fB/etc/multipath/wwids\fR
+.RE
.TP
.B log_checker_err
If set to
@@ -425,42 +515,81 @@ If set to
, multipathd logs the first path checker error at logging level 2. Any later
errors are logged at level 3 until the device is restored. If set to
.I always
-, multipathd always logs the path checker error at logging level 2. Default is
-.I always
+, multipathd always logs the path checker error at logging level 2.
+.RS
+.TP
+Default value is: \fBalways\fR
+.RE
.TP
.B reservation_key
This is the service action reservation key used by mpathpersist. It must be
set for all multipath devices using persistent reservations, and it must be
the same as the RESERVATION KEY field of the PERSISTENT RESERVE OUT parameter
list which contains an 8-byte value provided by the application client to the
-device server to identify the I_T nexus. It is unset by default.
+device server to identify the I_T nexus.
+.RS
+.TP
+Default value is: \fB<unset>\fR
+.RE
.TP
.B retain_attached_hw_handler
If set to
.I yes
-and the scsi layer has already attached a hardware_handler to the device,
+and the SCSI layer has already attached a hardware_handler to the device,
multipath will not force the device to use the hardware_handler specified by
-mutipath.conf. If the scsi layer has not attached a hardware handler,
-multipath will continue to use its configured hardware handler. Default is
-.I no
+mutipath.conf. If the SCSI layer has not attached a hardware handler,
+multipath will continue to use its configured hardware handler.
+.RS
+.TP
+Default value is: \fByes\fR
+.RE
.TP
.B detect_prio
If set to
.I yes
-, multipath will try to detect if the device supports ALUA. If so, the device
-will automatically use the
+, multipath will try to detect if the device supports SCSI-3 ALUA. If so, the
+device will automatically use the
+.I sysfs
+prioritizer if the required sysfs attributes
+.I access_state
+and
+.I preferred_path
+are supported, or the
.I alua
-prioritizer. If not, the prioritizer will be selected as usual. Default is
+prioritizer if not. If set to
.I no
+, the prioritizer will be selected as usual.
+.RS
+.TP
+Default value is: \fByes\fR
+.RE
.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
+multipathd checkers running in parallel causes significant CPU pressure.
+.RS
+.TP
+Default value is: \fBno\fR
+.RE
+.TP
+.B strict_timinig
+If set to
+.I yes
+, multipathd will start a new path checker loop after exactly one second,
+so that each path check will occur at exactly
+.I polling_interval
+seconds. On busy systems path checks might take longer than one second;
+here the missing ticks will be accounted for on the next round.
+A warning will be printed if path checks take longer than
+.I polling_interval
+seconds.
+.RS
+.TP
+Default value is: \fBno\fR
+.RE
.TP
.B deferred_remove
If set to
@@ -469,15 +598,31 @@ If set to
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
+will be canceled.
+.RS
+.TP
+Default value is: \fBno\fR
+.RE
+.TP
+.B partition_delimiter
+If this value is not set, when multipath renames a device, it will act just
+like the kpartx default does, only adding a \fI"p"\fR to names ending in a
+number. If this parameter is set, multipath will act like kpartx does with
+the \fI-p\fR option is used, and always add delimiter.
+.RS
+.TP
+Default value is: \fB<unset>\fR
+.RE
.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"
+information from them, just as if it was in \fI/etc/multipath.conf\fR.
+config_dir must either be "" or a fully qualified directory name.
+.RS
+.TP
+Default value is: \fB/etc/multipath/conf.d/\fR
+.RE
.TP
.B delay_watch_checks
If set to a value greater than 0, multipathd will watch paths that have
@@ -485,8 +630,11 @@ 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
+checks.
+.RS
+.TP
+Default value is: \fBno\fR
+.RE
.TP
.B delay_wait_checks
If set to a value greater than 0, when a device that has recently come back
@@ -495,39 +643,73 @@ online fails again within
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
+checks.
+.RS
.TP
-.B strict_timinig
+Default value is: \fBno\fR
+.RE
+.TP
+.B find_multipaths
If set to
.I yes
-, multipathd will start a new path checker loop after exactly one second,
-so that each path check will occur at exactly
-.I polling_interval
-seconds. On busy systems path checks might take longer than one second;
-here the missing ticks will be accounted for on the next round.
-A warning will be printed if path checks take longer than
-.I polling_interval
-seconds.
-Default is
-.I no
+, 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.
+.RS
+.TP
+Default value is: \fBno\fR
+.RE
.TP
.B uxsock_timeout
CLI receive timeout in milliseconds. For larger systems CLI commands
might timeout before the multipathd lock is released and the CLI command
can be processed. This will result in errors like
-'timeout receiving packet' to be returned from CLI commands.
+"timeout receiving packet" to be returned from CLI commands.
In these cases it is recommended to increase the CLI timeout to avoid
-those issues. The default is
-.I 1000
+those issues.
+.RS
+.TP
+Default value is: \fB1000\fR
+.RE
+.TP
+.B retrigger_tries
+Sets the number of times multipathd will try to retrigger a uevent to get the
+WWID.
+.RS
+.TP
+Default value is: \fB3\fR
+.RE
+.TP
+.B retrigger_delay
+Sets the amount of time, in seconds, to wait between retriggers.
+.RS
+.TP
+Default value is: \fB10\fR
+.RE
.TP
.B missing_uev_wait_timeout
Controls how many seconds multipathd will wait, after a new multipath device
is created, to receive a change event from udev for the device, before
automatically enabling device reloads. Usually multipathd will delay reloads
-on a device until it receives a change uevent from the initial table load. The
-default is
-.I 30
+on a device until it receives a change uevent from the initial table load.
+.RS
+.TP
+Default value is: \fB30\fR
+.RE
.
.SH "blacklist section"
The
@@ -538,20 +720,20 @@ LUNs for the array controller.
.LP
The following keywords are recognized:
.TP 17
-.B wwid
-The \fIWorld Wide Identification\fR of a device.
-.TP
.B devnode
Regular expression of the device nodes to be excluded.
.TP
+.B wwid
+The \fIWorld Wide Identification\fR of a device.
+.TP
.B property
Regular expression of the udev property to be excluded.
.TP
.B device
Subsection for the device description. This subsection recognizes the
-.I vendor
+.B vendor
and
-.I product
+.B product
keywords. For a full description of these keywords please see the
.I devices
section description.
@@ -560,7 +742,7 @@ The
.I blacklist_exceptions
section is used to revert the actions of the
.I blacklist
-section, ie to include specific device in the
+section, for example to include specific device in the
multipath topology. This allows one to selectively include devices which
would normally be excluded via the
.I blacklist
@@ -568,21 +750,24 @@ section.
.LP
The following keywords are recognized:
.TP 17
+.B devnode
+Regular expression of the device nodes to be whitelisted.
+.TP
.B wwid
The \fIWorld Wide Identification\fR of a device.
.TP
.B property
-Regular expression of the udev property to be whitelisted. Defaults to
-.I (ID_WWN|SCSI_IDENT_.*)
+Regular expression of the udev property to be whitelisted.
+.RS
.TP
-.B devnode
-Regular expression of the device nodes to be whitelisted.
+Default value is: \fB(ID_WWN|SCSI_IDENT_.*)\fR
+.RE
.TP
.B device
Subsection for the device description. This subsection recognizes the
-.I vendor
+.B vendor
and
-.I product
+.B product
keywords. For a full description of these keywords please see the
.I devices
section description.
@@ -591,27 +776,27 @@ The
.I property
blacklist and whitelist handling is different from the usual handling
in the sense that the whitelist
-.B has
+.I has
to be set, otherwise the device will be blacklisted.
In these cases the message
.I blacklisted, udev property missing
will be displayed.
.SH "multipaths section"
The only recognized attribute for the
-.B multipaths
+.I multipaths
section is the
.I multipath
subsection.
.LP
The
-.B multipath
+.I multipath
subsection recognizes the following attributes:
.TP 17
.B wwid
-Index of the container. Mandatory for this subsection.
+(Mandatory) Index of the container.
.TP
.B alias
-(Optional) symbolic name for the multipath map.
+(Optional) Symbolic name for the multipath map.
.LP
The following attributes are optional; if not set the default values
are taken from the
@@ -635,18 +820,20 @@ section:
.TP
.B rr_weight
.TP
-.B flush_on_last_del
-.TP
.B no_path_retry
.TP
.B rr_min_io
.TP
.B rr_min_io_rq
.TP
+.B flush_on_last_del
+.TP
.B features
.TP
.B reservation_key
.TP
+.B user_friendly_names
+.TP
.B deferred_remove
.TP
.B delay_watch_checks
@@ -657,7 +844,7 @@ section:
.LP
.SH "devices section"
The only recognized attribute for the
-.B devices
+.I devices
section is the
.I device
subsection.
@@ -667,38 +854,45 @@ The
subsection recognizes the following attributes:
.TP 17
.B vendor
-(Mandatory) Vendor identifier
+(Mandatory) Vendor identifier.
.TP
.B product
-(Mandatory) Product identifier
+(Mandatory) Product identifier.
.TP
.B revision
-(Optional) Revision identfier
+(Optional) Revision identfier.
.TP
.B product_blacklist
-(Optional) Product strings to blacklist for this vendor
+(Optional) Product strings to blacklist for this vendor.
.TP
.B alias_prefix
(Optional) The user_friendly_names prefix to use for this
-device type, instead of the default "mpath"
+device type, instead of the default "mpath".
.TP
.B hardware_handler
(Optional) The hardware handler to use for this device type.
The following hardware handler are implemented:
.RS
.TP 12
-.B 1 emc
-Hardware handler for EMC storage arrays.
-.TP
-.B 1 rdac
-Hardware handler for LSI/Engenio/NetApp E-Series RDAC storage controller.
-.TP
-.B 1 hp_sw
-Hardware handler for Compaq/HP storage arrays in active/standby
-mode.
-.TP
-.B 1 alua
+.I 1 emc
+(Hardware-dependent)
+Hardware handler for DGC class arrays as CLARiiON CX/AX and EMC VNX families.
+.TP
+.I 1 rdac
+(Hardware-dependent)
+Hardware handler for LSI/Engenio/NetApp RDAC class as NetApp E/EF
+Series, and OEM arrays from IBM DELL SGI STK and SUN.
+.TP
+.I 1 hp_sw
+(Hardware-dependent)
+Hardware handler for HP/COMPAQ/DEC HSG80 and MSA/HSV arrays with
+Active/Standby mode exclusively.
+.TP
+.I 1 alua
+(Hardware-dependent)
Hardware handler for SCSI-3 ALUA compatible arrays.
+.TP
+Default value is: \fB<unset>\fR
.RE
.LP
The following attributes are optional; if not set the default values
@@ -811,11 +1005,11 @@ sections:
.PD
.LP
.SH "WWID generation"
-Multipath uses a \fIWorld Wide Identification\fR (wwid) to determine
+Multipath uses a \fIWorld Wide Identification\fR (WWID) to determine
which paths belong to the same device. Each path presenting the same
-wwid is assumed to point to the same device.
+WWID is assumed to point to the same device.
.LP
-The wwid is generated by three methods (in the order of preference):
+The WWID is generated by three methods (in the order of preference):
.TP 17
.B getuid_callout
Use the specified external program; cf \fIgetuid_callout\fR above.
@@ -833,35 +1027,36 @@ variable.
.B vpd_pg83
If none of the \fIgetuid_callout\fR or \fIuid_attribute\fR parameters
are present multipath will try to use the sysfs attribute
-\fIvpd_pg83\fR to generate the wwid.
+\fIvpd_pg83\fR to generate the WWID.
.SH "KNOWN ISSUES"
The usage of
-.B queue_if_no_path
+.I queue_if_no_path
option can lead to
-.B D state
+.I D state
processes being hung and not killable in situations where all the paths to the LUN go offline.
It is advisable to use the
-.B no_path_retry
+.I no_path_retry
option instead.
.P
The use of
-.B queue_if_no_path
+.I queue_if_no_path
or
-.B no_path_retry
+.I no_path_retry
might lead to a deadlock if the
-.B dev_loss_tmo
+.I dev_loss_tmo
setting results in a device being removed while I/O is still queued.
The multipath daemon will update the
-.B dev_loss_tmo
+.I dev_loss_tmo
setting accordingly to avoid this deadlock. Hence if both values are
specified the order of precedence is
-.I no_path_retry, queue_if_no_path, dev_loss_tmo
+.I no_path_retry, queue_if_no_path, dev_loss_tmo.
.SH "SEE ALSO"
.BR udev (8),
-.BR dmsetup (8)
-.BR multipath (8)
-.BR multipathd (8)
+.BR dmsetup (8),
+.BR multipath (8),
+.BR multipathd (8).
+
.SH AUTHORS
-.B multipath
+.I multipath-tools
was developed by Christophe Varoqui, <christophe.varoqui@opensvc.com> and others.
diff --git a/multipath/multipath.init.suse b/multipath/multipath.init.suse
deleted file mode 100644
index de1cc1f..0000000
--- a/multipath/multipath.init.suse
+++ /dev/null
@@ -1,158 +0,0 @@
-#! /bin/sh
-# Copyright (c) 2005 SuSE GmbH Nuernberg, Germany.
-#
-# Author: Hannes Reinecke <feedback@suse.de>
-#
-# init.d/boot.multipath
-#
-### BEGIN INIT INFO
-# Provides: boot.multipath
-# Required-Start: boot.device-mapper boot.udev
-# Required-Stop: boot.device-mapper boot.udev
-# Should-Start: boot.xdrsetsite
-# Should-Stop: boot.xdrsetsite
-# Default-Start: B
-# Default-Stop:
-# Short-Description: Create multipath device targets
-# Description: Setup initial multipath device-mapper targets
-### END INIT INFO
-
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-PROGRAM=/sbin/multipath
-
-# Set the maximum number of open files
-MAX_OPEN_FDS=4096
-
-# Number of seconds to wait for disks and partitions
-MPATH_DEVICE_TIMEOUT=30
-
-test -x $PROGRAM || exit 5
-
-# Shell functions sourced from /etc/rc.status:
-# rc_check check and set local and overall rc status
-# rc_status check and set local and overall rc status
-# rc_status -v ditto but be verbose in local rc status
-# rc_status -v -r ditto and clear the local rc status
-# rc_failed set local and overall rc status to failed
-# rc_reset clear local rc status (overall remains)
-# rc_exit exit appropriate to overall rc status
-. /etc/rc.status
-
-# First reset status of this service
-rc_reset
-
-# Return values acc. to LSB for all commands but status:
-# 0 - success
-# 1 - misc error
-# 2 - invalid or excess args
-# 3 - unimplemented feature (e.g. reload)
-# 4 - insufficient privilege
-# 5 - program not installed
-# 6 - program not configured
-# 7 - program is not running
-#
-# Note that starting an already running service, stopping
-# or restarting a not-running service as well as the restart
-# with force-reload (in case signalling is not supported) are
-# considered a success.
-
-case "$1" in
- start)
- # Check for existing multipath mappings
- if dmsetup table --target multipath | grep -q multipath ; then
- # Multipath active, start daemon
- exec /etc/init.d/multipathd $1
- fi
-
- echo -n "Creating multipath targets:"
- # Check whether multipath daemon is already running
- if /sbin/multipathd -k"list paths" > /dev/null 2>&1 ; then
- echo -n " (multipathd running)"
- rc_status -v
- rc_exit
- fi
- # Load prerequisite module
- modprobe dm-multipath
-
- # Set the maximum number of open files
- if [ -n "$MAX_OPEN_FDS" ] ; then
- ulimit -n $MAX_OPEN_FDS
- fi
-
- # Start the program directly as checkproc doesn't work here
- $PROGRAM -v 0
- echo -n " (waiting for udev)"
- # Wait for all multipathed devices to appear
- maplist=$(/sbin/dmsetup ls --target multipath | sed '/No devices/d' | sed -n 's/\(^[^ ()]*\)[\t ]*.*/\1/p')
- wait=$MPATH_DEVICE_TIMEOUT
- while [ $wait -gt 0 ] ; do
- num=0
- for map in $maplist; do
- [ -e /dev/disk/by-id/dm-name-$map ] && continue
- num=$((num + 1))
- done
- [ $num -eq 0 ] && break
- wait=$((wait - 1))
- sleep 1;
- done
- if [ $wait -le 0 ] ; then
- echo -n " timeout: $num devices left"
- rc_failed 1
- else
- # Reset to wait for partitions
- wait=$MPATH_DEVICE_TIMEOUT
- fi
- # Wait for all partitions on multipathed devices
- while [ $wait -gt 0 ] ; do
- num=0
- for map in $maplist ; do
- [ -e /dev/disk/by-id/dm-name-$map ] || continue
- partlist=$(/sbin/kpartx -l -p _part /dev/disk/by-id/dm-name-$map | sed 's/\([^ ]*\) :.*/\1/p')
- for part in $partlist; do
- [ -e /dev/disk/by-id/dm-name-$part ] && continue
- num=$((num + 1))
- done
- done
- [ $num -eq 0 ] && break
- wait=$((wait - 1))
- sleep 1;
- done
- if [ $wait -le 0 ] ; then
- echo -n "timeout: $num partitions left"
- rc_failed 1
- fi
-
- # Remember status and be verbose
- rc_status -v
- ;;
- stop)
- echo -n "Removing multipath targets:"
-
- # Flush all existing maps
- $PROGRAM -F
-
- rc_failed 0
- rc_status -v
- ;;
- status)
- echo -n "Checking multipath targets: "
- # Display active multipath tables
- tblnum=$(/sbin/dmsetup ls --target multipath | sed '/No devices/d' | wc --lines)
- if [ "$tblnum" ] && [ $tblnum -gt 0 ] ; then
- echo -n "($tblnum multipath devices) "
- rc_failed 0
- else
- rc_failed 3
- fi
- rc_status -v
- ;;
- restart)
- $0 stop
- $0 start
- ;;
- *)
- echo "Usage: $0 {start|stop|status|restart}"
- exit 1
- ;;
-esac
-rc_exit
diff --git a/multipathd/Makefile b/multipathd/Makefile
index 9b0210f..092b74b 100644
--- a/multipathd/Makefile
+++ b/multipathd/Makefile
@@ -9,7 +9,7 @@ CFLAGS += -I$(multipathdir) -I$(mpathpersistdir) -I$(mpathcmddir)
ifdef SYSTEMD
CFLAGS += -DUSE_SYSTEMD=$(SYSTEMD)
endif
-LDFLAGS += -lpthread -ldevmapper -lreadline
+LDFLAGS += -lurcu -lpthread -ldevmapper -lreadline
ifdef SYSTEMD
ifeq ($(shell test $(SYSTEMD) -gt 209 && echo 1), 1)
LDFLAGS += -lsystemd
@@ -46,7 +46,6 @@ $(EXEC): $(OBJS)
install:
$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
- $(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir)
ifdef SYSTEMD
$(INSTALL_PROGRAM) -d $(DESTDIR)$(unitdir)
$(INSTALL_PROGRAM) -m 644 $(EXEC).service $(DESTDIR)$(unitdir)
@@ -56,12 +55,10 @@ endif
$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
uninstall:
- rm -f $(DESTDIR)$(bindir)/$(EXEC)
- rm -f $(DESTDIR)$(rcdir)/$(EXEC)
- rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
- rm -f $(DESTDIR)$(unitdir)/$(EXEC).service
- rm -f $(DESTDIR)$(unitdir)/$(EXEC).socket
+ $(RM) $(DESTDIR)$(bindir)/$(EXEC)
+ $(RM) $(DESTDIR)$(mandir)/$(EXEC).8.gz
+ $(RM) $(DESTDIR)$(unitdir)/$(EXEC).service
+ $(RM) $(DESTDIR)$(unitdir)/$(EXEC).socket
clean:
- rm -f core *.o $(EXEC) *.gz
-
+ $(RM) core *.o $(EXEC) *.gz
diff --git a/multipathd/cli.c b/multipathd/cli.c
index d991cd0..3663c0a 100644
--- a/multipathd/cli.c
+++ b/multipathd/cli.c
@@ -4,13 +4,13 @@
#include <sys/time.h>
#include <errno.h>
#include <pthread.h>
-#include <memory.h>
-#include <vector.h>
-#include <structs.h>
-#include <structs_vec.h>
-#include <parser.h>
-#include <util.h>
-#include <version.h>
+#include "memory.h"
+#include "vector.h"
+#include "structs.h"
+#include "structs_vec.h"
+#include "parser.h"
+#include "util.h"
+#include "version.h"
#include <readline/readline.h>
#include "cli.h"
@@ -109,7 +109,7 @@ set_handler_callback (uint64_t fp, int (*fn)(void *, char **, int *, void *))
}
int
-set_unlocked_handler_callback (unsigned long fp,int (*fn)(void *, char **, int *, void *))
+set_unlocked_handler_callback (uint64_t fp,int (*fn)(void *, char **, int *, void *))
{
struct handler * h = find_handler(fp);
@@ -207,6 +207,7 @@ load_keys (void)
r += add_key(keys, "setprstatus", SETPRSTATUS, 0);
r += add_key(keys, "unsetprstatus", UNSETPRSTATUS, 0);
r += add_key(keys, "format", FMT, 1);
+ r += add_key(keys, "json", JSON, 0);
if (r) {
free_keys(keys);
@@ -496,7 +497,7 @@ parse_cmd (char * cmd, char ** reply, int * len, void * data, int timeout )
pthread_testcancel();
r = h->fn(cmdvec, reply, len, data);
}
- lock_cleanup_pop(vecs->lock);
+ pthread_cleanup_pop(!r);
} else
r = h->fn(cmdvec, reply, len, data);
free_keys(cmdvec);
@@ -537,8 +538,10 @@ cli_init (void) {
add_handler(LIST+MAPS+FMT, NULL);
add_handler(LIST+MAPS+RAW+FMT, NULL);
add_handler(LIST+MAPS+TOPOLOGY, NULL);
+ add_handler(LIST+MAPS+JSON, NULL);
add_handler(LIST+TOPOLOGY, NULL);
add_handler(LIST+MAP+TOPOLOGY, NULL);
+ add_handler(LIST+MAP+JSON, NULL);
add_handler(LIST+MAP+FMT, NULL);
add_handler(LIST+MAP+RAW+FMT, NULL);
add_handler(LIST+CONFIG, NULL);
@@ -685,4 +688,3 @@ key_generator (const char * str, int state)
*/
return ((char *)NULL);
}
-
diff --git a/multipathd/cli.h b/multipathd/cli.h
index 84ca40f..92cb41b 100644
--- a/multipathd/cli.h
+++ b/multipathd/cli.h
@@ -36,6 +36,7 @@ enum {
__SETPRSTATUS,
__UNSETPRSTATUS,
__FMT,
+ __JSON,
};
#define LIST (1 << __LIST)
@@ -74,6 +75,7 @@ enum {
#define SETPRSTATUS (1ULL << __SETPRSTATUS)
#define UNSETPRSTATUS (1ULL << __UNSETPRSTATUS)
#define FMT (1ULL << __FMT)
+#define JSON (1ULL << __JSON)
#define INITIAL_REPLY_LEN 1200
diff --git a/multipathd/cli_handlers.c b/multipathd/cli_handlers.c
index 8b3cb9d..8ff4362 100644
--- a/multipathd/cli_handlers.c
+++ b/multipathd/cli_handlers.c
@@ -1,23 +1,23 @@
/*
* Copyright (c) 2005 Christophe Varoqui
*/
-#include <checkers.h>
-#include <memory.h>
-#include <vector.h>
-#include <structs.h>
-#include <structs_vec.h>
+#include "checkers.h"
+#include "memory.h"
+#include "vector.h"
+#include "structs.h"
+#include "structs_vec.h"
#include <libdevmapper.h>
-#include <devmapper.h>
-#include <discovery.h>
-#include <config.h>
-#include <configure.h>
-#include <blacklist.h>
-#include <debug.h>
-#include <print.h>
-#include <sysfs.h>
+#include "devmapper.h"
+#include "discovery.h"
+#include "config.h"
+#include "configure.h"
+#include "blacklist.h"
+#include "debug.h"
+#include "print.h"
+#include "sysfs.h"
#include <errno.h>
#include <libudev.h>
-#include <util.h>
+#include "util.h"
#include "main.h"
#include "cli.h"
@@ -127,7 +127,7 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs)
char * reply;
unsigned int maxlen = INITIAL_REPLY_LEN;
int again = 1;
-
+
get_path_layout(vecs->pathvec, 0);
reply = MALLOC(maxlen);
@@ -156,51 +156,122 @@ show_maps_topology (char ** r, int * len, struct vectors * vecs)
}
int
+show_maps_json (char ** r, int * len, struct vectors * vecs)
+{
+ int i;
+ struct multipath * mpp;
+ char * c;
+ char * reply;
+ unsigned int maxlen = INITIAL_REPLY_LEN *
+ PRINT_JSON_MULTIPLIER * VECTOR_SIZE(vecs->mpvec);
+ int again = 1;
+
+ vector_foreach_slot(vecs->mpvec, mpp, i) {
+ if (update_multipath(vecs, mpp->alias, 0)) {
+ return 1;
+ }
+ }
+
+ reply = MALLOC(maxlen);
+
+ while (again) {
+ if (!reply)
+ return 1;
+
+ c = reply;
+
+ c += snprint_multipath_topology_json(c, maxlen, vecs);
+ again = ((c - reply) == maxlen);
+
+ REALLOC_REPLY(reply, again, maxlen);
+ }
+ *r = reply;
+ *len = (int)(c - reply);
+ return 0;
+}
+
+int
+show_map_json (char ** r, int * len, struct multipath * mpp,
+ struct vectors * vecs)
+{
+ char * c;
+ char * reply;
+ unsigned int maxlen = INITIAL_REPLY_LEN;
+ int again = 1;
+
+ if (update_multipath(vecs, mpp->alias, 0))
+ return 1;
+ reply = MALLOC(maxlen);
+
+ while (again) {
+ if (!reply)
+ return 1;
+
+ c = reply;
+
+ c += snprint_multipath_map_json(c, maxlen, mpp, 1);
+ again = ((c - reply) == maxlen);
+
+ REALLOC_REPLY(reply, again, maxlen);
+ }
+ *r = reply;
+ *len = (int)(c - reply);
+ return 0;
+}
+
+int
show_config (char ** r, int * len)
{
char * c;
char * reply;
unsigned int maxlen = INITIAL_REPLY_LEN;
int again = 1;
+ struct config *conf;
c = reply = MALLOC(maxlen);
+ conf = get_multipath_config();
while (again) {
- if (!reply)
+ if (!reply) {
+ put_multipath_config(conf);
return 1;
+ }
c = reply;
- c += snprint_defaults(c, reply + maxlen - c);
+ c += snprint_defaults(conf, c, reply + maxlen - c);
again = ((c - reply) == maxlen);
REALLOC_REPLY(reply, again, maxlen);
if (again)
continue;
- c += snprint_blacklist(c, reply + maxlen - c);
+ c += snprint_blacklist(conf, c, reply + maxlen - c);
again = ((c - reply) == maxlen);
REALLOC_REPLY(reply, again, maxlen);
if (again)
continue;
- c += snprint_blacklist_except(c, reply + maxlen - c);
+ c += snprint_blacklist_except(conf, c, reply + maxlen - c);
again = ((c - reply) == maxlen);
REALLOC_REPLY(reply, again, maxlen);
if (again)
continue;
- c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable);
+ c += snprint_hwtable(conf, c, reply + maxlen - c,
+ conf->hwtable);
again = ((c - reply) == maxlen);
REALLOC_REPLY(reply, again, maxlen);
if (again)
continue;
- c += snprint_overrides(c, reply + maxlen - c, conf->overrides);
+ c += snprint_overrides(conf, c, reply + maxlen - c,
+ conf->overrides);
again = ((c - reply) == maxlen);
REALLOC_REPLY(reply, again, maxlen);
if (again)
continue;
if (VECTOR_SIZE(conf->mptable) > 0) {
- c += snprint_mptable(c, reply + maxlen - c,
+ c += snprint_mptable(conf, c, reply + maxlen - c,
conf->mptable);
again = ((c - reply) == maxlen);
REALLOC_REPLY(reply, again, maxlen);
}
}
+ put_multipath_config(conf);
*r = reply;
*len = (int)(c - reply + 1);
return 0;
@@ -267,7 +338,7 @@ cli_list_map_topology (void * v, char ** reply, int * len, void * data)
struct multipath * mpp;
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);
@@ -291,6 +362,35 @@ cli_list_maps_topology (void * v, char ** reply, int * len, void * data)
}
int
+cli_list_map_json (void * v, char ** reply, int * len, void * data)
+{
+ struct multipath * mpp;
+ 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);
+
+ if (!mpp)
+ return 1;
+
+ condlog(3, "list multipath json %s (operator)", param);
+
+ return show_map_json(reply, len, mpp, vecs);
+}
+
+int
+cli_list_maps_json (void * v, char ** reply, int * len, void * data)
+{
+ struct vectors * vecs = (struct vectors *)data;
+
+ condlog(3, "list multipaths json (operator)");
+
+ return show_maps_json(reply, len, vecs);
+}
+
+int
cli_list_wildcards (void * v, char ** reply, int * len, void * data)
{
char * c;
@@ -528,29 +628,35 @@ cli_add_path (void * v, char ** reply, int * len, void * data)
char * param = get_keyparam(v, PATH);
struct path *pp;
int r;
+ struct config *conf;
param = convert_dev(param, 1);
condlog(2, "%s: add path (operator)", param);
-
+ conf = get_multipath_config();
if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
- param) > 0)
+ param) > 0) {
+ put_multipath_config(conf);
goto blacklisted;
+ }
pp = find_path_by_dev(vecs->pathvec, param);
if (pp) {
condlog(2, "%s: path already in pathvec", param);
- if (pp->mpp)
+ if (pp->mpp) {
+ put_multipath_config(conf);
return 0;
+ }
} else {
struct udev_device *udevice;
- udevice = udev_device_new_from_subsystem_sysname(conf->udev,
+ udevice = udev_device_new_from_subsystem_sysname(udev,
"block",
param);
- r = store_pathinfo(vecs->pathvec, conf->hwtable,
+ r = store_pathinfo(vecs->pathvec, conf,
udevice, DI_ALL, &pp);
udev_device_unref(udevice);
if (!pp) {
+ put_multipath_config(conf);
if (r == 2)
goto blacklisted;
condlog(0, "%s: failed to store path info", param);
@@ -558,6 +664,7 @@ cli_add_path (void * v, char ** reply, int * len, void * data)
}
pp->checkint = conf->checkint;
}
+ put_multipath_config(conf);
return ev_add_path(pp, vecs);
blacklisted:
*reply = strdup("blacklisted\n");
@@ -592,16 +699,20 @@ cli_add_map (void * v, char ** reply, int * len, void * data)
char dev_path[PATH_SIZE];
char *alias, *refwwid;
int rc, count = 0;
+ struct config *conf;
param = convert_dev(param, 0);
condlog(2, "%s: add map (operator)", param);
+ conf = get_multipath_config();
if (filter_wwid(conf->blist_wwid, conf->elist_wwid, param, NULL) > 0) {
+ put_multipath_config(conf);
*reply = strdup("blacklisted\n");
*len = strlen(*reply) + 1;
condlog(2, "%s: map blacklisted", param);
return 1;
}
+ put_multipath_config(conf);
do {
minor = dm_get_minor(param);
if (minor < 0)
@@ -615,13 +726,14 @@ cli_add_map (void * v, char ** reply, int * len, void * data)
if (!alias && !count) {
condlog(2, "%s: mapname not found for %d:%d",
param, major, minor);
- rc = get_refwwid(param, DEV_DEVMAP, vecs->pathvec,
- &refwwid);
+ rc = get_refwwid(CMD_NONE, param, DEV_DEVMAP,
+ vecs->pathvec, &refwwid);
if (refwwid) {
- if (coalesce_paths(vecs, NULL, refwwid, 0))
+ if (coalesce_paths(vecs, NULL, refwwid, 0, 1))
condlog(2, "%s: coalesce_paths failed",
param);
dm_lib_release();
+ FREE(refwwid);
}
} /*we attempt to create device only once*/
count++;
@@ -633,7 +745,6 @@ cli_add_map (void * v, char ** reply, int * len, void * data)
}
rc = ev_add_map(dev_path, alias, vecs);
FREE(alias);
- FREE(refwwid);
return rc;
}
@@ -696,7 +807,7 @@ cli_reload(void *v, char **reply, int *len, void *data)
return 1;
}
- return reload_map(vecs, mpp, 0);
+ return reload_map(vecs, mpp, 0, 1);
}
int resize_map(struct multipath *mpp, unsigned long long size,
@@ -709,7 +820,7 @@ int resize_map(struct multipath *mpp, unsigned long long size,
update_mpp_paths(mpp, vecs->pathvec);
setup_map(mpp, params, PARAMS_SIZE);
mpp->action = ACT_RESIZE;
- if (domap(mpp, params) <= 0) {
+ if (domap(mpp, params, 1) <= 0) {
condlog(0, "%s: failed to resize map : %s", mpp->alias,
strerror(errno));
mpp->size = orig_size;
@@ -787,18 +898,24 @@ cli_resize(void *v, char **reply, int *len, void *data)
int
cli_force_no_daemon_q(void * v, char ** reply, int * len, void * data)
{
+ struct config *conf = get_multipath_config();
+
condlog(2, "force queue_without_daemon (operator)");
if (conf->queue_without_daemon == QUE_NO_DAEMON_OFF)
conf->queue_without_daemon = QUE_NO_DAEMON_FORCE;
+ put_multipath_config(conf);
return 0;
}
int
cli_restore_no_daemon_q(void * v, char ** reply, int * len, void * data)
{
+ struct config *conf = get_multipath_config();
+
condlog(2, "restore queue_without_daemon (operator)");
if (conf->queue_without_daemon == QUE_NO_DAEMON_FORCE)
conf->queue_without_daemon = QUE_NO_DAEMON_OFF;
+ put_multipath_config(conf);
return 0;
}
@@ -827,8 +944,11 @@ cli_restore_queueing(void *v, char **reply, int *len, void *data)
dm_queue_if_no_path(mpp->alias, 1);
if (mpp->nr_active > 0)
mpp->retry_tick = 0;
- else
+ else {
+ struct config *conf = get_multipath_config();
mpp->retry_tick = mpp->no_path_retry * conf->checkint;
+ put_multipath_config(conf);
+ }
}
return 0;
}
@@ -847,8 +967,11 @@ cli_restore_all_queueing(void *v, char **reply, int *len, void *data)
dm_queue_if_no_path(mpp->alias, 1);
if (mpp->nr_active > 0)
mpp->retry_tick = 0;
- else
+ else {
+ struct config *conf = get_multipath_config();
mpp->retry_tick = mpp->no_path_retry * conf->checkint;
+ put_multipath_config(conf);
+ }
}
}
return 0;
@@ -1061,21 +1184,25 @@ show_blacklist (char ** r, int * len)
char *reply = NULL;
unsigned int maxlen = INITIAL_REPLY_LEN;
int again = 1;
+ struct config *conf = get_multipath_config();
reply = MALLOC(maxlen);
while (again) {
- if (!reply)
+ if (!reply) {
+ put_multipath_config(conf);
return 1;
+ }
c = reply;
- c += snprint_blacklist_report(c, maxlen);
+ c += snprint_blacklist_report(conf, c, maxlen);
again = ((c - reply) == maxlen);
REALLOC_REPLY(reply, again, maxlen);
}
*r = reply;
*len = (int)(c - reply + 1);
+ put_multipath_config(conf);
return 0;
}
@@ -1095,21 +1222,25 @@ show_devices (char ** r, int * len, struct vectors *vecs)
char *reply = NULL;
unsigned int maxlen = INITIAL_REPLY_LEN;
int again = 1;
+ struct config *conf = get_multipath_config();
reply = MALLOC(maxlen);
while (again) {
- if (!reply)
+ if (!reply) {
+ put_multipath_config(conf);
return 1;
+ }
c = reply;
- c += snprint_devices(c, maxlen, vecs);
+ c += snprint_devices(conf, c, maxlen, vecs);
again = ((c - reply) == maxlen);
REALLOC_REPLY(reply, again, maxlen);
}
*r = reply;
*len = (int)(c - reply + 1);
+ put_multipath_config(conf);
return 0;
}
diff --git a/multipathd/cli_handlers.h b/multipathd/cli_handlers.h
index 5d51018..19e003d 100644
--- a/multipathd/cli_handlers.h
+++ b/multipathd/cli_handlers.h
@@ -13,6 +13,8 @@ int cli_list_maps_status (void * v, char ** reply, int * len, void * data);
int cli_list_maps_stats (void * v, char ** reply, int * len, void * data);
int cli_list_map_topology (void * v, char ** reply, int * len, void * data);
int cli_list_maps_topology (void * v, char ** reply, int * len, void * data);
+int cli_list_map_json (void * v, char ** reply, int * len, void * data);
+int cli_list_maps_json (void * v, char ** reply, int * len, void * data);
int cli_list_config (void * v, char ** reply, int * len, void * data);
int cli_list_blacklist (void * v, char ** reply, int * len, void * data);
int cli_list_devices (void * v, char ** reply, int * len, void * data);
@@ -41,4 +43,3 @@ int cli_reassign (void * v, char ** reply, int * len, void * data);
int cli_getprstatus(void * v, char ** reply, int * len, void * data);
int cli_setprstatus(void * v, char ** reply, int * len, void * data);
int cli_unsetprstatus(void * v, char ** reply, int * len, void * data);
-
diff --git a/multipathd/main.c b/multipathd/main.c
index 58e8854..8784307 100644
--- a/multipathd/main.c
+++ b/multipathd/main.c
@@ -7,7 +7,7 @@
#include <unistd.h>
#include <sys/stat.h>
#include <libdevmapper.h>
-#include <wait.h>
+#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
@@ -17,18 +17,17 @@
#include <limits.h>
#include <linux/oom.h>
#include <libudev.h>
+#include <urcu.h>
#ifdef USE_SYSTEMD
#include <systemd/sd-daemon.h>
#endif
#include <semaphore.h>
-#include <mpath_cmd.h>
-#include <mpath_persist.h>
#include <time.h>
/*
* libcheckers
*/
-#include <checkers.h>
+#include "checkers.h"
#ifdef USE_SYSTEMD
static int use_watchdog;
@@ -39,32 +38,36 @@ int uxsock_timeout;
/*
* libmultipath
*/
-#include <parser.h>
-#include <vector.h>
-#include <memory.h>
-#include <config.h>
-#include <util.h>
-#include <hwtable.h>
-#include <defaults.h>
-#include <structs.h>
-#include <blacklist.h>
-#include <structs_vec.h>
-#include <dmparser.h>
-#include <devmapper.h>
-#include <sysfs.h>
-#include <dict.h>
-#include <discovery.h>
-#include <debug.h>
-#include <propsel.h>
-#include <uevent.h>
-#include <switchgroup.h>
-#include <print.h>
-#include <configure.h>
-#include <prio.h>
-#include <wwids.h>
-#include <pgpolicies.h>
-#include <uevent.h>
-#include <log.h>
+#include "parser.h"
+#include "vector.h"
+#include "memory.h"
+#include "config.h"
+#include "util.h"
+#include "hwtable.h"
+#include "defaults.h"
+#include "structs.h"
+#include "blacklist.h"
+#include "structs_vec.h"
+#include "dmparser.h"
+#include "devmapper.h"
+#include "sysfs.h"
+#include "dict.h"
+#include "discovery.h"
+#include "debug.h"
+#include "propsel.h"
+#include "uevent.h"
+#include "switchgroup.h"
+#include "print.h"
+#include "configure.h"
+#include "prio.h"
+#include "wwids.h"
+#include "pgpolicies.h"
+#include "uevent.h"
+#include "log.h"
+
+#include "mpath_cmd.h"
+#include "mpath_persist.h"
+
#include "prioritizers/alua_rtpg.h"
#include "main.h"
@@ -97,6 +100,9 @@ struct mpath_event_param
unsigned int mpath_mx_alloc_len;
int logsink;
+int verbosity;
+int bindings_read_only;
+int ignore_new_devs;
enum daemon_status running_state = DAEMON_INIT;
pid_t daemon_pid;
pthread_mutex_t config_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -109,6 +115,8 @@ struct vectors * gvecs;
struct udev * udev;
+struct config *multipath_conf;
+
const char *
daemon_status(void)
{
@@ -197,12 +205,24 @@ int set_config_state(enum daemon_status state)
return rc;
}
+struct config *get_multipath_config(void)
+{
+ rcu_read_lock();
+ return rcu_dereference(multipath_conf);
+}
+
+void put_multipath_config(struct config *conf)
+{
+ rcu_read_unlock();
+}
+
static int
need_switch_pathgroup (struct multipath * mpp, int refresh)
{
struct pathgroup * pgp;
struct path * pp;
unsigned int i, j;
+ struct config *conf;
if (!mpp || mpp->pgfailback == -FAILBACK_MANUAL)
return 0;
@@ -210,10 +230,15 @@ need_switch_pathgroup (struct multipath * mpp, int refresh)
/*
* Refresh path priority values
*/
- if (refresh)
- vector_foreach_slot (mpp->pg, pgp, i)
- vector_foreach_slot (pgp->paths, pp, j)
- pathinfo(pp, conf->hwtable, DI_PRIO);
+ if (refresh) {
+ vector_foreach_slot (mpp->pg, pgp, i) {
+ vector_foreach_slot (pgp->paths, pp, j) {
+ conf = get_multipath_config();
+ pathinfo(pp, conf, DI_PRIO);
+ put_multipath_config(conf);
+ }
+ }
+ }
if (!mpp->pg || VECTOR_SIZE(mpp->paths) == 0)
return 0;
@@ -240,8 +265,12 @@ coalesce_maps(struct vectors *vecs, vector nmpv)
{
struct multipath * ompp;
vector ompv = vecs->mpvec;
- unsigned int i;
+ unsigned int i, reassign_maps;
+ struct config *conf;
+ conf = get_multipath_config();
+ reassign_maps = conf->reassign_maps;
+ put_multipath_config(conf);
vector_foreach_slot (ompv, ompp, i) {
condlog(3, "%s: coalesce map", ompp->alias);
if (!find_mp_by_wwid(nmpv, ompp->wwid)) {
@@ -271,7 +300,7 @@ coalesce_maps(struct vectors *vecs, vector nmpv)
dm_lib_release();
condlog(2, "%s devmap removed", ompp->alias);
}
- } else if (conf->reassign_maps) {
+ } else if (reassign_maps) {
condlog(3, "%s: Reassign existing device-mapper"
" devices", ompp->alias);
dm_reassign(ompp->alias);
@@ -292,7 +321,7 @@ 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 ||
+ if (pp->state == PATH_UNCHECKED ||
pp->state == PATH_WILD ||
pp->state == PATH_DELAYED)
continue;
@@ -379,7 +408,7 @@ retry:
retries = -1;
goto fail;
}
- if (domap(mpp, params) <= 0 && retries-- > 0) {
+ if (domap(mpp, params, 1) <= 0 && retries-- > 0) {
condlog(0, "%s: map_udate sleep", mpp->alias);
sleep(1);
goto retry;
@@ -431,7 +460,8 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
char * refwwid;
struct multipath * mpp;
int map_present;
- int r = 1;
+ int r = 1, delayed_reconfig, reassign_maps;
+ struct config *conf;
map_present = dm_map_present(alias);
@@ -448,9 +478,13 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
/* setup multipathd removed the map */
return 1;
}
+ conf = get_multipath_config();
+ delayed_reconfig = conf->delayed_reconfig;
+ reassign_maps = conf->reassign_maps;
+ put_multipath_config(conf);
if (mpp->wait_for_udev) {
mpp->wait_for_udev = 0;
- if (conf->delayed_reconfig &&
+ if (delayed_reconfig &&
!need_to_delay_reconfig(vecs)) {
condlog(2, "reconfigure (delayed)");
set_config_state(DAEMON_CONFIGURE);
@@ -462,7 +496,7 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
* if we create a multipath mapped device as a result
* of uev_add_path
*/
- if (conf->reassign_maps) {
+ if (reassign_maps) {
condlog(3, "%s: Reassign existing device-mapper devices",
alias);
dm_reassign(alias);
@@ -484,10 +518,10 @@ ev_add_map (char * dev, char * alias, struct vectors * vecs)
return 1;
}
}
- r = get_refwwid(dev, DEV_DEVMAP, vecs->pathvec, &refwwid);
+ r = get_refwwid(CMD_NONE, dev, DEV_DEVMAP, vecs->pathvec, &refwwid);
if (refwwid) {
- r = coalesce_paths(vecs, NULL, refwwid, 0);
+ r = coalesce_paths(vecs, NULL, refwwid, 0, CMD_NONE);
dm_lib_release();
}
@@ -567,6 +601,7 @@ uev_add_path (struct uevent *uev, struct vectors * vecs)
{
struct path *pp;
int ret = 0, i;
+ struct config *conf;
condlog(2, "%s: add path (uevent)", uev->kernel);
if (strstr(uev->kernel, "..") != NULL) {
@@ -590,8 +625,10 @@ uev_add_path (struct uevent *uev, struct vectors * vecs)
condlog(3, "%s: reinitialize path", uev->kernel);
udev_device_unref(pp->udev);
pp->udev = udev_device_ref(uev->udev);
- r = pathinfo(pp, conf->hwtable,
+ conf = get_multipath_config();
+ r = pathinfo(pp, conf,
DI_ALL | DI_BLACKLIST);
+ put_multipath_config(conf);
if (r == PATHINFO_OK)
ret = ev_add_path(pp, vecs);
else if (r == PATHINFO_SKIPPED) {
@@ -615,8 +652,10 @@ uev_add_path (struct uevent *uev, struct vectors * vecs)
/*
* get path vital state
*/
- ret = alloc_path_with_pathinfo(conf->hwtable, uev->udev,
+ conf = get_multipath_config();
+ ret = alloc_path_with_pathinfo(conf, uev->udev,
DI_ALL, &pp);
+ put_multipath_config(conf);
if (!pp) {
if (ret == PATHINFO_SKIPPED)
return 0;
@@ -628,7 +667,9 @@ uev_add_path (struct uevent *uev, struct vectors * vecs)
pthread_testcancel();
ret = store_path(vecs->pathvec, pp);
if (!ret) {
+ conf = get_multipath_config();
pp->checkint = conf->checkint;
+ put_multipath_config(conf);
ret = ev_add_path(pp, vecs);
} else {
condlog(0, "%s: failed to store path info, "
@@ -724,7 +765,7 @@ rescan:
* reload the map for the multipath mapped device
*/
retry:
- ret = domap(mpp, params);
+ ret = domap(mpp, params, 1);
if (ret <= 0) {
if (ret < 0 && retries-- > 0) {
condlog(0, "%s: retry domap for addition of new "
@@ -866,7 +907,7 @@ ev_remove_path (struct path *pp, struct vectors * vecs)
* reload the map
*/
mpp->action = ACT_RELOAD;
- if (domap(mpp, params) <= 0) {
+ if (domap(mpp, params, 1) <= 0) {
condlog(0, "%s: failed in domap for "
"removal of path %s",
mpp->alias, pp->dev);
@@ -931,7 +972,7 @@ uev_update_path (struct uevent *uev, struct vectors * vecs)
}
}
if (mpp) {
- retval = reload_map(vecs, mpp, 0);
+ retval = reload_map(vecs, mpp, 0, 1);
condlog(2, "%s: map %s reloaded (retval %d)",
uev->kernel, mpp->alias, retval);
@@ -1023,6 +1064,7 @@ uev_trigger (struct uevent * uev, void * trigger_data)
{
int r = 0;
struct vectors * vecs;
+ struct config *conf;
vecs = (struct vectors *)trigger_data;
@@ -1059,9 +1101,13 @@ uev_trigger (struct uevent * uev, void * trigger_data)
/*
* path add/remove event
*/
+ conf = get_multipath_config();
if (filter_devnode(conf->blist_devnode, conf->elist_devnode,
- uev->kernel) > 0)
+ uev->kernel) > 0) {
+ put_multipath_config(conf);
goto out;
+ }
+ put_multipath_config(conf);
if (!strncmp(uev->action, "add", 3)) {
r = uev_add_path(uev, vecs);
@@ -1080,23 +1126,33 @@ out:
return r;
}
+static void *rcu_unregister(void *param)
+{
+ rcu_unregister_thread();
+ return NULL;
+}
+
static void *
ueventloop (void * ap)
{
struct udev *udev = ap;
+ pthread_cleanup_push(rcu_unregister, NULL);
+ rcu_register_thread();
if (uevent_listen(udev))
condlog(0, "error starting uevent listener");
-
+ pthread_cleanup_pop(1);
return NULL;
}
static void *
uevqloop (void * ap)
{
+ pthread_cleanup_push(rcu_unregister, NULL);
+ rcu_register_thread();
if (uevent_dispatch(&uev_trigger, ap))
condlog(0, "error starting uevent dispatcher");
-
+ pthread_cleanup_pop(1);
return NULL;
}
static void *
@@ -1106,7 +1162,8 @@ uxlsnrloop (void * ap)
condlog(1, "Failed to init uxsock listener");
return NULL;
}
-
+ pthread_cleanup_push(rcu_unregister, NULL);
+ rcu_register_thread();
set_handler_callback(LIST+PATHS, cli_list_paths);
set_handler_callback(LIST+PATHS+FMT, cli_list_paths_fmt);
set_handler_callback(LIST+PATHS+RAW+FMT, cli_list_paths_raw);
@@ -1120,11 +1177,13 @@ uxlsnrloop (void * ap)
set_handler_callback(LIST+MAPS+RAW+FMT, cli_list_maps_raw);
set_handler_callback(LIST+MAPS+TOPOLOGY, cli_list_maps_topology);
set_handler_callback(LIST+TOPOLOGY, cli_list_maps_topology);
+ set_handler_callback(LIST+MAPS+JSON, cli_list_maps_json);
set_handler_callback(LIST+MAP+TOPOLOGY, cli_list_map_topology);
set_handler_callback(LIST+MAP+FMT, cli_list_map_fmt);
set_handler_callback(LIST+MAP+RAW+FMT, cli_list_map_fmt);
- set_unlocked_handler_callback(LIST+CONFIG, cli_list_config);
- set_unlocked_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
+ set_handler_callback(LIST+MAP+JSON, cli_list_map_json);
+ set_handler_callback(LIST+CONFIG, cli_list_config);
+ set_handler_callback(LIST+BLACKLIST, cli_list_blacklist);
set_handler_callback(LIST+DEVICES, cli_list_devices);
set_handler_callback(LIST+WILDCARDS, cli_list_wildcards);
set_handler_callback(ADD+PATH, cli_add_path);
@@ -1154,7 +1213,7 @@ uxlsnrloop (void * ap)
umask(077);
uxsock_listen(&uxsock_trigger, ap);
-
+ pthread_cleanup_pop(1);
return NULL;
}
@@ -1272,7 +1331,8 @@ missing_uev_wait_tick(struct vectors *vecs)
{
struct multipath * mpp;
unsigned int i;
- int timed_out = 0;
+ int timed_out = 0, delayed_reconfig;
+ struct config *conf;
vector_foreach_slot (vecs->mpvec, mpp, i) {
if (mpp->wait_for_udev && --mpp->uev_wait_tick <= 0) {
@@ -1287,7 +1347,10 @@ missing_uev_wait_tick(struct vectors *vecs)
}
}
- if (timed_out && conf->delayed_reconfig &&
+ conf = get_multipath_config();
+ delayed_reconfig = conf->delayed_reconfig;
+ put_multipath_config(conf);
+ if (timed_out && delayed_reconfig &&
!need_to_delay_reconfig(vecs)) {
condlog(2, "reconfigure (delayed)");
set_config_state(DAEMON_CONFIGURE);
@@ -1337,12 +1400,15 @@ int update_prio(struct path *pp, int refresh_all)
struct path *pp1;
struct pathgroup * pgp;
int i, j, changed = 0;
+ struct config *conf;
if (refresh_all) {
vector_foreach_slot (pp->mpp->pg, pgp, i) {
vector_foreach_slot (pgp->paths, pp1, j) {
oldpriority = pp1->priority;
- pathinfo(pp1, conf->hwtable, DI_PRIO);
+ conf = get_multipath_config();
+ pathinfo(pp1, conf, DI_PRIO);
+ put_multipath_config(conf);
if (pp1->priority != oldpriority)
changed = 1;
}
@@ -1350,7 +1416,9 @@ int update_prio(struct path *pp, int refresh_all)
return changed;
}
oldpriority = pp->priority;
- pathinfo(pp, conf->hwtable, DI_PRIO);
+ conf = get_multipath_config();
+ pathinfo(pp, conf, DI_PRIO);
+ put_multipath_config(conf);
if (pp->priority == oldpriority)
return 0;
@@ -1359,7 +1427,7 @@ int update_prio(struct path *pp, int refresh_all)
int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh)
{
- if (reload_map(vecs, mpp, refresh))
+ if (reload_map(vecs, mpp, refresh, 1))
return 1;
dm_lib_release();
@@ -1371,7 +1439,8 @@ int update_path_groups(struct multipath *mpp, struct vectors *vecs, int refresh)
}
/*
- * Returns '1' if the path has been checked, '0' otherwise
+ * Returns '1' if the path has been checked, '-1' if it was blacklisted
+ * and '0' otherwise
*/
int
check_path (struct vectors * vecs, struct path * pp, int ticks)
@@ -1382,6 +1451,9 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
int add_active;
int disable_reinstate = 0;
int oldchkrstate = pp->chkrstate;
+ int retrigger_tries, checkint;
+ struct config *conf;
+ int ret;
if ((pp->initialized == INIT_OK ||
pp->initialized == INIT_REQUESTED_UDEV) && !pp->mpp)
@@ -1392,8 +1464,12 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
if (pp->tick)
return 0; /* don't check this path yet */
+ conf = get_multipath_config();
+ retrigger_tries = conf->retrigger_tries;
+ checkint = conf->checkint;
+ put_multipath_config(conf);
if (!pp->mpp && pp->initialized == INIT_MISSING_UDEV &&
- pp->retriggers < conf->retrigger_tries) {
+ pp->retriggers < retrigger_tries) {
condlog(2, "%s: triggering change event to reinitialize",
pp->dev);
pp->initialized = INIT_REQUESTED_UDEV;
@@ -1407,7 +1483,7 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
* provision a next check soonest,
* in case we exit abnormaly from here
*/
- pp->tick = conf->checkint;
+ pp->tick = checkint;
newstate = path_offline(pp);
/*
@@ -1418,24 +1494,34 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
if (newstate == PATH_REMOVED)
newstate = PATH_DOWN;
- if (newstate == PATH_UP)
- newstate = get_state(pp, 1);
- else
+ if (newstate == PATH_UP) {
+ conf = get_multipath_config();
+ newstate = get_state(pp, conf, 1);
+ put_multipath_config(conf);
+ } else
checker_clear_message(&pp->checker);
if (newstate == PATH_WILD || newstate == PATH_UNCHECKED) {
condlog(2, "%s: unusable path", pp->dev);
- pathinfo(pp, conf->hwtable, 0);
+ conf = get_multipath_config();
+ pathinfo(pp, conf, 0);
+ put_multipath_config(conf);
return 1;
}
if (!pp->mpp) {
if (!strlen(pp->wwid) && pp->initialized != INIT_MISSING_UDEV &&
(newstate == PATH_UP || newstate == PATH_GHOST)) {
condlog(2, "%s: add missing path", pp->dev);
- if (pathinfo(pp, conf->hwtable, DI_ALL) == 0) {
+ conf = get_multipath_config();
+ ret = pathinfo(pp, conf, DI_ALL | DI_BLACKLIST);
+ if (ret == PATHINFO_OK) {
ev_add_path(pp, vecs);
pp->tick = 1;
+ } else if (ret == PATHINFO_SKIPPED) {
+ put_multipath_config(conf);
+ return -1;
}
+ put_multipath_config(conf);
}
return 0;
}
@@ -1450,7 +1536,7 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
/*
* Synchronize with kernel state
*/
- if (update_multipath_strings(pp->mpp, vecs->pathvec)) {
+ if (update_multipath_strings(pp->mpp, vecs->pathvec, 1)) {
condlog(1, "%s: Could not synchronize with kernel state",
pp->dev);
pp->dmstate = PSTATE_UNDEF;
@@ -1491,7 +1577,9 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
* upon state change, reset the checkint
* to the shortest delay
*/
+ conf = get_multipath_config();
pp->checkint = conf->checkint;
+ put_multipath_config(conf);
if (newstate == PATH_DOWN || newstate == PATH_SHAKY) {
/*
@@ -1571,16 +1659,20 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
return 0;
}
} else {
+ unsigned int max_checkint;
LOG_MSG(4, checker_message(&pp->checker));
- if (pp->checkint != conf->max_checkint) {
+ conf = get_multipath_config();
+ max_checkint = conf->max_checkint;
+ put_multipath_config(conf);
+ if (pp->checkint != max_checkint) {
/*
* double the next check delay.
* max at conf->max_checkint
*/
- if (pp->checkint < (conf->max_checkint / 2))
+ if (pp->checkint < (max_checkint / 2))
pp->checkint = 2 * pp->checkint;
else
- pp->checkint = conf->max_checkint;
+ pp->checkint = max_checkint;
condlog(4, "%s: delay next check %is",
pp->dev_t, pp->checkint);
@@ -1592,7 +1684,12 @@ check_path (struct vectors * vecs, struct path * pp, int ticks)
}
else if (newstate == PATH_DOWN &&
strlen(checker_message(&pp->checker))) {
- if (conf->log_checker_err == LOG_CHKR_ERR_ONCE)
+ int log_checker_err;
+
+ conf = get_multipath_config();
+ log_checker_err = conf->log_checker_err;
+ put_multipath_config(conf);
+ if (log_checker_err == LOG_CHKR_ERR_ONCE)
LOG_MSG(3, checker_message(&pp->checker));
else
LOG_MSG(2, checker_message(&pp->checker));
@@ -1633,7 +1730,10 @@ checkerloop (void *ap)
unsigned int i;
struct itimerval timer_tick_it;
struct timeval last_time;
+ struct config *conf;
+ pthread_cleanup_push(rcu_unregister, NULL);
+ rcu_register_thread();
mlockall(MCL_CURRENT | MCL_FUTURE);
vecs = (struct vectors *)ap;
condlog(2, "path checkers start up");
@@ -1642,7 +1742,9 @@ checkerloop (void *ap)
* init the path check interval
*/
vector_foreach_slot (vecs->pathvec, pp, i) {
+ conf = get_multipath_config();
pp->checkint = conf->checkint;
+ put_multipath_config(conf);
}
/* Tweak start time for initial path check */
@@ -1678,13 +1780,18 @@ checkerloop (void *ap)
condlog(4, "timeout waiting for DAEMON_IDLE");
continue;
}
- strict_timing = conf->strict_timing;
if (vecs->pathvec) {
pthread_cleanup_push(cleanup_lock, &vecs->lock);
lock(vecs->lock);
pthread_testcancel();
vector_foreach_slot (vecs->pathvec, pp, i) {
- num_paths += check_path(vecs, pp, ticks);
+ rc = check_path(vecs, pp, ticks);
+ if (rc < 0) {
+ vector_del_slot(vecs->pathvec, i);
+ free_path(pp);
+ i--;
+ } else
+ num_paths += rc;
}
lock_cleanup_pop(vecs->lock);
}
@@ -1714,10 +1821,15 @@ checkerloop (void *ap)
gettimeofday(&end_time, NULL) == 0) {
timersub(&end_time, &start_time, &diff_time);
if (num_paths) {
+ unsigned int max_checkint;
+
condlog(3, "checked %d path%s in %lu.%06lu secs",
num_paths, num_paths > 1 ? "s" : "",
diff_time.tv_sec, diff_time.tv_usec);
- if (diff_time.tv_sec > conf->max_checkint)
+ conf = get_multipath_config();
+ max_checkint = conf->max_checkint;
+ put_multipath_config(conf);
+ if (diff_time.tv_sec > max_checkint)
condlog(1, "path checkers took longer "
"than %lu seconds, consider "
"increasing max_polling_interval",
@@ -1726,6 +1838,9 @@ checkerloop (void *ap)
}
post_config_state(DAEMON_IDLE);
+ conf = get_multipath_config();
+ strict_timing = conf->strict_timing;
+ put_multipath_config(conf);
if (!strict_timing)
sleep(1);
else {
@@ -1749,11 +1864,14 @@ checkerloop (void *ap)
if (sigwait(&mask, &signo) != 0) {
condlog(3, "sigwait failed with error %d",
errno);
+ conf = get_multipath_config();
conf->strict_timing = 0;
+ put_multipath_config(conf);
break;
}
}
}
+ pthread_cleanup_pop(1);
return NULL;
}
@@ -1764,6 +1882,7 @@ configure (struct vectors * vecs, int start_waiters)
struct path * pp;
vector mpvec;
int i, ret;
+ struct config *conf;
if (!vecs->pathvec && !(vecs->pathvec = vector_alloc()))
return 1;
@@ -1777,11 +1896,12 @@ configure (struct vectors * vecs, int start_waiters)
/*
* probe for current path (from sysfs) and map (from dm) sets
*/
- ret = path_discovery(vecs->pathvec, conf, DI_ALL);
+ ret = path_discovery(vecs->pathvec, DI_ALL);
if (ret < 0)
return 1;
vector_foreach_slot (vecs->pathvec, pp, i){
+ conf = get_multipath_config();
if (filter_path(conf, pp) > 0){
vector_del_slot(vecs->pathvec, i);
free_path(pp);
@@ -1789,6 +1909,7 @@ configure (struct vectors * vecs, int start_waiters)
}
else
pp->checkint = conf->checkint;
+ put_multipath_config(conf);
}
if (map_discovery(vecs))
return 1;
@@ -1796,7 +1917,7 @@ configure (struct vectors * vecs, int start_waiters)
/*
* create new set of maps & push changed ones into dm
*/
- if (coalesce_paths(vecs, mpvec, NULL, 1))
+ if (coalesce_paths(vecs, mpvec, NULL, 1, CMD_NONE))
return 1;
/*
@@ -1854,11 +1975,21 @@ need_to_delay_reconfig(struct vectors * vecs)
return 0;
}
+void rcu_free_config(struct rcu_head *head)
+{
+ struct config *conf = container_of(head, struct config, rcu);
+
+ free_config(conf);
+}
+
int
reconfigure (struct vectors * vecs)
{
- struct config * old = conf;
- int retval = 1;
+ struct config * old, *conf;
+
+ conf = load_config(DEFAULT_CONFIGFILE);
+ if (!conf)
+ return 1;
/*
* free old map and path vectors ... they use old conf state
@@ -1866,30 +1997,29 @@ reconfigure (struct vectors * vecs)
if (VECTOR_SIZE(vecs->mpvec))
remove_maps_and_stop_waiters(vecs);
- if (VECTOR_SIZE(vecs->pathvec))
- free_pathvec(vecs->pathvec, FREE_PATHS);
-
+ free_pathvec(vecs->pathvec, FREE_PATHS);
vecs->pathvec = NULL;
- conf = NULL;
/* Re-read any timezone changes */
tzset();
- if (!load_config(DEFAULT_CONFIGFILE, udev)) {
- dm_drv_version(conf->version, TGT_MPATH);
- conf->verbosity = old->verbosity;
- conf->bindings_read_only = old->bindings_read_only;
- conf->ignore_new_devs = old->ignore_new_devs;
- conf->daemon = 1;
- configure(vecs, 1);
- free_config(old);
- retval = 0;
- } else {
- conf = old;
- }
+ dm_drv_version(conf->version, TGT_MPATH);
+ if (verbosity)
+ conf->verbosity = verbosity;
+ if (bindings_read_only)
+ conf->bindings_read_only = bindings_read_only;
+ if (ignore_new_devs)
+ conf->ignore_new_devs = ignore_new_devs;
uxsock_timeout = conf->uxsock_timeout;
- return retval;
+ old = rcu_dereference(multipath_conf);
+ rcu_assign_pointer(multipath_conf, conf);
+ call_rcu(&old->rcu, rcu_free_config);
+
+ configure(vecs, 1);
+
+
+ return 0;
}
static struct vectors *
@@ -2074,12 +2204,13 @@ child (void * param)
unsigned long checkint;
#endif
int rc;
+ int pid_fd = -1;
+ struct config *conf;
char *envp;
mlockall(MCL_CURRENT | MCL_FUTURE);
signal_init();
-
- udev = udev_new();
+ rcu_init();
setup_thread_attr(&misc_attr, 64 * 1024, 1);
setup_thread_attr(&uevent_attr, DEFAULT_UEVENT_STACKSIZE * 1024, 1);
@@ -2090,7 +2221,8 @@ child (void * param)
log_thread_start(&log_attr);
pthread_attr_destroy(&log_attr);
}
- if (pidfile_create(DEFAULT_PIDFILE, daemon_pid)) {
+ pid_fd = pidfile_create(DEFAULT_PIDFILE, daemon_pid);
+ if (pid_fd < 0) {
condlog(1, "failed to create pidfile");
if (logsink == 1)
log_thread_stop();
@@ -2102,17 +2234,25 @@ child (void * param)
condlog(2, "--------start up--------");
condlog(2, "read " DEFAULT_CONFIGFILE);
- if (load_config(DEFAULT_CONFIGFILE, udev))
+ conf = load_config(DEFAULT_CONFIGFILE);
+ if (!conf)
goto failed;
+ if (verbosity)
+ conf->verbosity = verbosity;
+ if (bindings_read_only)
+ conf->bindings_read_only = bindings_read_only;
+ if (ignore_new_devs)
+ conf->ignore_new_devs = ignore_new_devs;
uxsock_timeout = conf->uxsock_timeout;
-
+ multipath_conf = conf;
+ dm_init(conf->verbosity);
dm_drv_version(conf->version, TGT_MPATH);
- if (init_checkers()) {
+ if (init_checkers(conf->multipath_dir)) {
condlog(0, "failed to initialize checkers");
goto failed;
}
- if (init_prio()) {
+ if (init_prio(conf->multipath_dir)) {
condlog(0, "failed to initialize prioritizers");
goto failed;
}
@@ -2156,7 +2296,6 @@ child (void * param)
setscheduler();
set_oom_adj();
- conf->daemon = 1;
dm_udev_set_sync_support(0);
#ifdef USE_SYSTEMD
envp = getenv("WATCHDOG_USEC");
@@ -2283,6 +2422,7 @@ child (void * param)
conf = NULL;
udev_unref(udev);
udev = NULL;
+ pthread_attr_destroy(&waiter_attr);
#ifdef _DEBUG_
dbg_free_final(NULL);
#endif
@@ -2296,6 +2436,8 @@ failed:
#ifdef USE_SYSTEMD
sd_notify(0, "ERRNO=1");
#endif
+ if (pid_fd >= 0)
+ close(pid_fd);
exit(1);
}
@@ -2360,9 +2502,9 @@ main (int argc, char *argv[])
int arg;
int err;
int foreground = 0;
+ struct config *conf;
logsink = 1;
- dm_init();
if (getuid() != 0) {
fprintf(stderr, "need to be root\n");
@@ -2375,10 +2517,7 @@ main (int argc, char *argv[])
strerror(errno));
umask(umask(077) | 022);
- conf = alloc_config();
-
- if (!conf)
- exit(1);
+ udev = udev_new();
while ((arg = getopt(argc, argv, ":dsv:k::Bn")) != EOF ) {
switch(arg) {
@@ -2393,21 +2532,24 @@ main (int argc, char *argv[])
!isdigit(optarg[0]))
exit(1);
- conf->verbosity = atoi(optarg);
+ verbosity = atoi(optarg);
break;
case 's':
logsink = -1;
break;
case 'k':
- if (load_config(DEFAULT_CONFIGFILE, udev_new()))
+ conf = load_config(DEFAULT_CONFIGFILE);
+ if (!conf)
exit(1);
+ if (verbosity)
+ conf->verbosity = verbosity;
uxclnt(optarg, uxsock_timeout + 100);
exit(0);
case 'B':
- conf->bindings_read_only = 1;
+ bindings_read_only = 1;
break;
case 'n':
- conf->ignore_new_devs = 1;
+ ignore_new_devs = 1;
break;
default:
fprintf(stderr, "Invalid argument '-%c'\n",
@@ -2420,8 +2562,11 @@ main (int argc, char *argv[])
char * s = cmd;
char * c = s;
- if (load_config(DEFAULT_CONFIGFILE, udev_new()))
+ conf = load_config(DEFAULT_CONFIGFILE);
+ if (!conf)
exit(1);
+ if (verbosity)
+ conf->verbosity = verbosity;
memset(cmd, 0x0, CMDSIZE);
while (optind < argc) {
if (strchr(argv[optind], ' '))
@@ -2566,4 +2711,3 @@ int mpath_pr_event_handle(struct path *pp)
rc = pthread_join(thread, NULL);
return 0;
}
-
diff --git a/multipathd/multipathd.8 b/multipathd/multipathd.8
index 77f6e72..96a8fdb 100644
--- a/multipathd/multipathd.8
+++ b/multipathd/multipathd.8
@@ -7,14 +7,14 @@ multipathd \- multipath daemon
.RB [\| options \|]
.SH DESCRIPTION
-The
-.B multipathd
+The
+.B multipathd
daemon is in charge of checking for failed paths. When this happens,
-it will reconfigure the multipath map the path belongs to, so that this map
+it will reconfigure the multipath map the path belongs to, so that this map
regains its maximum performance and redundancy.
-This daemon executes the external multipath config tool when events occur.
-In turn, the multipath tool signals the multipathd daemon when it is done with
+This daemon executes the external multipath config tool when events occur.
+In turn, the multipath tool signals the multipathd daemon when it is done with
devmap reconfiguration, so that it can refresh its failed path list.
.SH OPTIONS
@@ -26,14 +26,14 @@ Foreground Mode. Don't daemonize, and print all messages to stdout and stderr.
Suppress timestamps. Do not prefix logging messages with a timestamp.
.TP
.B -v "level"
-Verbosity level. Print additional information while running multipathd. A level of 0 means only print errors. A level of 3 or greater prints debugging information as well.
+Verbosity level. Print additional information while running multipathd. A level of 0 means only print errors. A level of 3 or greater prints debugging information as well.
.TP
.B -B
Read-only bindings file. Multipathd will not write to the user_friendly_names
bindings file. If a user_friendly_name doesn't already exist for a device, it
will use its WWID as its alias.
.TP
-.B -k
+.B -k
multipathd will enter interactive mode. From this mode, the available commands can be viewed by entering "help". When you are finished entering commands, press CTRL-D to quit.
.TP
.B -n
@@ -45,14 +45,14 @@ wwid for the device is already listed in the wwids file.
The following commands can be used in interactive mode:
.TP
.B list|show paths
-Show the paths that multipathd is monitoring, and their state.
+Show the paths that multipathd is monitoring, and their state.
.TP
.B list|show paths format $format
Show the paths that multipathd is monitoring, using a format string with path
format wildcards.
.TP
.B list|show maps|multipaths
-Show the multipath devices that the multipathd is monitoring.
+Show the multipath devices that the multipathd is monitoring.
.TP
.B list|show maps|multipaths format $format
Show the status of all multipath devices that the multipathd is monitoring,
@@ -94,19 +94,19 @@ Show the current state of the multipathd daemon
.TP
.B add path $path
Add a path to the list of monitored paths. $path is as listed in /sys/block (e.g. sda).
-.TP
+.TP
.B remove|del path $path
Stop monitoring a path. $path is as listed in /sys/block (e.g. sda).
.TP
.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).
+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|multipath $map
Stop monitoring a multipath device.
.TP
.B resize map|multipath $map
Resizes map $map to the given size
-.TP
+.TP
.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
diff --git a/multipathd/multipathd.init.debian b/multipathd/multipathd.init.debian
deleted file mode 100644
index ed23b5b..0000000
--- a/multipathd/multipathd.init.debian
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-DAEMON=/usr/bin/multipathd
-
-test -x $DAEMON || exit 0
-
-case "$1" in
- start)
- echo -n "Starting multipath daemon: multipathd"
- $DAEMON
- echo "."
- ;;
- stop)
- echo -n "Stopping multipath daemon: multipathd"
- echo "."
- $DAEMON shutdown
- ;;
- force-reload|restart)
- $0 stop
- $0 start
- ;;
- *)
- echo "Usage: /etc/init.d/multipathd {start|stop|restart|force-reload}"
- exit 1
- ;;
-esac
-
-exit 0
diff --git a/multipathd/multipathd.init.redhat b/multipathd/multipathd.init.redhat
deleted file mode 100644
index d46ef80..0000000
--- a/multipathd/multipathd.init.redhat
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/bin/bash
-#
-# multipathd Starts the multipath daemon
-#
-# chkconfig: - 06 87
-# description: Manages device-mapper multipath devices
-
-### BEGIN INIT INFO
-# Provides: multipathd
-# Required-Start:
-# Required-Stop:
-# Default-Start:
-# Default-Stop:
-# Short-Description: Control multipathd
-# Description: This service monitors and manages
-# device-mapper multipath devices
-### END INIT INFO
-
-DAEMON=/sbin/multipathd
-prog=`basename $DAEMON`
-initdir=/etc/rc.d/init.d
-lockdir=/var/lock/subsys
-sysconfig=/etc/sysconfig
-syspath=/sys/block
-
-
-. $initdir/functions
-
-test -r $sysconfig/$prog && . $sysconfig/$prog
-
-RETVAL=0
-
-teardown_slaves()
-{
-pushd $1 > /dev/null
-if [ -d "slaves" ]; then
-for slave in slaves/*;
-do
- if [ "$slave" = "slaves/*" ]; then
- read dev < $1/dev
- tablename=`dmsetup table --target multipath | sed -n "s/\(.*\): .* $dev .*/\1/p"`
- if ! [ -z $tablename ]; then
- echo "Root is on a multipathed device, multipathd can not be stopped"
- exit 1
- fi
- else
- local_slave=`readlink -f $slave`;
- teardown_slaves $local_slave;
- fi
- done
-
-else
- read dev < $1/dev
- tablename=`dmsetup table --target multipath | sed -n "s/\(.*\): .* $dev .*/\1/p"`
- if ! [ -z $tablename ]; then
- echo "Root is on a multipathed device, multipathd can not be stopped"
- exit 1
- fi
-fi
-popd > /dev/null
-}
-
-#
-# See how we were called.
-#
-
-start() {
- test -x $DAEMON || exit 5
- echo -n $"Starting $prog daemon: "
- daemon $DAEMON
- RETVAL=$?
- [ $RETVAL -eq 0 ] && touch $lockdir/$prog
- echo
-}
-
-force_stop() {
- echo -n $"Stopping $prog daemon: "
- killproc $DAEMON
- RETVAL=$?
- [ $RETVAL -eq 0 ] && rm -f $lockdir/$prog
- echo
-}
-
-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_queue_without_daemon() {
- $DAEMON forcequeueing daemon
-}
-
-restart() {
- force_queue_without_daemon
- check_root
- force_stop
- start
-}
-
-force_restart() {
- force_queue_without_daemon
- force_stop
- start
-}
-
-reload() {
- echo -n "Reloading $prog: "
- trap "" SIGHUP
- killproc $DAEMON -HUP
- RETVAL=$?
- echo
-}
-
-case "$1" in
-start)
- start
- ;;
-stop)
- check_root
- force_stop
- ;;
-force-stop)
- force_stop
- ;;
-force-reload|reload)
- reload
- ;;
-restart)
- restart
- ;;
-force-restart)
- force_restart
- ;;
-condrestart|try-restart)
- if [ -f $lockdir/$prog ]; then
- restart
- fi
- ;;
-status)
- status $prog
- RETVAL=$?
- ;;
-*)
- echo $"Usage: $0 {start|stop|force-stop|status|restart|force-restart|condrestart|reload}"
- RETVAL=2
-esac
-
-exit $RETVAL
diff --git a/multipathd/multipathd.init.suse b/multipathd/multipathd.init.suse
deleted file mode 100644
index ed699fa..0000000
--- a/multipathd/multipathd.init.suse
+++ /dev/null
@@ -1,200 +0,0 @@
-#! /bin/sh
-# Copyright (c) 1995-2001 SuSE GmbH Nuernberg, Germany.
-#
-# Author: Hannes Reinecke <feedback@suse.de>
-#
-# init.d/multipathd
-#
-### BEGIN INIT INFO
-# Provides: multipathd
-# Required-Start: $syslog
-# Required-Stop: $syslog
-# Default-Start: 3 5
-# Default-Stop: 0 1 2 4 6
-# Short-Description: Starts multipath daemon
-# Description: Starts the multipath daemon
-### END INIT INFO
-
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-DAEMON=/sbin/multipathd
-PIDFILE=/run/multipathd.pid
-MPATH_INIT_TIMEOUT=10
-ARGS=""
-
-# Set the maximum number of open files
-MAX_OPEN_FDS=4096
-
-# Set to enable asynchronous daemon startup
-DAEMON_ASYNC_STARTUP=
-
-test -x $DAEMON || exit 5
-
-. /etc/rc.status
-
-# First reset status of this service
-rc_reset
-
-case "$1" in
- start)
- echo -n "Starting multipathd"
- ulimit -c unlimited
- if $DAEMON -k"reconfigure" > /dev/null 2>&1 ; then
- echo -n " (multipathd running)"
- rc_status -v
- rc_exit
- fi
-
- modprobe dm-multipath
-
- # Set the maximum number of open files
- if [ -n "$MAX_OPEN_FDS" ] ; then
- ulimit -n $MAX_OPEN_FDS
- fi
-
- $DAEMON $ARGS
-
- if [ -n "$DAEMON_ASYNC_STARTUP" ] ; then
- rc_status -v
- rc_exit
- fi
- # Wait for the daemon to start up
- status=$($DAEMON -k'show daemon' 2> /dev/null)
- timeout=$MPATH_INIT_TIMEOUT
- while [ $timeout -gt 0 ] ; do
- if [ -n "$status" ] ; then
- PID=${status##pid }
- STATUS=${PID##* }
- # Configuration might be taking some time,
- # so don't increase the timeout here
- [ "$STATUS" != "configure" ] && timeout=$(( $timeout - 1 ))
-
- [ "$STATUS" == "running" ] && break
- else
- timeout=$(( $timeout - 1 ))
- fi
- sleep 1
- status=$($DAEMON -k'show daemon' 2> /dev/null)
- done
- if [ -z "$status" ] ; then
- rc_failed 7
- fi
- if [ $timeout -le 0 ] ; then
- rc_failed 1
- fi
- # Remember status and be verbose
- rc_status -v
- ;;
- stop)
- echo -n "Shutting down multipathd"
- STATUS="unknown"
- # Try to get PID from daemon
- status=$($DAEMON -k'show daemon' 2> /dev/null)
- if [ -n "$status" ] ; then
- PID=${status##pid }
- STATUS=${PID##* }
- PID=${PID%% *}
- fi
- # Fallback to PID file for older versions
- if [ -z "$PID" ] || [ "$PID" == "multipath-tools" ] ; then
- if [ -f $PIDFILE ]; then
- PID="$(cat $PIDFILE)"
- STATUS="running"
- else
- rc_failed 7
- rc_status -v
- rc_exit
- fi
- fi
- # Shutdown the daemon via CLI
- if [ "$STATUS" = "running" ] ; then
- status=$($DAEMON -k'shutdown' 2> /dev/null)
- if [ "$status" = "ok" ] ; then
- timeout=$MPATH_INIT_TIMEOUT
- while [ $timeout -gt 0 ] ; do
- PROCNAME="$(ps -p $PID -o comm=)"
- if [ "$PROCNAME" != "multipathd" ] &&
- [ "$PROCNAME" != "multipathd <defunct>" ] ; then
- STATUS="shutdown"
- break
- fi
- sleep 1
- timeout=$(( $timeout - 1 ))
- done
- fi
- fi
- # Kill the daemon if the above failed
- if [ -n "$PID" -a "$STATUS" != "shutdown" ] ; then
- kill -TERM $PID
- timeout=$MPATH_INIT_TIMEOUT
- while [ $timeout -gt 0 ] ; do
- PROCNAME="$(ps -p $PID -o comm=)"
- if [ "$PROCNAME" != "multipathd" ] &&
- [ "$PROCNAME" != "multipathd <defunct>" ] ; then
- STATUS="shutdown"
- break
- fi
- sleep 1
- timeout=$(( $timeout - 1 ))
- done
- fi
- if [ $STATUS != "shutdown" ] ; then
- echo -n " (still running)"
- rc_failed 1
- fi
-
- # Remember status and be verbose
- rc_status -v
- ;;
- try-restart)
- ## Stop the service and if this succeeds (i.e. the
- ## service was running before), start it again.
- $0 status >/dev/null && $0 restart
-
- # Remember status and be quiet
- rc_status
- ;;
- restart|force-reload)
- ## Stop the service and regardless of whether it was
- ## running or not, start it again.
- $0 stop
- $0 start
-
- # Remember status and be quiet
- rc_status
- ;;
- reload)
- ## Like force-reload, but if daemon does not support
- ## signalling, do nothing (!)
-
- $DAEMON -k"reconfigure" > /dev/null 2>&1
-
- # Remember status and be quiet
- rc_status
- ;;
- status)
- echo -n "Checking for multipathd: "
-
- # Status has a slightly different for the status command:
- # 0 - service running
- # 1 - service dead, but /var/run/ pid file exists
- # 2 - service dead, but /var/lock/ lock file exists
- # 3 - service not running
-
- status=$($DAEMON -k'show daemon' 2> /dev/null)
- if [ -n "$status" ]; then
- (exit 0)
- else
- (exit 3)
- fi
- rc_status -v
- ;;
- probe)
- ## Optional: Probe for the necessity of a reload,
- ## give out the argument which is required for a reload.
- ;;
- *)
- echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
- exit 1
- ;;
-esac
-rc_exit
diff --git a/multipathd/pidfile.c b/multipathd/pidfile.c
index e3fb896..9bac1dd 100644
--- a/multipathd/pidfile.c
+++ b/multipathd/pidfile.c
@@ -8,7 +8,7 @@
#include <unistd.h> /* for unlink() */
#include <fcntl.h> /* for fcntl() */
-#include <debug.h>
+#include "debug.h"
#include "pidfile.h"
@@ -22,7 +22,7 @@ int pidfile_create(const char *pidFile, pid_t pid)
(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
condlog(0, "Cannot open pidfile [%s], error was [%s]",
pidFile, strerror(errno));
- return 1;
+ return -errno;
}
lock.l_type = F_WRLCK;
lock.l_start = 0;
@@ -60,8 +60,8 @@ int pidfile_create(const char *pidFile, pid_t pid)
"error was [%s]", pidFile, strerror(errno));
goto fail;
}
- return 0;
+ return fd;
fail:
close(fd);
- return 1;
+ return -errno;
}
diff --git a/multipathd/uxclnt.c b/multipathd/uxclnt.c
index 06c1bf8..62ff6f4 100644
--- a/multipathd/uxclnt.c
+++ b/multipathd/uxclnt.c
@@ -14,16 +14,16 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/poll.h>
+#include <poll.h>
#include <readline/readline.h>
#include <readline/history.h>
-#include <mpath_cmd.h>
-#include <uxsock.h>
-#include <memory.h>
-#include <defaults.h>
+#include "mpath_cmd.h"
+#include "uxsock.h"
+#include "memory.h"
+#include "defaults.h"
-#include <vector.h>
+#include "vector.h"
#include "cli.h"
static void print_reply(char *s)
@@ -135,6 +135,6 @@ int uxclnt(char * inbuf, unsigned int timeout)
process_req(fd, inbuf, timeout);
else
process(fd, timeout);
-
+ mpath_disconnect(fd);
return 0;
}
diff --git a/multipathd/uxlsnr.c b/multipathd/uxlsnr.c
index 9912e00..0159648 100644
--- a/multipathd/uxlsnr.c
+++ b/multipathd/uxlsnr.c
@@ -19,19 +19,19 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/poll.h>
+#include <poll.h>
#include <sys/time.h>
#include <signal.h>
-#include <checkers.h>
-#include <memory.h>
-#include <debug.h>
-#include <vector.h>
-#include <structs.h>
-#include <structs_vec.h>
-#include <uxsock.h>
-#include <defaults.h>
-#include <config.h>
-#include <mpath_cmd.h>
+#include "checkers.h"
+#include "memory.h"
+#include "debug.h"
+#include "vector.h"
+#include "structs.h"
+#include "structs_vec.h"
+#include "uxsock.h"
+#include "defaults.h"
+#include "config.h"
+#include "mpath_cmd.h"
#include "main.h"
#include "cli.h"
@@ -144,11 +144,6 @@ void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
return NULL;
}
- if (!conf) {
- condlog(1, "uxsock: configuration changed");
- return NULL;
- }
-
pthread_cleanup_push(uxsock_cleanup, NULL);
condlog(3, "uxsock: startup listener");
diff --git a/multipathd/uxlsnr.h b/multipathd/uxlsnr.h
index d274b04..7839fce 100644
--- a/multipathd/uxlsnr.h
+++ b/multipathd/uxlsnr.h
@@ -10,4 +10,3 @@ extern volatile sig_atomic_t reconfig_sig;
extern volatile sig_atomic_t log_reset_sig;
#endif
-