[packages/multipath-tools] updated git patch; rel 10
glen
glen at pld-linux.org
Fri May 17 23:38:42 CEST 2013
commit 81d0f82c939505ab8e223a7d5156bee541ea7656
Author: Elan Ruusamäe <glen at delfi.ee>
Date: Sat May 18 00:29:29 2013 +0300
updated git patch; rel 10
add support for -c:
-c check if a device should be a path in a multipath device
config.patch | 54 +-
multipath-tools-git.patch | 12237 +++++++++++++++++++++++++++++-------
multipath-tools-kpartx-udev.patch | 8 +-
multipath-tools-llh.patch | 18 -
multipath-tools.spec | 17 +-
5 files changed, 9925 insertions(+), 2409 deletions(-)
---
diff --git a/multipath-tools.spec b/multipath-tools.spec
index c1eeb6a..61e4417 100644
--- a/multipath-tools.spec
+++ b/multipath-tools.spec
@@ -6,7 +6,7 @@ Summary: Tools to manage multipathed devices with the device-mapper
Summary(pl.UTF-8): Implementacja wielotrasowego dostępu do zasobów przy użyciu device-mappera
Name: multipath-tools
Version: 0.4.9
-Release: 9
+Release: 10
License: GPL v2
Group: Base
Source0: http://christophe.varoqui.free.fr/multipath-tools/%{name}-%{version}.tar.bz2
@@ -17,7 +17,6 @@ Source2: multipathd.sysconfig
Source3: %{name}-bindings
URL: http://christophe.varoqui.free.fr/
Patch100: %{name}-git.patch
-Patch0: %{name}-llh.patch
Patch1: %{name}-kpartx-udev.patch
Patch2: config.patch
BuildRequires: device-mapper-devel >= 1.02.08
@@ -97,7 +96,6 @@ umożliwia tworzenie partycji na odwzorowaniach wielotrasowych.
%prep
%setup -qc
%patch100 -p1
-%patch0 -p1
%patch1 -p1
%patch2 -p1
@@ -126,9 +124,15 @@ install -d $RPM_BUILD_ROOT{/etc/{rc.d/init.d,sysconfig},%{_sysconfdir}/multipath
DESTDIR=$RPM_BUILD_ROOT
install -p %{SOURCE1} $RPM_BUILD_ROOT/etc/rc.d/init.d/multipathd
-cp -a multipath.conf.defaults $RPM_BUILD_ROOT%{_sysconfdir}/multipath.conf
-cp -a %{SOURCE2} $RPM_BUILD_ROOT/etc/sysconfig/multipathd
-cp -a %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/multipath/bindings
+cp -p multipath.conf.defaults $RPM_BUILD_ROOT%{_sysconfdir}/multipath.conf
+cp -p %{SOURCE2} $RPM_BUILD_ROOT/etc/sysconfig/multipathd
+cp -p %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/multipath/bindings
+
+# no -devel, so remove
+%{__rm} $RPM_BUILD_ROOT%{_includedir}/mpath_persist.h
+%{__rm} $RPM_BUILD_ROOT%{_mandir}/man3/mpath_persistent_reserve_in.3*
+%{__rm} $RPM_BUILD_ROOT%{_mandir}/man3/mpath_persistent_reserve_out.3*
+%{__rm} $RPM_BUILD_ROOT/%{_lib}/libmpathpersist.so
%clean
rm -rf $RPM_BUILD_ROOT
@@ -167,7 +171,6 @@ fi
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/multipath.conf
%dir %{_sysconfdir}/multipath
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/multipath/bindings
-/etc/udev/rules.d/multipath.rules
%{systemdunitdir}/multipathd.service
%{_mandir}/man5/multipath.conf.5*
%{_mandir}/man8/mpathpersist.8*
diff --git a/config.patch b/config.patch
index 1fd19b6..ea4a4c8 100644
--- a/config.patch
+++ b/config.patch
@@ -1,41 +1,29 @@
---- multipath-tools-0.4.8/multipath.conf.defaults~ 2009-10-26 17:17:11.000000000 +0200
-+++ multipath-tools-0.4.8/multipath.conf.defaults 2009-10-29 14:43:54.217124402 +0200
+--- multipath-tools-0.4.9/multipath.conf.defaults~ 2013-05-18 00:16:15.000000000 +0300
++++ multipath-tools-0.4.9/multipath.conf.defaults 2013-05-18 00:17:20.615348580 +0300
@@ -1,7 +1,7 @@
# These are the compiled in default settings. They will be used unless you
# overwrite these values in your config file.
-
+
-#defaults {
+defaults {
- # udev_dir /dev
- # polling_interval 5
- # selector "round-robin 0"
-@@ -13,16 +13,16 @@
- # rr_weight uniform
- # failback manual
- # no_path_retry fail
--# user_friendly_names no
+ # verbosity 2
+ # polling_interval 5
+ # path_selector "service-time 0"
+@@ -19,14 +19,15 @@
+ # queue_without_daemon "yes"
+ # pg_timeout "none"
+ # flush_on_last_del "no"
+-# user_friendly_names "no"
++ user_friendly_names "yes"
+ # fast_io_fail_tmo 5
+ # bindings_file "/etc/multipath/bindings"
+ # wwids_file /etc/multipath/wwids
+ # log_checker_err always
+ # retain_attached_hw_handler no
+ # detect_prio no
-#}
--#
--#blacklist {
-+ user_friendly_names yes
+}
+
-+blacklist {
- # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
- # devnode "^hd[a-z]"
- # devnode "^dcssblk[0-9]*"
--#}
--#
--#devices {
-+}
-+
-+devices {
- # device {
- # vendor "APPLE*"
- # product "Xserve RAID"
-@@ -571,4 +571,4 @@
- # path_checker rdac
- # prio rdac
- # }
--#}
-+}
+ #blacklist {
+ # devnode "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
+ # devnode "^hd[a-z]"
diff --git a/multipath-tools-git.patch b/multipath-tools-git.patch
index 844781d..15ed895 100644
--- a/multipath-tools-git.patch
+++ b/multipath-tools-git.patch
@@ -1,5 +1,21 @@
+diff --git a/.gitignore b/.gitignore
+index 9b3f663..7f25d0e 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -5,6 +5,8 @@
+ *.so.0
+ *.a
+ *.gz
+-kpartx
+-multipath
+-multipathd
++kpartx/kpartx
++multipath/multipath
++multipathd/multipathd
++mpathpersist/mpathpersist
++.nfs*
diff --git a/Makefile b/Makefile
-index d0063d0..5b0c61a 100644
+index d0063d0..baf7753 100644
--- a/Makefile
+++ b/Makefile
@@ -23,8 +23,10 @@ BUILDDIRS = \
@@ -13,11 +29,25 @@ index d0063d0..5b0c61a 100644
kpartx
ifeq ($(MULTIPATH_VERSION),)
+@@ -64,6 +66,13 @@ install: recurse_install
+
+ uninstall: recurse_uninstall
+
++.PHONY: TAGS
++TAGS:
++ etags -a libmultipath/*.c
++ 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
diff --git a/Makefile.inc b/Makefile.inc
-index dbcbc3b..02aef4f 100644
+index dbcbc3b..92d2289 100644
--- a/Makefile.inc
+++ b/Makefile.inc
-@@ -28,9 +28,12 @@ libudevdir = ${prefix}/lib/udev
+@@ -28,14 +28,21 @@ libudevdir = ${prefix}/lib/udev
multipathdir = $(TOPDIR)/libmultipath
mandir = $(prefix)/usr/share/man/man8
man5dir = $(prefix)/usr/share/man/man5
@@ -28,13 +58,24 @@ index dbcbc3b..02aef4f 100644
+unitdir = $(prefix)/lib/systemd/system
+mpathpersistdir = $(TOPDIR)/libmpathpersist
- GZIP = /bin/gzip -9 -c
+-GZIP = /bin/gzip -9 -c
++GZIP = gzip -9 -c
INSTALL_PROGRAM = install
+
+-OPTFLAGS = -pipe -g -Wall -Wunused -Wstrict-prototypes
++ifndef RPM_OPT_FLAGS
++ RPM_OPT_FLAGS = -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4
++endif
++
++OPTFLAGS = $(RPM_OPT_FLAGS) -Wunused -Wstrict-prototypes
+ CFLAGS = $(OPTFLAGS) -fPIC -DLIB_STRING=\"${LIB}\"
+ SHARED_FLAGS = -shared
+
diff --git a/kpartx/Makefile b/kpartx/Makefile
-index e1e9651..1287053 100644
+index e1e9651..4ba38ba 100644
--- a/kpartx/Makefile
+++ b/kpartx/Makefile
-@@ -6,6 +6,12 @@ include ../Makefile.inc
+@@ -6,9 +6,15 @@ include ../Makefile.inc
CFLAGS += -I. -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
@@ -46,7 +87,11 @@ index e1e9651..1287053 100644
+
LDFLAGS = -ldevmapper
OBJS = bsd.o dos.o kpartx.o solaris.o unixware.o dasd.o sun.o \
- gpt.o mac.o crc32.o lopart.o xstrncpy.o devmapper.o
+- gpt.o mac.o crc32.o lopart.o xstrncpy.o devmapper.o
++ gpt.o mac.o ps3.o crc32.o lopart.o xstrncpy.o devmapper.o
+ EXEC = kpartx
+
+ all: $(EXEC)
@@ -16,7 +22,7 @@ all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(OBJS) -o $(EXEC) $(LDFLAGS)
@@ -56,8 +101,50 @@ index e1e9651..1287053 100644
install: $(EXEC) $(EXEC).8
$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
+@@ -30,6 +36,7 @@ install: $(EXEC) $(EXEC).8
+ uninstall:
+ rm -f $(DESTDIR)$(bindir)/$(EXEC)
+ rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
++ rm -f $(DESTDIR)$(libudevdir)/kpartx_id
+
+ clean:
+ rm -f core *.o $(EXEC) *.gz
+diff --git a/kpartx/byteorder.h b/kpartx/byteorder.h
+index 21962d6..199c66b 100644
+--- a/kpartx/byteorder.h
++++ b/kpartx/byteorder.h
+@@ -12,12 +12,16 @@
+ # define le16_to_cpu(x) (x)
+ # define be16_to_cpu(x) bswap_16(x)
+ # define le32_to_cpu(x) (x)
++# define le64_to_cpu(x) (x)
+ # define be32_to_cpu(x) bswap_32(x)
++# define be64_to_cpu(x) bswap_64(x)
+ #elif BYTE_ORDER == BIG_ENDIAN
+ # define le16_to_cpu(x) bswap_16(x)
+ # define be16_to_cpu(x) (x)
+ # define le32_to_cpu(x) bswap_32(x)
++# define le64_to_cpu(x) bswap_64(x)
+ # define be32_to_cpu(x) (x)
++# define be64_to_cpu(x) (x)
+ #else
+ # error unsupported
+ #endif
+diff --git a/kpartx/dasd.h b/kpartx/dasd.h
+index 0ed7c80..42f94db 100644
+--- a/kpartx/dasd.h
++++ b/kpartx/dasd.h
+@@ -68,7 +68,7 @@ typedef struct volume_label
+ char res2[4]; /* reserved */
+ char lvtoc[14]; /* owner code for LVTOC */
+ char res3[28]; /* reserved */
+- char ldl_version; /* version number, valid for ldl format */
++ uint8_t ldl_version; /* version number, valid for ldl format */
+ uint64_t formatted_blocks; /* valid when ldl_version >= f2 */
+ } __attribute__ ((packed)) volume_label_t;
+
diff --git a/kpartx/devmapper.c b/kpartx/devmapper.c
-index f884511..4baebd9 100644
+index f884511..24a43ee 100644
--- a/kpartx/devmapper.c
+++ b/kpartx/devmapper.c
@@ -12,6 +12,14 @@
@@ -75,6 +162,15 @@ index f884511..4baebd9 100644
extern int
dm_prereq (char * str, int x, int y, int z)
+@@ -70,7 +78,7 @@ dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie) {
+ if (no_flush)
+ dm_task_no_flush(dmt);
+
+- if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, 0))
++ if (udev_wait_flag && !dm_task_set_cookie(dmt, cookie, (udev_sync)? 0 : DM_UDEV_DISABLE_LIBRARY_FALLBACK))
+ goto out;
+ r = dm_task_run(dmt);
+
@@ -81,7 +89,7 @@ dm_simplecmd (int task, const char *name, int no_flush, uint32_t *cookie) {
extern int
@@ -94,6 +190,15 @@ index f884511..4baebd9 100644
if (task == DM_DEVICE_CREATE && uuid) {
prefixed_uuid = malloc(MAX_PREFIX_LEN + strlen(uuid) + 1);
if (!prefixed_uuid) {
+@@ -117,7 +128,7 @@ dm_addmap (int task, const char *name, const char *target,
+
+ dm_task_no_open_count(dmt);
+
+- if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, cookie, 0))
++ if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, cookie, (udev_sync)? 0 : DM_UDEV_DISABLE_LIBRARY_FALLBACK))
+ goto addout;
+ r = dm_task_run (dmt);
+
@@ -268,3 +279,62 @@ out:
return r;
}
@@ -158,10 +263,15 @@ index f884511..4baebd9 100644
+ return 0;
+}
diff --git a/kpartx/devmapper.h b/kpartx/devmapper.h
-index f8692cc..8e350a0 100644
+index f8692cc..0edc063 100644
--- a/kpartx/devmapper.h
+++ b/kpartx/devmapper.h
-@@ -5,9 +5,10 @@
+@@ -2,12 +2,15 @@
+ #define MINOR(dev) ((dev & 0xff) | ((dev >> 12) & 0xfff00))
+ #define MKDEV(ma,mi) ((mi & 0xff) | (ma << 8) | ((mi & ~0xff) << 12))
+
++extern int udev_sync;
++
int dm_prereq (char *, int, int, int);
int dm_simplecmd (int, const char *, int, uint32_t *);
int dm_addmap (int, const char *, const char *, const char *, uint64_t,
@@ -173,8 +283,21 @@ index f8692cc..8e350a0 100644
char * dm_mapuuid(int major, int minor);
int dm_devn (char * mapname, int *major, int *minor);
+int dm_no_partitions(int major, int minor);
+diff --git a/kpartx/dos.c b/kpartx/dos.c
+index 1691105..a1a9961 100644
+--- a/kpartx/dos.c
++++ b/kpartx/dos.c
+@@ -98,6 +98,8 @@ read_dos_pt(int fd, struct slice all, struct slice *sp, int ns) {
+ break;
+ }
+ if (is_extended(p.sys_type)) {
++ sp[i].size = 2; /* extended partitions only get two
++ sectors mapped for LILO to install */
+ n += read_extended_partition(fd, &p, i, sp+n, ns-n);
+ }
+ }
diff --git a/kpartx/gpt.c b/kpartx/gpt.c
-index 047a829..3082cae 100644
+index 047a829..0a22927 100644
--- a/kpartx/gpt.c
+++ b/kpartx/gpt.c
@@ -358,6 +358,24 @@ is_gpt_valid(int fd, uint64_t lba,
@@ -202,8 +325,31 @@ index 047a829..3082cae 100644
if (!(*ptes = alloc_read_gpt_entries(fd, *gpt))) {
free(*gpt);
*gpt = NULL;
+@@ -619,6 +637,7 @@ read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns)
+ uint32_t i;
+ int n = 0;
+ int last_used_index=-1;
++ int sector_size_mul = get_sector_size(fd)/512;
+
+ if (!find_valid_gpt (fd, &gpt, &ptes) || !gpt || !ptes) {
+ if (gpt)
+@@ -634,9 +653,11 @@ read_gpt_pt (int fd, struct slice all, struct slice *sp, int ns)
+ sp[n].size = 0;
+ n++;
+ } else {
+- sp[n].start = __le64_to_cpu(ptes[i].starting_lba);
+- sp[n].size = __le64_to_cpu(ptes[i].ending_lba) -
+- __le64_to_cpu(ptes[i].starting_lba) + 1;
++ sp[n].start = sector_size_mul *
++ __le64_to_cpu(ptes[i].starting_lba);
++ sp[n].size = sector_size_mul *
++ (__le64_to_cpu(ptes[i].ending_lba) -
++ __le64_to_cpu(ptes[i].starting_lba) + 1);
+ last_used_index=n;
+ n++;
+ }
diff --git a/kpartx/kpartx.8 b/kpartx/kpartx.8
-index 923be1e..8a37d4f 100644
+index 923be1e..021ddc0 100644
--- a/kpartx/kpartx.8
+++ b/kpartx/kpartx.8
@@ -17,20 +17,52 @@ creation and deletion.
@@ -211,7 +357,7 @@ index 923be1e..8a37d4f 100644
Add partition mappings
.TP
+.B \-r
-+Readonly partition mappings
++Read-only partition mappings
+.TP
.B \-d
Delete partition mappings
@@ -220,7 +366,8 @@ index 923be1e..8a37d4f 100644
+Update partition mappings
+.TP
.B \-l
- List partition mappings that would be added -a
+-List partition mappings that would be added -a
++List partition mappings that would be added \-a
.TP
.B \-p
set device name-partition number delimiter
@@ -239,7 +386,7 @@ index 923be1e..8a37d4f 100644
+.SH EXAMPLE
+To mount all the partitions in a raw disk image:
+.IP
-+kpartx -av disk.img
++kpartx \-av disk.img
+.PP
+This will output lines such as:
+.IP
@@ -255,12 +402,12 @@ index 923be1e..8a37d4f 100644
+.PP
+When you're done, you need to remove the devices:
+.IP
-+kpartx -d disk.img
++kpartx \-d disk.img
.SH "SEE ALSO"
.BR multipath (8)
.BR multipathd (8)
diff --git a/kpartx/kpartx.c b/kpartx/kpartx.c
-index 3d33990..b5e0a32 100644
+index 3d33990..98d88c0 100644
--- a/kpartx/kpartx.c
+++ b/kpartx/kpartx.c
@@ -48,7 +48,7 @@
@@ -272,8 +419,19 @@ index 3d33990..b5e0a32 100644
struct pt {
char *type;
-@@ -82,19 +82,24 @@ initpts(void)
+@@ -56,6 +56,7 @@ struct pt {
+ } pts[MAXTYPES];
+
+ int ptct = 0;
++int udev_sync = 0;
+
+ static void
+ addpts(char *t, ptreader f)
+@@ -80,21 +81,27 @@ initpts(void)
+ addpts("dasd", read_dasd_pt);
+ addpts("mac", read_mac_pt);
addpts("sun", read_sun_pt);
++ addpts("ps3", read_ps3_pt);
}
-static char short_opts[] = "ladgvp:t:s";
@@ -299,7 +457,7 @@ index 3d33990..b5e0a32 100644
printf("\t-v verbose\n");
printf("\t-s sync mode. Don't return until the partitions are created\n");
return 1;
-@@ -185,7 +190,8 @@ get_hotplug_device(void)
+@@ -185,7 +192,8 @@ get_hotplug_device(void)
int
main(int argc, char **argv){
@@ -309,7 +467,15 @@ index 3d33990..b5e0a32 100644
struct slice all;
struct pt *ptp;
enum action what = LIST;
-@@ -233,6 +239,12 @@ main(int argc, char **argv){
+@@ -199,7 +207,6 @@ main(int argc, char **argv){
+ int loopro = 0;
+ int hotplug = 0;
+ int loopcreated = 0;
+- int sync = 0;
+ struct stat buf;
+ uint32_t cookie = 0;
+
+@@ -233,6 +240,12 @@ main(int argc, char **argv){
}
while ((arg = getopt(argc, argv, short_opts)) != EOF) switch(arg) {
@@ -322,20 +488,24 @@ index 3d33990..b5e0a32 100644
case 'g':
force_gpt=1;
break;
-@@ -257,15 +269,20 @@ main(int argc, char **argv){
- case 's':
- sync = 1;
+@@ -255,17 +268,22 @@ main(int argc, char **argv){
+ what = DELETE;
break;
+ case 's':
+- sync = 1;
++ udev_sync = 1;
++ break;
+ case 'u':
+ what = UPDATE;
-+ break;
+ break;
default:
usage();
exit(1);
}
+- if (!sync)
+#ifdef LIBDM_API_COOKIE
- if (!sync)
++ if (!udev_sync)
dm_udev_set_sync_support(0);
+#endif
@@ -344,7 +514,7 @@ index 3d33990..b5e0a32 100644
fprintf(stderr, "device mapper prerequisites not met\n");
exit(1);
}
-@@ -306,12 +323,6 @@ main(int argc, char **argv){
+@@ -306,12 +324,6 @@ main(int argc, char **argv){
device = loopdev;
}
@@ -357,7 +527,7 @@ index 3d33990..b5e0a32 100644
off = find_devname_offset(device);
if (!loopdev) {
-@@ -326,6 +337,18 @@ main(int argc, char **argv){
+@@ -326,6 +338,18 @@ main(int argc, char **argv){
if (!mapname)
mapname = device + off;
@@ -371,12 +541,12 @@ index 3d33990..b5e0a32 100644
+ if (delim == NULL) {
+ delim = malloc(DELIM_SIZE);
+ memset(delim, 0, DELIM_SIZE);
-+ set_delimiter(device, delim);
++ set_delimiter(mapname, delim);
+ }
fd = open(device, O_RDONLY);
-@@ -350,8 +373,10 @@ main(int argc, char **argv){
+@@ -350,8 +374,10 @@ main(int argc, char **argv){
printf("%s: %d slices\n", ptp->type, n);
#endif
@@ -388,7 +558,7 @@ index 3d33990..b5e0a32 100644
else
continue;
-@@ -399,15 +424,6 @@ main(int argc, char **argv){
+@@ -399,15 +425,6 @@ main(int argc, char **argv){
break;
}
@@ -404,7 +574,7 @@ index 3d33990..b5e0a32 100644
break;
case DELETE:
-@@ -443,6 +459,8 @@ main(int argc, char **argv){
+@@ -443,6 +460,8 @@ main(int argc, char **argv){
break;
case ADD:
@@ -413,7 +583,7 @@ index 3d33990..b5e0a32 100644
for (j = 0, c = 0; j < n; j++) {
if (slices[j].size == 0)
continue;
-@@ -470,7 +488,7 @@ main(int argc, char **argv){
+@@ -470,7 +489,7 @@ main(int argc, char **argv){
DM_DEVICE_RELOAD : DM_DEVICE_CREATE);
if (!dm_addmap(op, partname, DM_TARGET, params,
@@ -422,7 +592,30 @@ index 3d33990..b5e0a32 100644
buf.st_mode & 0777, buf.st_uid,
buf.st_gid, &cookie)) {
fprintf(stderr, "create/reload failed on %s\n",
-@@ -536,7 +554,7 @@ main(int argc, char **argv){
+@@ -497,7 +516,6 @@ main(int argc, char **argv){
+ d = c;
+ while (c) {
+ for (j = 0; j < n; j++) {
+- uint64_t start;
+ int k = slices[j].container - 1;
+
+ if (slices[j].size == 0)
+@@ -523,11 +541,9 @@ main(int argc, char **argv){
+ }
+ strip_slash(partname);
+
+- start = slices[j].start - slices[k].start;
+- if (safe_sprintf(params, "%d:%d %" PRIu64,
+- slices[k].major,
+- slices[k].minor,
+- start)) {
++ if (safe_sprintf(params, "%s %" PRIu64,
++ device,
++ slices[j].start)) {
+ fprintf(stderr, "params too small\n");
+ exit(1);
+ }
+@@ -536,7 +552,7 @@ main(int argc, char **argv){
DM_DEVICE_RELOAD : DM_DEVICE_CREATE);
dm_addmap(op, partname, DM_TARGET, params,
@@ -431,7 +624,7 @@ index 3d33990..b5e0a32 100644
buf.st_mode & 0777,
buf.st_uid, buf.st_gid,
&cookie);
-@@ -559,7 +577,31 @@ main(int argc, char **argv){
+@@ -559,7 +575,31 @@ main(int argc, char **argv){
if (d == c)
break;
}
@@ -464,7 +657,7 @@ index 3d33990..b5e0a32 100644
default:
break;
-@@ -568,7 +610,20 @@ main(int argc, char **argv){
+@@ -568,7 +608,20 @@ main(int argc, char **argv){
if (n > 0)
break;
}
@@ -485,31 +678,260 @@ index 3d33990..b5e0a32 100644
dm_lib_release();
dm_lib_exit();
+diff --git a/kpartx/kpartx.h b/kpartx/kpartx.h
+index 43ae3f8..61d31b6 100644
+--- a/kpartx/kpartx.h
++++ b/kpartx/kpartx.h
+@@ -39,6 +39,7 @@ extern ptreader read_gpt_pt;
+ extern ptreader read_dasd_pt;
+ extern ptreader read_mac_pt;
+ extern ptreader read_sun_pt;
++extern ptreader read_ps3_pt;
+
+ char *getblock(int fd, unsigned int secnr);
+
diff --git a/kpartx/kpartx.rules b/kpartx/kpartx.rules
-index 8978b73..64863a0 100644
+index 8978b73..b96ec89 100644
--- a/kpartx/kpartx.rules
+++ b/kpartx/kpartx.rules
-@@ -17,19 +17,13 @@ OPTIONS="link_priority=50"
+@@ -8,6 +8,8 @@ KERNEL!="dm-*", GOTO="kpartx_end"
+ ACTION=="remove", GOTO="kpartx_end"
+
+ ENV{DM_TABLE_STATE}!="LIVE", GOTO="kpartx_end"
++ENV{DM_ACTION}=="PATH_FAILED|PATH_REINSTATED", GOTO="kpartx_end"
++ENV{DM_DEPS}=="0", GOTO="kpartx_end"
+
+ ENV{DM_UUID}=="?*", IMPORT{program}=="kpartx_id %M %m $env{DM_UUID}"
+
+@@ -16,20 +18,22 @@ OPTIONS="link_priority=50"
+ # Create persistent links for multipath tables
ENV{DM_UUID}=="mpath-*", \
SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
-
+-
-# Create persistent links for dmraid tables
-ENV{DM_UUID}=="dmraid-*", \
- SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
--
++ENV{DM_MPATH}=="?*", ENV{DM_PART}!="?*", \
++ SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_MPATH}"
++ENV{DM_WWN}=="?*", ENV{DM_PART}!="?*", \
++ SYMLINK+="disk/by-id/wwn-$env{DM_WWN}"
+
# Create persistent links for partitions
ENV{DM_PART}=="?*", \
SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}-part$env{DM_PART}"
++ENV{DM_MPATH}=="?*", ENV{DM_PART}=="?*", \
++ SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_MPATH}-part$env{DM_PART}"
++ENV{DM_WWN}=="?*", ENV{DM_PART}=="?*", \
++ SYMLINK+="disk/by-id/wwn-$env{DM_WWN}-part$env{DM_PART}"
# Create dm tables for partitions
- ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="mpath-*", \
+-ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="mpath-*", \
- RUN+="/sbin/kpartx -a -p -part /dev/$name"
-ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="dmraid-*", \
- RUN+="/sbin/kpartx -a -p -part /dev/$name"
++ENV{DM_STATE}!="SUSPENDED", ENV{DM_UUID}=="mpath-*", \
+ RUN+="/sbin/kpartx -u -p -part /dev/$name"
LABEL="kpartx_end"
+diff --git a/kpartx/kpartx_id b/kpartx/kpartx_id
+index 81f32bf..517b856 100644
+--- a/kpartx/kpartx_id
++++ b/kpartx/kpartx_id
+@@ -55,6 +55,9 @@ if [ "$dmtbl" = "part" ] ; then
+ # The name of the kpartx table is the name of the parent table
+ dmname=$($DMSETUP info -c --noheadings -o name -u $dmuuid)
+ echo "DM_NAME=$dmname"
++ if [ "$dmname" != ${dmuuid#mpath-} ] ; then
++ echo "DM_MPATH=${dmuuid#mpath-}"
++ fi
+ # We need the dependencies of the parent table to figure out
+ # the type if the parent is a multipath table
+ case "$dmuuid" in
+@@ -63,7 +66,10 @@ if [ "$dmtbl" = "part" ] ; then
+ ;;
+ esac
+ elif [ "$dmtbl" = "mpath" ] ; then
+- dmname=$tblname
++ if [ -n "$DM_NAME" -a "$DM_NAME" != "$dmuuid" ] ; then
++ echo "DM_MPATH=$dmuuid"
++ fi
++ dmname="$dmuuid"
+ # We need the dependencies of the table to figure out the type
+ dmdeps=$($DMSETUP deps -u $UUID)
+ elif [ "$dmtbl" = "dmraid" ] ; then
+@@ -77,13 +83,17 @@ fi
+ if [ -n "$dmdeps" ] ; then
+ case "$dmdeps" in
+ *\(94,*)
+- echo "DM_TYPE=dasd"
++ echo "DM_TYPE=ccw"
++ ;;
++ *\(104,* | *\(105,* | *\(106,* | *\(107,* | *\(108,* | *\(109,* | *\(110,* | *\(112,*)
++ echo "DM_TYPE=cciss"
+ ;;
+ *\(9*)
+ echo "DM_TYPE=raid"
+ ;;
+ *)
+ echo "DM_TYPE=scsi"
++ echo "DM_WWN=0x${dmname#?}"
+ ;;
+ esac
+ else
+diff --git a/kpartx/lopart.c b/kpartx/lopart.c
+index 79d8328..79a7593 100644
+--- a/kpartx/lopart.c
++++ b/kpartx/lopart.c
+@@ -26,18 +26,7 @@
+ #include <sys/stat.h>
+ #include <sys/mman.h>
+ #include <sysmacros.h>
+-
+-#if defined(__hppa__) || defined(__powerpc64__) || defined (__alpha__) \
+- || defined (__x86_64__)
+-typedef unsigned long __kernel_old_dev_t;
+-#elif defined(__powerpc__) || defined(__ia64__) || (defined(__sparc__) && defined (__arch64__))
+-typedef unsigned int __kernel_old_dev_t;
+-#else
+-typedef unsigned short __kernel_old_dev_t;
+-#endif
+-
+-#define dev_t __kernel_old_dev_t
+-
++#include <asm/posix_types.h>
+ #include <linux/loop.h>
+
+ #include "lopart.h"
+@@ -216,13 +205,13 @@ find_unused_loop_device (void)
+ fprintf(stderr,
+ "mount: Could not find any loop device, and, according to %s,\n"
+ " this kernel does not know about the loop device.\n"
+- " (If so, then recompile or `insmod loop.o'.)",
++ " (If so, then recompile or `modprobe loop'.)",
+ PROC_DEVICES);
+
+ else
+ fprintf(stderr,
+ "mount: Could not find any loop device. Maybe this kernel does not know\n"
+- " about the loop device (then recompile or `insmod loop.o'), or\n"
++ " about the loop device (then recompile or `modprobe loop'), or\n"
+ " maybe /dev/loop# has the wrong major number?");
+
+ } else
+@@ -286,6 +275,7 @@ set_loop (const char *device, const char *file, int offset, int *loopro)
+ extern int
+ del_loop (const char *device)
+ {
++ int retries = 3;
+ int fd;
+
+ if ((fd = open (device, O_RDONLY)) < 0) {
+@@ -295,10 +285,17 @@ del_loop (const char *device)
+ return 1;
+ }
+
+- if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
+- perror ("ioctl: LOOP_CLR_FD");
+- close (fd);
+- return 1;
++ while (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
++ if (errno != EBUSY || retries-- <= 0) {
++ perror ("ioctl: LOOP_CLR_FD");
++ close (fd);
++ return 1;
++ }
++ fprintf(stderr,
++ "loop: device %s still in use, retrying delete\n",
++ device);
++ sleep(1);
++ continue;
+ }
+
+ close (fd);
+diff --git a/kpartx/ps3.c b/kpartx/ps3.c
+new file mode 100644
+index 0000000..d1e5d64
+--- /dev/null
++++ b/kpartx/ps3.c
+@@ -0,0 +1,77 @@
++#include "kpartx.h"
++#include "byteorder.h"
++#include <sys/types.h>
++#include <string.h>
++
++#define SECTOR_SIZE 512
++#define MAX_ACL_ENTRIES 8
++#define MAX_PARTITIONS 8
++
++#define MAGIC1 0x0FACE0FFULL
++#define MAGIC2 0xDEADFACEULL
++
++struct p_acl_entry {
++ u_int64_t laid;
++ u_int64_t rights;
++};
++
++struct d_partition {
++ u_int64_t p_start;
++ u_int64_t p_size;
++ struct p_acl_entry p_acl[MAX_ACL_ENTRIES];
++};
++
++struct disklabel {
++ u_int8_t d_res1[16];
++ u_int64_t d_magic1;
++ u_int64_t d_magic2;
++ u_int64_t d_res2;
++ u_int64_t d_res3;
++ struct d_partition d_partitions[MAX_PARTITIONS];
++ u_int8_t d_pad[0x600 - MAX_PARTITIONS * sizeof(struct d_partition)- 0x30];
++};
++
++static int
++read_disklabel(int fd, struct disklabel *label) {
++ unsigned char *data;
++ int i;
++
++ for (i = 0; i < sizeof(struct disklabel) / SECTOR_SIZE; i++) {
++ data = (unsigned char *) getblock(fd, i);
++ if (!data)
++ return 0;
++
++ memcpy((unsigned char *) label + i * SECTOR_SIZE, data, SECTOR_SIZE);
++ }
++
++ return 1;
++}
++
++int
++read_ps3_pt(int fd, struct slice all, struct slice *sp, int ns) {
++ struct disklabel label;
++ int n = 0;
++ int i;
++
++ if (!read_disklabel(fd, &label))
++ return -1;
++
++ if ((be64_to_cpu(label.d_magic1) != MAGIC1) ||
++ (be64_to_cpu(label.d_magic2) != MAGIC2))
++ return -1;
++
++ for (i = 0; i < MAX_PARTITIONS; i++) {
++ if (label.d_partitions[i].p_start && label.d_partitions[i].p_size) {
++ sp[n].start = be64_to_cpu(label.d_partitions[i].p_start);
++ sp[n].size = be64_to_cpu(label.d_partitions[i].p_size);
++ n++;
++ }
++ }
++
++ return n;
++}
++
++
++
++
++
diff --git a/libmpathpersist/Makefile b/libmpathpersist/Makefile
new file mode 100644
index 0000000..c4ec1c5
@@ -567,10 +989,10 @@ index 0000000..c4ec1c5
+ rm -f mpath_persistent_reserve_in.3.gz mpath_persistent_reserve_out.3.gz
diff --git a/libmpathpersist/mpath_persist.c b/libmpathpersist/mpath_persist.c
new file mode 100644
-index 0000000..302dd3f
+index 0000000..3041089
--- /dev/null
+++ b/libmpathpersist/mpath_persist.c
-@@ -0,0 +1,885 @@
+@@ -0,0 +1,884 @@
+#include "mpath_persist.h"
+#include <libdevmapper.h>
+#include <defaults.h>
@@ -592,7 +1014,6 @@ index 0000000..302dd3f
+#include <dmparser.h>
+#include <ctype.h>
+#include <propsel.h>
-+#include <sysfs.h>
+
+#include "mpathpr.h"
+#include "mpath_pr_ioctl.h"
@@ -613,10 +1034,6 @@ index 0000000..302dd3f
+ return 1;
+ }
+
-+ if (sysfs_init(conf->sysfs_dir, FILE_NAME_SIZE)){
-+ condlog(0, "Failed. mpathpersist needs sysfs mounted");
-+ exit(1);
-+ }
+ return 0;
+}
+
@@ -755,8 +1172,10 @@ index 0000000..302dd3f
+ goto out;
+ }
+
-+ if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER))
++ if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) {
++ ret = MPATH_PR_DMMP_ERROR;
+ goto out1;
++ }
+
+ /* get info of all paths from the dm device */
+ if (get_mpvec (curmp, pathvec, alias)){
@@ -843,8 +1262,10 @@ index 0000000..302dd3f
+ goto out;
+ }
+
-+ if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER))
++ if (path_discovery(pathvec, conf, DI_SYSFS | DI_CHECKER)) {
++ ret = MPATH_PR_DMMP_ERROR;
+ goto out1;
++ }
+
+ /* get info of all paths from the dm device */
+ if (get_mpvec(curmp, pathvec, alias)){
@@ -986,7 +1407,7 @@ index 0000000..302dd3f
+ int rc;
+ int count=0;
+ int status = MPATH_PR_SUCCESS;
-+ uint64_t sa_key;
++ uint64_t sa_key = 0;
+
+ if (!mpp)
+ return MPATH_PR_DMMP_ERROR;
@@ -1458,7 +1879,7 @@ index 0000000..302dd3f
+
diff --git a/libmpathpersist/mpath_persist.h b/libmpathpersist/mpath_persist.h
new file mode 100644
-index 0000000..42294e9
+index 0000000..d8ff6f2
--- /dev/null
+++ b/libmpathpersist/mpath_persist.h
@@ -0,0 +1,241 @@
@@ -1658,15 +2079,15 @@ index 0000000..42294e9
+ *
+ * @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 below. The caller should
++ * @resp: The response from PRIN service action. The resp is a struct specified above. 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-3]. 0->disabled, 3->Max verbose
+ *
+ * RESTRICTIONS:
+ *
-+ * RETURNS: MPATH_PR_SUCCESS if PR command successful else returns any of the PR status (specified
-+ * above).
++ * RETURNS: MPATH_PR_SUCCESS if PR command successful else returns any of the status specified
++ * above in RETURN_STATUS.
+ *
+ */
+extern int mpath_persistent_reserve_in (int fd, int rq_servact, struct prin_resp *resp,
@@ -1681,7 +2102,7 @@ index 0000000..42294e9
+ * @rq_scope: Persistent reservation scope. The value should be always LU_SCOPE (0h).
+ * @rq_type: Persistent reservation type. The valid values of persistent reservation types are
+ * 5h (Write exclusive - registrants only)
-+ * 8h (Exclusive access - registrants only)
++ * 6h (Exclusive access - registrants only)
+ * 7h (Write exclusive - All registrants)
+ * 8h (Exclusive access - All registrants).
+ * @paramp: PROUT command parameter data. The paramp is a struct which describes PROUT
@@ -1791,7 +2212,7 @@ index 0000000..c404e13
+.br
diff --git a/libmpathpersist/mpath_persistent_reserve_out.3 b/libmpathpersist/mpath_persistent_reserve_out.3
new file mode 100644
-index 0000000..44f950b
+index 0000000..f7f84ff
--- /dev/null
+++ b/libmpathpersist/mpath_persistent_reserve_out.3
@@ -0,0 +1,92 @@
@@ -1823,7 +2244,7 @@ index 0000000..44f950b
+.I rq_type
+.B Persistent reservation type. The valid values of persistent reservation types are
+ 5h (Write exclusive - registrants only)
-+ 8h (Exclusive access - registrants only)
++ 6h (Exclusive access - registrants only)
+ 7h (Write exclusive - All registrants)
+ 8h (Exclusive access - All registrants).
+.br
@@ -1889,10 +2310,10 @@ index 0000000..44f950b
+.br
diff --git a/libmpathpersist/mpath_pr_ioctl.c b/libmpathpersist/mpath_pr_ioctl.c
new file mode 100644
-index 0000000..2d4d968
+index 0000000..de3292e
--- /dev/null
+++ b/libmpathpersist/mpath_pr_ioctl.c
-@@ -0,0 +1,574 @@
+@@ -0,0 +1,583 @@
+#include <stdio.h>
+#include <stdlib.h>
+
@@ -2209,6 +2630,11 @@ index 0000000..2d4d968
+ else
+ mx_resp_len = get_prin_length(rq_servact);
+
++ if (mx_resp_len == 0) {
++ status = MPATH_PR_SYNTAX_ERROR;
++ goto out;
++ }
++
+ cdb[1] = (unsigned char)(rq_servact & 0x1f);
+ cdb[7] = (unsigned char)((mx_resp_len >> 8) & 0xff);
+ cdb[8] = (unsigned char)(mx_resp_len & 0xff);
@@ -2464,6 +2890,10 @@ index 0000000..2d4d968
+ 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;
+}
@@ -2586,10 +3016,10 @@ index 0000000..573ff15
+
diff --git a/libmpathpersist/mpath_updatepr.c b/libmpathpersist/mpath_updatepr.c
new file mode 100644
-index 0000000..2982947
+index 0000000..8597d40
--- /dev/null
+++ b/libmpathpersist/mpath_updatepr.c
-@@ -0,0 +1,50 @@
+@@ -0,0 +1,51 @@
+#include<stdio.h>
+#include<unistd.h>
+#include <errno.h>
@@ -2606,6 +3036,7 @@ index 0000000..2982947
+#include <debug.h>
+#include "memory.h"
+#include "../libmultipath/uxsock.h"
++#include "../libmultipath/defaults.h"
+
+unsigned long mem_allocated; /* Total memory used in Bytes */
+
@@ -2617,7 +3048,7 @@ index 0000000..2982947
+ size_t len;
+ int ret = 0;
+
-+ fd = ux_socket_connect("/var/run/multipathd.sock");
++ fd = ux_socket_connect(DEFAULT_SOCKET);
+ if (fd == -1) {
+ condlog (0, "ux socket connect error");
+ return 1 ;
@@ -2702,10 +3133,29 @@ index 0000000..54dfb3e
+
+#endif
diff --git a/libmultipath/Makefile b/libmultipath/Makefile
-index 203833d..f396f49 100644
+index 203833d..22d3844 100644
--- a/libmultipath/Makefile
+++ b/libmultipath/Makefile
-@@ -23,10 +23,16 @@ ifneq ($(strip $(LIBDM_API_FLUSH)),0)
+@@ -7,15 +7,15 @@ include ../Makefile.inc
+ SONAME=0
+ DEVLIB = libmultipath.so
+ LIBS = $(DEVLIB).$(SONAME)
+-LIBDEPS = -lpthread -ldl -ldevmapper
++LIBDEPS = -lpthread -ldl -ldevmapper -ludev
+
+-OBJS = memory.o parser.o vector.o devmapper.o callout.o \
++OBJS = memory.o parser.o vector.o devmapper.o \
+ hwtable.o blacklist.o util.o dmparser.o config.o \
+ structs.o discovery.o propsel.o dict.o \
+ pgpolicies.o debug.o regex.o defaults.o uevent.o \
+ switchgroup.o uxsock.o print.o alias.o log_pthread.o \
+ log.o configure.o structs_vec.o sysfs.o prio.o checkers.o \
+- lock.o waiter.o
++ lock.o waiter.o file.o wwids.o prioritizers/alua_rtpg.o
+
+ LIBDM_API_FLUSH = $(shell grep -Ecs '^[a-z]*[[:space:]]+dm_task_no_flush' /usr/include/libdevmapper.h)
+
+@@ -23,10 +23,23 @@ ifneq ($(strip $(LIBDM_API_FLUSH)),0)
CFLAGS += -DLIBDM_API_FLUSH -D_GNU_SOURCE
endif
@@ -2715,6 +3165,13 @@ index 203833d..f396f49 100644
+ CFLAGS += -DLIBDM_API_COOKIE
+endif
+
++LIBUDEV_API_RECVBUF = $(shell grep -Ecs '^[a-z]*[[:space:]]+udev_monitor_set_resolve_buffer_size' /usr/include/libudev.h)
++
++ifneq ($(strip $(LIBUDEV_API_RECVBUF)),0)
++ CFLAGS += -DLIBUDEV_API_RECVBUF
++endif
++
++
all: $(LIBS)
$(LIBS): $(OBJS)
@@ -2724,13 +3181,181 @@ index 203833d..f396f49 100644
install:
diff --git a/libmultipath/alias.c b/libmultipath/alias.c
-index 95506b4..4159ec6 100644
+index 95506b4..d913294 100644
--- a/libmultipath/alias.c
+++ b/libmultipath/alias.c
-@@ -180,34 +180,35 @@ fail:
- }
+@@ -3,19 +3,19 @@
+ * Copyright (c) 2005 Benjamin Marzinski, Redhat
+ */
+ #include <stdlib.h>
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#include <fcntl.h>
+ #include <errno.h>
+ #include <unistd.h>
+ #include <string.h>
+ #include <limits.h>
+ #include <stdio.h>
+-#include <signal.h>
+
+ #include "debug.h"
+ #include "uxsock.h"
+ #include "alias.h"
++#include "file.h"
++#include "vector.h"
++#include "checkers.h"
++#include "structs.h"
+
+
+ /*
+@@ -36,178 +36,37 @@
+ * See the file COPYING included with this distribution for more details.
+ */
+
+-static int
+-ensure_directories_exist(char *str, mode_t dir_mode)
+-{
+- char *pathname;
+- char *end;
+- int err;
+-
+- pathname = strdup(str);
+- if (!pathname){
+- condlog(0, "Cannot copy bindings file pathname : %s",
+- strerror(errno));
+- return -1;
+- }
+- end = pathname;
+- /* skip leading slashes */
+- while (end && *end && (*end == '/'))
+- end++;
+-
+- while ((end = strchr(end, '/'))) {
+- /* if there is another slash, make the dir. */
+- *end = '\0';
+- err = mkdir(pathname, dir_mode);
+- if (err && errno != EEXIST) {
+- condlog(0, "Cannot make directory [%s] : %s",
+- pathname, strerror(errno));
+- free(pathname);
+- return -1;
+- }
+- if (!err)
+- condlog(3, "Created dir [%s]", pathname);
+- *end = '/';
+- end++;
+- }
+- free(pathname);
+- return 0;
+-}
+-
+-static void
+-sigalrm(int sig)
+-{
+- /* do nothing */
+-}
static int
+-lock_bindings_file(int fd)
+-{
+- struct sigaction act, oldact;
+- sigset_t set, oldset;
+- struct flock lock;
+- int err;
+-
+- memset(&lock, 0, sizeof(lock));
+- lock.l_type = F_WRLCK;
+- lock.l_whence = SEEK_SET;
+-
+- act.sa_handler = sigalrm;
+- sigemptyset(&act.sa_mask);
+- act.sa_flags = 0;
+- sigemptyset(&set);
+- sigaddset(&set, SIGALRM);
+-
+- sigaction(SIGALRM, &act, &oldact);
+- sigprocmask(SIG_UNBLOCK, &set, &oldset);
+-
+- alarm(BINDINGS_FILE_TIMEOUT);
+- err = fcntl(fd, F_SETLKW, &lock);
+- alarm(0);
+-
+- if (err) {
+- if (errno != EINTR)
+- condlog(0, "Cannot lock bindings file : %s",
+- strerror(errno));
+- else
+- condlog(0, "Bindings file is locked. Giving up.");
+- }
+-
+- sigprocmask(SIG_SETMASK, &oldset, NULL);
+- sigaction(SIGALRM, &oldact, NULL);
+- return err;
+-
+-}
+-
+-
+-static int
+-open_bindings_file(char *file, int *can_write)
+-{
+- int fd;
+- struct stat s;
+-
+- if (ensure_directories_exist(file, 0700))
+- return -1;
+- *can_write = 1;
+- fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+- if (fd < 0) {
+- if (errno == EROFS) {
+- *can_write = 0;
+- condlog(3, "Cannot open bindings file [%s] read/write. "
+- " trying readonly", file);
+- fd = open(file, O_RDONLY);
+- if (fd < 0) {
+- condlog(0, "Cannot open bindings file [%s] "
+- "readonly : %s", file, strerror(errno));
+- return -1;
+- }
+- }
+- else {
+- condlog(0, "Cannot open bindings file [%s] : %s", file,
+- strerror(errno));
+- return -1;
+- }
+- }
+- if (*can_write && lock_bindings_file(fd) < 0)
+- goto fail;
+-
+- memset(&s, 0, sizeof(s));
+- if (fstat(fd, &s) < 0){
+- condlog(0, "Cannot stat bindings file : %s", strerror(errno));
+- goto fail;
+- }
+- if (s.st_size == 0) {
+- if (*can_write == 0)
+- goto fail;
+- /* If bindings file is empty, write the header */
+- size_t len = strlen(BINDINGS_FILE_HEADER);
+- if (write_all(fd, BINDINGS_FILE_HEADER, len) != len) {
+- condlog(0,
+- "Cannot write header to bindings file : %s",
+- strerror(errno));
+- /* cleanup partially written header */
+- ftruncate(fd, 0);
+- goto fail;
+- }
+- fsync(fd);
+- condlog(3, "Initialized new bindings file [%s]", file);
+- }
+-
+- return fd;
+-
+-fail:
+- close(fd);
+- return -1;
+-}
+-
+-static int
-format_devname(char *name, int id, int len)
+format_devname(char *name, int id, int len, char *prefix)
{
@@ -2772,7 +3397,7 @@ index 95506b4..4159ec6 100644
while (*c != '\0' && *c != ' ' && *c != '\t') {
i = *c - 'a';
n = ( n * 26 ) + i;
-@@ -221,7 +222,7 @@ scan_devname(char *alias)
+@@ -221,7 +80,7 @@ scan_devname(char *alias)
}
static int
@@ -2781,7 +3406,7 @@ index 95506b4..4159ec6 100644
{
char buf[LINE_MAX];
unsigned int line_nr = 0;
-@@ -240,7 +241,7 @@ lookup_binding(FILE *f, char *map_wwid, char **map_alias)
+@@ -240,10 +99,10 @@ lookup_binding(FILE *f, char *map_wwid, char **map_alias)
alias = strtok(buf, " \t");
if (!alias) /* blank line */
continue;
@@ -2789,9 +3414,38 @@ index 95506b4..4159ec6 100644
+ curr_id = scan_devname(alias, prefix);
if (curr_id >= id)
id = curr_id + 1;
- wwid = strtok(NULL, "");
-@@ -284,7 +285,7 @@ rlookup_binding(FILE *f, char **map_wwid, char *map_alias)
- alias = strtok(buf, " \t");
+- wwid = strtok(NULL, "");
++ wwid = strtok(NULL, " \t");
+ if (!wwid){
+ condlog(3,
+ "Ignoring malformed line %u in bindings file",
+@@ -265,26 +124,26 @@ lookup_binding(FILE *f, char *map_wwid, char **map_alias)
+ }
+
+ static int
+-rlookup_binding(FILE *f, char **map_wwid, char *map_alias)
++rlookup_binding(FILE *f, char *buff, char *map_alias)
+ {
+- char buf[LINE_MAX];
++ char line[LINE_MAX];
+ unsigned int line_nr = 0;
+ int id = 0;
+
+- *map_wwid = NULL;
++ buff[0] = '\0';
+
+- while (fgets(buf, LINE_MAX, f)) {
++ while (fgets(line, LINE_MAX, f)) {
+ char *c, *alias, *wwid;
+ int curr_id;
+
+ line_nr++;
+- c = strpbrk(buf, "#\n\r");
++ c = strpbrk(line, "#\n\r");
+ if (c)
+ *c = '\0';
+- alias = strtok(buf, " \t");
++ alias = strtok(line, " \t");
if (!alias) /* blank line */
continue;
- curr_id = scan_devname(alias);
@@ -2799,7 +3453,28 @@ index 95506b4..4159ec6 100644
if (curr_id >= id)
id = curr_id + 1;
wwid = strtok(NULL, " \t");
-@@ -309,7 +310,7 @@ rlookup_binding(FILE *f, char **map_wwid, char *map_alias)
+@@ -294,13 +153,16 @@ rlookup_binding(FILE *f, char **map_wwid, char *map_alias)
+ line_nr);
+ continue;
+ }
++ if (strlen(wwid) > WWID_SIZE - 1) {
++ condlog(3,
++ "Ignoring too large wwid at %u in bindings file", line_nr);
++ continue;
++ }
+ if (strcmp(alias, map_alias) == 0){
+ condlog(3, "Found matching alias [%s] in bindings file."
+ "\nSetting wwid to %s", alias, wwid);
+- *map_wwid = strdup(wwid);
+- if (*map_wwid == NULL)
+- condlog(0, "Cannot copy alias from bindings "
+- "file : %s", strerror(errno));
++ strncpy(buff, wwid, WWID_SIZE);
++ buff[WWID_SIZE - 1] = '\0';
+ return id;
+ }
+ }
+@@ -309,7 +171,7 @@ rlookup_binding(FILE *f, char **map_wwid, char *map_alias)
}
static char *
@@ -2808,7 +3483,7 @@ index 95506b4..4159ec6 100644
{
char buf[LINE_MAX];
off_t offset;
-@@ -321,7 +322,7 @@ allocate_binding(int fd, char *wwid, int id)
+@@ -321,7 +183,7 @@ allocate_binding(int fd, char *wwid, int id)
return NULL;
}
@@ -2817,7 +3492,18 @@ index 95506b4..4159ec6 100644
c = buf + i;
snprintf(c,LINE_MAX - i, " %s\n", wwid);
buf[LINE_MAX - 1] = '\0';
-@@ -352,7 +353,8 @@ allocate_binding(int fd, char *wwid, int id)
+@@ -336,7 +198,9 @@ allocate_binding(int fd, char *wwid, int id)
+ condlog(0, "Cannot write binding to bindings file : %s",
+ strerror(errno));
+ /* clear partial write */
+- ftruncate(fd, offset);
++ if (ftruncate(fd, offset))
++ condlog(0, "Cannot truncate the header : %s",
++ strerror(errno));
+ return NULL;
+ }
+ c = strchr(buf, ' ');
+@@ -352,10 +216,11 @@ allocate_binding(int fd, char *wwid, int id)
}
char *
@@ -2826,8 +3512,35 @@ index 95506b4..4159ec6 100644
+ int bindings_read_only)
{
char *alias;
- int fd, scan_fd, id;
-@@ -385,7 +387,7 @@ get_user_friendly_alias(char *wwid, char *file)
+- int fd, scan_fd, id;
++ int fd, id;
+ FILE *f;
+ int can_write;
+
+@@ -364,87 +229,67 @@ get_user_friendly_alias(char *wwid, char *file)
+ return NULL;
+ }
+
+- fd = open_bindings_file(file, &can_write);
++ fd = open_file(file, &can_write, BINDINGS_FILE_HEADER);
+ if (fd < 0)
+ return NULL;
+
+- scan_fd = dup(fd);
+- if (scan_fd < 0) {
+- condlog(0, "Cannot dup bindings file descriptor : %s",
+- strerror(errno));
+- close(fd);
+- return NULL;
+- }
+-
+- f = fdopen(scan_fd, "r");
++ f = fdopen(fd, "r");
+ if (!f) {
+ condlog(0, "cannot fdopen on bindings file descriptor : %s",
+ strerror(errno));
+- close(scan_fd);
+ close(fd);
return NULL;
}
@@ -2835,41 +3548,241 @@ index 95506b4..4159ec6 100644
+ id = lookup_binding(f, wwid, &alias, prefix);
if (id < 0) {
fclose(f);
- close(scan_fd);
-@@ -393,8 +395,8 @@ get_user_friendly_alias(char *wwid, char *file)
+- close(scan_fd);
+- close(fd);
return NULL;
}
- if (!alias && can_write)
- alias = allocate_binding(fd, wwid, id);
++ if (fflush(f) != 0) {
++ condlog(0, "cannot fflush bindings file stream : %s",
++ strerror(errno));
++ fclose(f);
++ return NULL;
++ }
++
+ if (!alias && can_write && !bindings_read_only)
+ alias = allocate_binding(fd, wwid, id, prefix);
fclose(f);
- close(scan_fd);
+- close(scan_fd);
+- close(fd);
+ return alias;
+ }
+
+-char *
+-get_user_friendly_wwid(char *alias, char *file)
++int
++get_user_friendly_wwid(char *alias, char *buff, char *file)
+ {
+- char *wwid;
+- int fd, scan_fd, id, unused;
++ int fd, unused;
+ FILE *f;
+
+ if (!alias || *alias == '\0') {
+ condlog(3, "Cannot find binding for empty alias");
+- return NULL;
++ return -1;
+ }
+
+- fd = open_bindings_file(file, &unused);
++ fd = open_file(file, &unused, BINDINGS_FILE_HEADER);
+ if (fd < 0)
+- return NULL;
+-
+- scan_fd = dup(fd);
+- if (scan_fd < 0) {
+- condlog(0, "Cannot dup bindings file descriptor : %s",
+- strerror(errno));
+- close(fd);
+- return NULL;
+- }
++ return -1;
+
+- f = fdopen(scan_fd, "r");
++ f = fdopen(fd, "r");
+ if (!f) {
+ condlog(0, "cannot fdopen on bindings file descriptor : %s",
+ strerror(errno));
+- close(scan_fd);
+ close(fd);
+- return NULL;
++ return -1;
+ }
+
+- id = rlookup_binding(f, &wwid, alias);
+- if (id < 0) {
++ rlookup_binding(f, buff, alias);
++ if (!strlen(buff)) {
+ fclose(f);
+- close(scan_fd);
+- close(fd);
+- return NULL;
++ return -1;
+ }
+
+ fclose(f);
+- close(scan_fd);
+- close(fd);
+- return wwid;
++ return 0;
+ }
diff --git a/libmultipath/alias.h b/libmultipath/alias.h
-index fe1191b..c489a86 100644
+index fe1191b..8ddd0b5 100644
--- a/libmultipath/alias.h
+++ b/libmultipath/alias.h
-@@ -8,5 +8,6 @@
+@@ -1,4 +1,3 @@
+-#define BINDINGS_FILE_TIMEOUT 30
+ #define BINDINGS_FILE_HEADER \
+ "# Multipath bindings, Version : 1.0\n" \
+ "# NOTE: this file is automatically maintained by the multipath program.\n" \
+@@ -8,5 +7,6 @@
"# alias wwid\n" \
"#\n"
-char *get_user_friendly_alias(char *wwid, char *file);
+-char *get_user_friendly_wwid(char *alias, char *file);
+char *get_user_friendly_alias(char *wwid, char *file, char *prefix,
+ int bindings_readonly);
- char *get_user_friendly_wwid(char *alias, char *file);
-diff --git a/libmultipath/callout.c b/libmultipath/callout.c
-index 520343e..ae19051 100644
---- a/libmultipath/callout.c
-+++ b/libmultipath/callout.c
-@@ -17,17 +17,9 @@
- #include "checkers.h"
- #include "vector.h"
- #include "structs.h"
-+#include "util.h"
- #include "debug.h"
++int get_user_friendly_wwid(char *alias, char *buff, char *file);
+diff --git a/libmultipath/blacklist.c b/libmultipath/blacklist.c
+index f369517..49a40f9 100644
+--- a/libmultipath/blacklist.c
++++ b/libmultipath/blacklist.c
+@@ -96,50 +96,6 @@ set_ble_device (vector blist, char * vendor, char * product, int origin)
+ }
+
+ int
+-setup_default_blist (struct config * conf)
+-{
+- struct blentry * ble;
+- struct hwentry *hwe;
+- char * str;
+- int i;
+-
+- str = STRDUP("^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*");
+- if (!str)
+- return 1;
+- if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
+- return 1;
+-
+- str = STRDUP("^hd[a-z]");
+- if (!str)
+- return 1;
+- if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
+- return 1;
+-
+- str = STRDUP("^dcssblk[0-9]*");
+- if (!str)
+- return 1;
+- if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
+- return 1;
+-
+- vector_foreach_slot (conf->hwtable, hwe, i) {
+- if (hwe->bl_product) {
+- if (alloc_ble_device(conf->blist_device))
+- return 1;
+- ble = VECTOR_SLOT(conf->blist_device,
+- VECTOR_SIZE(conf->blist_device) -1);
+- if (set_ble_device(conf->blist_device,
+- STRDUP(hwe->vendor),
+- STRDUP(hwe->bl_product),
+- ORIGIN_DEFAULT)) {
+- FREE(ble);
+- return 1;
+- }
+- }
+- }
+- return 0;
+-}
+-
+-int
+ _blacklist_exceptions (vector elist, char * str)
+ {
+ int i;
+@@ -193,6 +149,53 @@ _blacklist_device (vector blist, char * vendor, char * product)
+ return 0;
+ }
++int
++setup_default_blist (struct config * conf)
++{
++ struct blentry * ble;
++ struct hwentry *hwe;
++ char * str;
++ int i;
++
++ str = STRDUP("^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*");
++ if (!str)
++ return 1;
++ if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
++ return 1;
++
++ str = STRDUP("^hd[a-z]");
++ if (!str)
++ return 1;
++ if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
++ return 1;
++
++ str = STRDUP("^dcssblk[0-9]*");
++ if (!str)
++ return 1;
++ if (store_ble(conf->blist_devnode, str, ORIGIN_DEFAULT))
++ return 1;
++
++ vector_foreach_slot (conf->hwtable, hwe, i) {
++ if (hwe->bl_product) {
++ if (_blacklist_device(conf->blist_device, hwe->vendor,
++ hwe->bl_product))
++ continue;
++ if (alloc_ble_device(conf->blist_device))
++ return 1;
++ ble = VECTOR_SLOT(conf->blist_device,
++ VECTOR_SIZE(conf->blist_device) -1);
++ if (set_ble_device(conf->blist_device,
++ STRDUP(hwe->vendor),
++ STRDUP(hwe->bl_product),
++ ORIGIN_DEFAULT)) {
++ FREE(ble);
++ return 1;
++ }
++ }
++ }
++ return 0;
++}
++
+ #define LOG_BLIST(M) \
+ if (vendor && product) \
+ condlog(3, "%s: (%s:%s) %s", dev, vendor, product, (M)); \
+diff --git a/libmultipath/callout.c b/libmultipath/callout.c
+deleted file mode 100644
+index 520343e..0000000
+--- a/libmultipath/callout.c
++++ /dev/null
+@@ -1,224 +0,0 @@
+-/*
+- * Source: copy of the udev package source file
+- *
+- * Copyrights of the source file apply
+- * Copyright (c) 2004 Christophe Varoqui
+- */
+-#include <stdio.h>
+-#include <sys/stat.h>
+-#include <string.h>
+-#include <unistd.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#include <fcntl.h>
+-#include <sys/wait.h>
+-#include <errno.h>
+-
+-#include "checkers.h"
+-#include "vector.h"
+-#include "structs.h"
+-#include "debug.h"
+-
-#define PROGRAM_SIZE 100
-#define FIELD_PROGRAM
-
@@ -2879,31 +3792,213 @@ index 520343e..ae19051 100644
- strncpy(to, from, sizeof(to)-1); \
-} while (0)
-
- int execute_program(char *path, char *value, int len)
- {
- int retval;
-@@ -36,16 +28,17 @@ int execute_program(char *path, char *value, int len)
- int fds[2], null_fd;
- pid_t pid;
- char *pos;
+-int execute_program(char *path, char *value, int len)
+-{
+- int retval;
+- int count;
+- int status;
+- int fds[2], null_fd;
+- pid_t pid;
+- char *pos;
- char arg[PROGRAM_SIZE];
- char *argv[sizeof(arg) / 2];
-+ char arg[CALLOUT_MAX_SIZE];
-+ int argc = sizeof(arg) / 2;
-+ char *argv[argc + 1];
- int i;
-
- i = 0;
-
- if (strchr(path, ' ')) {
+- int i;
+-
+- i = 0;
+-
+- if (strchr(path, ' ')) {
- strfieldcpy(arg, path);
-+ strlcpy(arg, path, sizeof(arg));
- pos = arg;
+- pos = arg;
- while (pos != NULL) {
-+ while (pos != NULL && i < argc) {
- if (pos[0] == '\'') {
- /* don't separate if in apostrophes */
- pos++;
+- if (pos[0] == '\'') {
+- /* don't separate if in apostrophes */
+- pos++;
+- argv[i] = strsep(&pos, "\'");
+- while (pos[0] == ' ')
+- pos++;
+- } else {
+- argv[i] = strsep(&pos, " ");
+- }
+- i++;
+- }
+- } else {
+- argv[i++] = path;
+- }
+- argv[i] = NULL;
+-
+- retval = pipe(fds);
+-
+- if (retval != 0) {
+- condlog(0, "error creating pipe for callout: %s", strerror(errno));
+- return -1;
+- }
+-
+- pid = fork();
+-
+- switch(pid) {
+- case 0:
+- /* child */
+- close(STDOUT_FILENO);
+-
+- /* dup write side of pipe to STDOUT */
+- if (dup(fds[1]) < 0)
+- return -1;
+-
+- /* Ignore writes to stderr */
+- null_fd = open("/dev/null", O_WRONLY);
+- if (null_fd > 0) {
+- close(STDERR_FILENO);
+- dup(null_fd);
+- close(null_fd);
+- }
+-
+- retval = execv(argv[0], argv);
+- condlog(0, "error execing %s : %s", argv[0], strerror(errno));
+- exit(-1);
+- case -1:
+- condlog(0, "fork failed: %s", strerror(errno));
+- close(fds[0]);
+- close(fds[1]);
+- return -1;
+- default:
+- /* parent reads from fds[0] */
+- close(fds[1]);
+- retval = 0;
+- i = 0;
+- while (1) {
+- count = read(fds[0], value + i, len - i-1);
+- if (count <= 0)
+- break;
+-
+- i += count;
+- if (i >= len-1) {
+- condlog(0, "not enough space for response from %s", argv[0]);
+- retval = -1;
+- break;
+- }
+- }
+-
+- if (count < 0) {
+- condlog(0, "no response from %s", argv[0]);
+- retval = -1;
+- }
+-
+- if (i > 0 && value[i-1] == '\n')
+- i--;
+- value[i] = '\0';
+-
+- wait(&status);
+- close(fds[0]);
+-
+- retval = -1;
+- if (WIFEXITED(status)) {
+- status = WEXITSTATUS(status);
+- if (status == 0)
+- retval = 0;
+- else
+- condlog(0, "%s exitted with %d", argv[0], status);
+- }
+- else if (WIFSIGNALED(status))
+- condlog(0, "%s was terminated by signal %d", argv[0], WTERMSIG(status));
+- else
+- condlog(0, "%s terminated abnormally", argv[0]);
+- }
+- return retval;
+-}
+-
+-extern int
+-apply_format (char * string, char * cmd, struct path * pp)
+-{
+- char * pos;
+- char * dst;
+- char * p;
+- char * q;
+- int len;
+- int myfree;
+-
+- if (!string)
+- return 1;
+-
+- if (!cmd)
+- return 1;
+-
+- dst = cmd;
+- p = dst;
+- pos = strchr(string, '%');
+- myfree = CALLOUT_MAX_SIZE;
+-
+- if (!pos) {
+- strcpy(dst, string);
+- return 0;
+- }
+-
+- len = (int) (pos - string) + 1;
+- myfree -= len;
+-
+- if (myfree < 2)
+- return 1;
+-
+- snprintf(p, len, "%s", string);
+- p += len - 1;
+- pos++;
+-
+- switch (*pos) {
+- case 'n':
+- len = strlen(pp->dev) + 1;
+- myfree -= len;
+-
+- if (myfree < 2)
+- return 1;
+-
+- snprintf(p, len, "%s", pp->dev);
+- for (q = p; q < p + len; q++) {
+- if (q && *q == '!')
+- *q = '/';
+- }
+- p += len - 1;
+- break;
+- case 'd':
+- len = strlen(pp->dev_t) + 1;
+- myfree -= len;
+-
+- if (myfree < 2)
+- return 1;
+-
+- snprintf(p, len, "%s", pp->dev_t);
+- p += len - 1;
+- break;
+- default:
+- break;
+- }
+- pos++;
+-
+- if (!*pos)
+- return 0;
+-
+- len = strlen(pos) + 1;
+- myfree -= len;
+-
+- if (myfree < 2)
+- return 1;
+-
+- snprintf(p, len, "%s", pos);
+- condlog(3, "reformated callout = %s", dst);
+- return 0;
+-}
+-
+diff --git a/libmultipath/callout.h b/libmultipath/callout.h
+deleted file mode 100644
+index ab648e8..0000000
+--- a/libmultipath/callout.h
++++ /dev/null
+@@ -1,7 +0,0 @@
+-#ifndef _CALLOUT_H
+-#define _CALLOUT_H
+-
+-int execute_program(char *, char *, int);
+-int apply_format (char *, char *, struct path *);
+-
+-#endif /* _CALLOUT_H */
diff --git a/libmultipath/checkers.c b/libmultipath/checkers.c
index 19d0781..01dafdd 100644
--- a/libmultipath/checkers.c
@@ -3289,10 +4384,18 @@ index 6696b41..46fe6a7 100644
switch (ret)
{
diff --git a/libmultipath/checkers/emc_clariion.c b/libmultipath/checkers/emc_clariion.c
-index 3a88b0b..b42d267 100644
+index 3a88b0b..5d87bfd 100644
--- a/libmultipath/checkers/emc_clariion.c
+++ b/libmultipath/checkers/emc_clariion.c
-@@ -113,7 +113,7 @@ int libcheck_check (struct checker * c)
+@@ -15,6 +15,7 @@
+ #include "../libmultipath/sg_include.h"
+ #include "libsg.h"
+ #include "checkers.h"
++#include "debug.h"
+
+ #define INQUIRY_CMD 0x12
+ #define INQUIRY_CMDLEN 6
+@@ -113,7 +114,7 @@ int libcheck_check (struct checker * c)
io_hdr.dxferp = sense_buffer;
io_hdr.cmdp = inqCmdBlk;
io_hdr.sbp = sb;
@@ -3301,7 +4404,7 @@ index 3a88b0b..b42d267 100644
io_hdr.pack_id = 0;
if (ioctl(c->fd, SG_IO, &io_hdr) < 0) {
MSG(c, "emc_clariion_checker: sending query command failed");
-@@ -182,7 +182,8 @@ int libcheck_check (struct checker * c)
+@@ -182,7 +183,8 @@ int libcheck_check (struct checker * c)
unsigned char buf[4096];
memset(buf, 0, 4096);
@@ -3311,6 +4414,24 @@ index 3a88b0b..b42d267 100644
if (ret == PATH_DOWN) {
hexadecimal_to_ascii(ct->wwn, wwnstr);
+@@ -198,7 +200,7 @@ int libcheck_check (struct checker * c)
+ * 02/04/03 not 05/25/01 on read.
+ */
+ SET_INACTIVE_SNAP(c);
+- MSG(c, "emc_clariion_checker: Active "
++ condlog(3, "emc_clariion_checker: Active "
+ "path to inactive snapshot WWN %s.",
+ wwnstr);
+ } else
+@@ -219,7 +221,7 @@ int libcheck_check (struct checker * c)
+ } else {
+ if (IS_INACTIVE_SNAP(c)) {
+ hexadecimal_to_ascii(ct->wwn, wwnstr);
+- MSG(c, "emc_clariion_checker: Passive "
++ condlog(3, "emc_clariion_checker: Passive "
+ "path to inactive snapshot WWN %s.",
+ wwnstr);
+ ret = PATH_DOWN;
diff --git a/libmultipath/checkers/hp_sw.c b/libmultipath/checkers/hp_sw.c
index 3f28d85..b50ac0c 100644
--- a/libmultipath/checkers/hp_sw.c
@@ -3435,7 +4556,7 @@ index 97c4491..3994f45 100644
#endif /* _LIBSG_H */
diff --git a/libmultipath/checkers/rdac.c b/libmultipath/checkers/rdac.c
-index d12eed1..d7dfb08 100644
+index d12eed1..5f24f55 100644
--- a/libmultipath/checkers/rdac.c
+++ b/libmultipath/checkers/rdac.c
@@ -12,28 +12,113 @@
@@ -3549,7 +4670,7 @@ index d12eed1..d7dfb08 100644
+ set = 1;
+out:
+ if (set == 0)
-+ condlog(0, "rdac checker failed to set TAS bit");
++ condlog(3, "rdac checker failed to set TAS bit");
return 0;
}
@@ -3579,7 +4700,7 @@ index d12eed1..d7dfb08 100644
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
return 1;
-@@ -72,6 +160,22 @@ do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len)
+@@ -72,6 +160,23 @@ do_inq(int sg_fd, unsigned int pg_op, void *resp, int mx_resp_len)
if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
(0 == io_hdr.driver_status))
return 0;
@@ -3589,6 +4710,7 @@ index d12eed1..d7dfb08 100644
+ switch (io_hdr.host_status) {
+ case DID_BUS_BUSY:
+ case DID_ERROR:
++ case DID_SOFT_ERROR:
+ case DID_TRANSPORT_DISRUPTED:
+ /* Transport error, retry */
+ if (--retry_rdac)
@@ -3602,7 +4724,7 @@ index d12eed1..d7dfb08 100644
if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
(SCSI_COMMAND_TERMINATED == io_hdr.status) ||
(SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
-@@ -94,7 +198,10 @@ struct volume_access_inq
+@@ -94,7 +199,10 @@ struct volume_access_inq
char PQ_PDT;
char dontcare0[7];
char avtcvp;
@@ -3614,7 +4736,7 @@ index d12eed1..d7dfb08 100644
};
extern int
-@@ -104,16 +211,29 @@ libcheck_check (struct checker * c)
+@@ -104,16 +212,29 @@ libcheck_check (struct checker * c)
int ret;
memset(&inq, 0, sizeof(struct volume_access_inq));
@@ -3662,7 +4784,7 @@ index 24182e6..0550fb6 100644
switch (ret)
{
diff --git a/libmultipath/checkers/tur.c b/libmultipath/checkers/tur.c
-index 47107a2..224cf76 100644
+index 47107a2..9c141aa 100644
--- a/libmultipath/checkers/tur.c
+++ b/libmultipath/checkers/tur.c
@@ -12,10 +12,14 @@
@@ -3680,7 +4802,7 @@ index 47107a2..224cf76 100644
#define TUR_CMD_LEN 6
#define HEAVY_CHECK_COUNT 10
-@@ -23,23 +27,54 @@
+@@ -23,23 +27,80 @@
#define MSG_TUR_UP "tur checker reports path is up"
#define MSG_TUR_DOWN "tur checker reports path is down"
#define MSG_TUR_GHOST "tur checker reports path is in standby state"
@@ -3693,10 +4815,15 @@ index 47107a2..224cf76 100644
+ dev_t devt;
+ int state;
+ int running;
-+ time_t timeout;
++ int fd;
++ unsigned int timeout;
++ time_t time;
+ pthread_t thread;
+ pthread_mutex_t lock;
+ pthread_cond_t active;
++ pthread_spinlock_t hldr_lock;
++ int holders;
++ char message[CHECKER_MSG_LEN];
};
+#define TUR_DEVT(c) major((c)->devt), minor((c)->devt)
@@ -3711,21 +4838,40 @@ index 47107a2..224cf76 100644
+ memset(ct, 0, sizeof(struct tur_checker_context));
+
+ ct->state = PATH_UNCHECKED;
++ ct->fd = -1;
++ ct->holders = 1;
+ pthread_cond_init(&ct->active, NULL);
+ pthread_mutex_init(&ct->lock, NULL);
++ pthread_spin_init(&ct->hldr_lock, PTHREAD_PROCESS_PRIVATE);
+ c->context = ct;
+
return 0;
}
++void cleanup_context(struct tur_checker_context *ct)
++{
++ pthread_mutex_destroy(&ct->lock);
++ pthread_cond_destroy(&ct->active);
++ pthread_spin_destroy(&ct->hldr_lock);
++ free(ct);
++}
++
void libcheck_free (struct checker * c)
{
+ if (c->context) {
+ struct tur_checker_context *ct = c->context;
-+
-+ pthread_mutex_destroy(&ct->lock);
-+ pthread_cond_destroy(&ct->active);
-+ free(c->context);
++ int holders;
++ pthread_t thread;
++
++ pthread_spin_lock(&ct->hldr_lock);
++ ct->holders--;
++ holders = ct->holders;
++ thread = ct->thread;
++ pthread_spin_unlock(&ct->hldr_lock);
++ if (holders)
++ pthread_cancel(thread);
++ else
++ cleanup_context(ct);
+ c->context = NULL;
+ }
return;
@@ -3733,20 +4879,24 @@ index 47107a2..224cf76 100644
-extern int
-libcheck_check (struct checker * c)
++#define TUR_MSG(msg, fmt, args...) snprintf(msg, CHECKER_MSG_LEN, fmt, ##args);
++
+int
-+tur_check (struct checker * c)
++tur_check(int fd, unsigned int timeout, char *msg)
{
struct sg_io_hdr io_hdr;
unsigned char turCmdBlk[TUR_CMD_LEN] = { 0x00, 0, 0, 0, 0, 0 };
-@@ -55,12 +90,20 @@ libcheck_check (struct checker * c)
+@@ -55,12 +116,20 @@ libcheck_check (struct checker * c)
io_hdr.dxfer_direction = SG_DXFER_NONE;
io_hdr.cmdp = turCmdBlk;
io_hdr.sbp = sense_buffer;
- io_hdr.timeout = DEF_TIMEOUT;
-+ io_hdr.timeout = c->timeout;
++ io_hdr.timeout = timeout;
io_hdr.pack_id = 0;
- if (ioctl(c->fd, SG_IO, &io_hdr) < 0) {
- MSG(c, MSG_TUR_DOWN);
+- if (ioctl(c->fd, SG_IO, &io_hdr) < 0) {
+- MSG(c, MSG_TUR_DOWN);
++ if (ioctl(fd, SG_IO, &io_hdr) < 0) {
++ TUR_MSG(msg, MSG_TUR_DOWN);
return PATH_DOWN;
}
+ if ((io_hdr.status & 0x7e) == 0x18) {
@@ -3754,14 +4904,27 @@ index 47107a2..224cf76 100644
+ * SCSI-3 arrays might return
+ * reservation conflict on TUR
+ */
-+ MSG(c, MSG_TUR_UP);
++ TUR_MSG(msg, MSG_TUR_UP);
+ return PATH_UP;
+ }
if (io_hdr.info & SG_INFO_OK_MASK) {
int key = 0, asc, ascq;
-@@ -113,3 +156,161 @@ libcheck_check (struct checker * c)
- MSG(c, MSG_TUR_UP);
+@@ -103,13 +172,188 @@ libcheck_check (struct checker * c)
+ * LOGICAL UNIT NOT ACCESSIBLE,
+ * TARGET PORT IN STANDBY STATE
+ */
+- MSG(c, MSG_TUR_GHOST);
++ TUR_MSG(msg, MSG_TUR_GHOST);
+ return PATH_GHOST;
+ }
+ }
+- MSG(c, MSG_TUR_DOWN);
++ TUR_MSG(msg, MSG_TUR_DOWN);
+ return PATH_DOWN;
+ }
+- MSG(c, MSG_TUR_UP);
++ TUR_MSG(msg, MSG_TUR_UP);
return PATH_UP;
}
+
@@ -3770,18 +4933,25 @@ index 47107a2..224cf76 100644
+
+void cleanup_func(void *data)
+{
++ int holders;
+ struct tur_checker_context *ct = data;
++ pthread_spin_lock(&ct->hldr_lock);
++ ct->holders--;
++ holders = ct->holders;
+ ct->thread = 0;
++ pthread_spin_unlock(&ct->hldr_lock);
++ if (!holders)
++ cleanup_context(ct);
+}
+
+void *tur_thread(void *ctx)
+{
-+ struct checker *c = ctx;
-+ struct tur_checker_context *ct = c->context;
++ struct tur_checker_context *ct = ctx;
+ int state;
+
+ condlog(3, "%d:%d: tur checker starting up", TUR_DEVT(ct));
+
++ ct->message[0] = '\0';
+ /* This thread can be canceled, so setup clean up */
+ tur_thread_cleanup_push(ct)
+
@@ -3790,7 +4960,7 @@ index 47107a2..224cf76 100644
+ ct->state = PATH_PENDING;
+ pthread_mutex_unlock(&ct->lock);
+
-+ state = tur_check(c);
++ state = tur_check(ct->fd, ct->timeout, ct->message);
+
+ /* TUR checker done */
+ pthread_mutex_lock(&ct->lock);
@@ -3821,7 +4991,7 @@ index 47107a2..224cf76 100644
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
-+ ct->timeout = now.tv_sec + c->timeout;
++ ct->time = now.tv_sec + c->timeout;
+}
+
+int tur_check_async_timeout(struct checker *c)
@@ -3830,7 +5000,7 @@ index 47107a2..224cf76 100644
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
-+ return (now.tv_sec > ct->timeout);
++ return (now.tv_sec > ct->time);
+}
+
+extern int
@@ -3850,7 +5020,7 @@ index 47107a2..224cf76 100644
+ ct->devt = sb.st_rdev;
+
+ if (c->sync)
-+ return tur_check(c);
++ return tur_check(c->fd, c->timeout, c->message);
+
+ /*
+ * Async mode
@@ -3884,6 +5054,8 @@ index 47107a2..224cf76 100644
+ /* TUR checker done */
+ ct->running = 0;
+ tur_status = ct->state;
++ strncpy(c->message, ct->message, CHECKER_MSG_LEN);
++ c->message[CHECKER_MSG_LEN - 1] = '\0';
+ }
+ pthread_mutex_unlock(&ct->lock);
+ } else {
@@ -3892,24 +5064,32 @@ index 47107a2..224cf76 100644
+ pthread_mutex_unlock(&ct->lock);
+ condlog(3, "%d:%d: tur thread not responding, "
+ "using sync mode", TUR_DEVT(ct));
-+ return tur_check(c);
++ return tur_check(c->fd, c->timeout, c->message);
+ }
+ /* Start new TUR checker */
+ ct->state = PATH_UNCHECKED;
++ ct->fd = c->fd;
++ ct->timeout = c->timeout;
++ pthread_spin_lock(&ct->hldr_lock);
++ ct->holders++;
++ pthread_spin_unlock(&ct->hldr_lock);
+ tur_set_async_timeout(c);
+ setup_thread_attr(&attr, 32 * 1024, 1);
-+ r = pthread_create(&ct->thread, &attr, tur_thread, c);
++ r = pthread_create(&ct->thread, &attr, tur_thread, ct);
+ if (r) {
+ 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);
++ return tur_check(c->fd, c->timeout, c->message);
+ }
+ pthread_attr_destroy(&attr);
+ tur_timeout(&tsp);
+ r = pthread_cond_timedwait(&ct->active, &ct->lock, &tsp);
+ tur_status = ct->state;
++ strncpy(c->message, ct->message,CHECKER_MSG_LEN);
++ c->message[CHECKER_MSG_LEN -1] = '\0';
+ pthread_mutex_unlock(&ct->lock);
+ if (ct->thread &&
+ (tur_status == PATH_PENDING || tur_status == PATH_UNCHECKED)) {
@@ -3923,10 +5103,18 @@ index 47107a2..224cf76 100644
+ return tur_status;
+}
diff --git a/libmultipath/config.c b/libmultipath/config.c
-index a4178be..f99465a 100644
+index a4178be..da676df 100644
--- a/libmultipath/config.c
+++ b/libmultipath/config.c
-@@ -19,6 +19,7 @@
+@@ -5,6 +5,7 @@
+ */
+ #include <stdio.h>
+ #include <string.h>
++#include <libudev.h>
+
+ #include "checkers.h"
+ #include "memory.h"
+@@ -19,17 +20,24 @@
#include "blacklist.h"
#include "defaults.h"
#include "prio.h"
@@ -3934,7 +5122,27 @@ index a4178be..f99465a 100644
static int
hwe_strmatch (struct hwentry *hwe1, struct hwentry *hwe2)
-@@ -50,42 +51,64 @@ find_hwe_strmatch (vector hwtable, struct hwentry *hwe)
+ {
+- if (hwe1->vendor && hwe2->vendor && strcmp(hwe1->vendor, hwe2->vendor))
++ if ((hwe2->vendor && !hwe1->vendor) ||
++ (hwe1->vendor && (!hwe2->vendor ||
++ strcmp(hwe1->vendor, hwe2->vendor))))
+ return 1;
+
+- if (hwe1->product && hwe2->product && strcmp(hwe1->product, hwe2->product))
++ if ((hwe2->product && !hwe1->product) ||
++ (hwe1->product && (!hwe2->product ||
++ strcmp(hwe1->product, hwe2->product))))
+ return 1;
+
+- if (hwe1->revision && hwe2->revision && strcmp(hwe1->revision, hwe2->revision))
++ if ((hwe2->revision && !hwe1->revision) ||
++ (hwe1->revision && (!hwe2->revision ||
++ strcmp(hwe1->revision, hwe2->revision))))
+ return 1;
+
+ return 0;
+@@ -50,42 +58,64 @@ find_hwe_strmatch (vector hwtable, struct hwentry *hwe)
return ret;
}
@@ -4030,7 +5238,18 @@ index a4178be..f99465a 100644
}
return ret;
}
-@@ -158,6 +181,9 @@ free_hwe (struct hwentry * hwe)
+@@ -137,8 +167,8 @@ free_hwe (struct hwentry * hwe)
+ if (hwe->revision)
+ FREE(hwe->revision);
+
+- if (hwe->getuid)
+- FREE(hwe->getuid);
++ if (hwe->uid_attribute)
++ FREE(hwe->uid_attribute);
+
+ if (hwe->features)
+ FREE(hwe->features);
+@@ -158,6 +188,9 @@ free_hwe (struct hwentry * hwe)
if (hwe->prio_args)
FREE(hwe->prio_args);
@@ -4040,7 +5259,15 @@ index a4178be..f99465a 100644
if (hwe->bl_product)
FREE(hwe->bl_product);
-@@ -197,6 +223,12 @@ free_mpe (struct mpentry * mpe)
+@@ -191,12 +224,18 @@ free_mpe (struct mpentry * mpe)
+ if (mpe->selector)
+ FREE(mpe->selector);
+
+- if (mpe->getuid)
+- FREE(mpe->getuid);
++ if (mpe->uid_attribute)
++ FREE(mpe->uid_attribute);
+
if (mpe->alias)
FREE(mpe->alias);
@@ -4053,7 +5280,7 @@ index a4178be..f99465a 100644
FREE(mpe);
}
-@@ -257,20 +289,18 @@ set_param_str(char * str)
+@@ -257,37 +296,53 @@ set_param_str(char * str)
}
#define merge_str(s) \
@@ -4079,7 +5306,12 @@ index a4178be..f99465a 100644
{
merge_str(vendor);
merge_str(product);
-@@ -282,12 +312,18 @@ merge_hwe (struct hwentry * hwe1, struct hwentry * hwe2)
+ merge_str(revision);
+- merge_str(getuid);
++ merge_str(uid_attribute);
+ merge_str(features);
+ merge_str(hwhandler);
+ merge_str(selector);
merge_str(checker_name);
merge_str(prio_name);
merge_str(prio_args);
@@ -4095,10 +5327,31 @@ index a4178be..f99465a 100644
+ merge_num(flush_on_last_del);
+ merge_num(fast_io_fail);
+ merge_num(dev_loss);
++ merge_num(user_friendly_names);
++ merge_num(retain_hwhandler);
++ merge_num(detect_prio);
++
++ /*
++ * Make sure features is consistent with
++ * no_path_retry
++ */
++ if (dst->no_path_retry == NO_PATH_RETRY_FAIL)
++ remove_feature(&dst->features, "queue_if_no_path");
++ else if (dst->no_path_retry != NO_PATH_RETRY_UNDEF)
++ add_feature(&dst->features, "queue_if_no_path");
return 0;
}
-@@ -333,11 +369,15 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
+@@ -312,7 +367,7 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
+ if (dhwe->revision && !(hwe->revision = set_param_str(dhwe->revision)))
+ goto out;
+
+- if (dhwe->getuid && !(hwe->getuid = set_param_str(dhwe->getuid)))
++ if (dhwe->uid_attribute && !(hwe->uid_attribute = set_param_str(dhwe->uid_attribute)))
+ goto out;
+
+ if (dhwe->features && !(hwe->features = set_param_str(dhwe->features)))
+@@ -333,11 +388,22 @@ store_hwe (vector hwtable, struct hwentry * dhwe)
if (dhwe->prio_args && !(hwe->prio_args = set_param_str(dhwe->prio_args)))
goto out;
@@ -4111,19 +5364,29 @@ index a4178be..f99465a 100644
hwe->no_path_retry = dhwe->no_path_retry;
hwe->minio = dhwe->minio;
+ hwe->minio_rq = dhwe->minio_rq;
++ hwe->pg_timeout = dhwe->pg_timeout;
++ hwe->flush_on_last_del = dhwe->flush_on_last_del;
++ hwe->fast_io_fail = dhwe->fast_io_fail;
++ hwe->dev_loss = dhwe->dev_loss;
++ hwe->user_friendly_names = dhwe->user_friendly_names;
++ hwe->retain_hwhandler = dhwe->retain_hwhandler;
++ hwe->detect_prio = dhwe->detect_prio;
if (dhwe->bl_product && !(hwe->bl_product = set_param_str(dhwe->bl_product)))
goto out;
-@@ -353,21 +393,20 @@ out:
+@@ -352,25 +418,37 @@ out:
+ return 1;
}
- static int
+-static int
-factorize_hwtable (vector hw)
++static void
+factorize_hwtable (vector hw, int n)
{
struct hwentry *hwe1, *hwe2;
int i, j;
++restart:
vector_foreach_slot(hw, hwe1, i) {
- j = i+1;
+ if (i == n)
@@ -4139,16 +5402,56 @@ index a4178be..f99465a 100644
- vector_del_slot(hw, j);
- j--;
+ merge_hwe(hwe2, hwe1);
++ if (hwe_strmatch(hwe2, hwe1) == 0) {
++ vector_del_slot(hw, i);
++ free_hwe(hwe1);
++ n -= 1;
++ /*
++ * Play safe here; we have modified
++ * the original vector so the outer
++ * vector_foreach_slot() might
++ * become confused.
++ */
++ goto restart;
++ }
}
}
- return 0;
-@@ -406,14 +445,22 @@ free_config (struct config * conf)
+- return 0;
++ return;
+ }
+
+ struct config *
+@@ -388,8 +466,8 @@ free_config (struct config * conf)
+ if (conf->dev)
+ FREE(conf->dev);
+
+- if (conf->udev_dir)
+- FREE(conf->udev_dir);
++ if (conf->udev)
++ udev_unref(conf->udev);
+
+ if (conf->multipath_dir)
+ FREE(conf->multipath_dir);
+@@ -397,8 +475,8 @@ free_config (struct config * conf)
+ if (conf->selector)
+ FREE(conf->selector);
+
+- if (conf->getuid)
+- FREE(conf->getuid);
++ if (conf->uid_attribute)
++ FREE(conf->uid_attribute);
+
+ if (conf->features)
+ FREE(conf->features);
+@@ -406,14 +484,24 @@ free_config (struct config * conf)
if (conf->hwhandler)
FREE(conf->hwhandler);
+ if (conf->bindings_file)
+ FREE(conf->bindings_file);
+
++ if (conf->wwids_file)
++ FREE(conf->wwids_file);
if (conf->prio_name)
FREE(conf->prio_name);
@@ -4165,11 +5468,12 @@ index a4178be..f99465a 100644
free_blacklist(conf->blist_devnode);
free_blacklist(conf->blist_wwid);
-@@ -444,13 +491,20 @@ load_config (char * file)
+@@ -444,13 +532,25 @@ load_config (char * file)
if (!conf->verbosity)
conf->verbosity = DEFAULT_VERBOSITY;
-+ conf->dmrq = dm_drv_get_rq();
++ conf->udev = udev_new();
++ dm_drv_version(conf->version, TGT_MPATH);
conf->dev_type = DEV_NONE;
- conf->minio = 1000;
- conf->max_fds = 0;
@@ -4178,6 +5482,7 @@ index a4178be..f99465a 100644
+ conf->minio_rq = DEFAULT_MINIO_RQ;
+ get_sys_max_fds(&conf->max_fds);
+ conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
++ conf->wwids_file = set_default(DEFAULT_WWIDS_FILE);
+ conf->bindings_read_only = 0;
conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
+ conf->features = set_default(DEFAULT_FEATURES);
@@ -4186,10 +5491,13 @@ index a4178be..f99465a 100644
+ conf->reassign_maps = DEFAULT_REASSIGN_MAPS;
+ conf->checkint = DEFAULT_CHECKINT;
+ conf->max_checkint = MAX_CHECKINT(conf->checkint);
++ conf->fast_io_fail = DEFAULT_FAST_IO_FAIL;
++ conf->retain_hwhandler = DEFAULT_RETAIN_HWHANDLER;
++ conf->detect_prio = DEFAULT_DETECT_PRIO;
/*
* preload default hwtable
-@@ -467,19 +521,27 @@ load_config (char * file)
+@@ -467,19 +567,27 @@ load_config (char * file)
/*
* read the config file
*/
@@ -4224,24 +5532,26 @@ index a4178be..f99465a 100644
/*
* fill the voids left in the config file
-@@ -533,7 +595,11 @@ load_config (char * file)
- if (conf->udev_dir == NULL)
- conf->udev_dir = set_default(DEFAULT_UDEVDIR);
-
-- if (!conf->udev_dir || !conf->multipath_dir)
+@@ -530,10 +638,11 @@ load_config (char * file)
+ if (!conf->mptable)
+ goto out;
+ }
+- if (conf->udev_dir == NULL)
+- conf->udev_dir = set_default(DEFAULT_UDEVDIR);
+ if (conf->bindings_file == NULL)
+ conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
-+
-+ if (!conf->udev_dir || !conf->multipath_dir ||
-+ !conf->bindings_file)
+
+- if (!conf->udev_dir || !conf->multipath_dir)
++ if (!conf->multipath_dir || !conf->bindings_file ||
++ !conf->wwids_file)
goto out;
return 0;
diff --git a/libmultipath/config.h b/libmultipath/config.h
-index 471eed0..6fcd45e 100644
+index 471eed0..4ade355 100644
--- a/libmultipath/config.h
+++ b/libmultipath/config.h
-@@ -7,6 +7,13 @@
+@@ -7,6 +7,14 @@
#define ORIGIN_DEFAULT 0
#define ORIGIN_CONFIG 1
@@ -4249,13 +5559,22 @@ index 471eed0..6fcd45e 100644
+ * In kernel, fast_io_fail == 0 means immediate failure on rport delete.
+ * OTOH '0' means not-configured in various places in multipath-tools.
+ */
++#define MP_FAST_IO_FAIL_UNSET (0)
+#define MP_FAST_IO_FAIL_OFF (-1)
+#define MP_FAST_IO_FAIL_ZERO (-2)
+
enum devtypes {
DEV_NONE,
DEV_DEVT,
-@@ -25,12 +32,14 @@ struct hwentry {
+@@ -18,40 +26,51 @@ struct hwentry {
+ char * vendor;
+ char * product;
+ char * revision;
+- char * getuid;
++ char * uid_attribute;
+ char * features;
+ char * hwhandler;
+ char * selector;
char * checker_name;
char * prio_name;
char * prio_args;
@@ -4270,9 +5589,18 @@ index 471eed0..6fcd45e 100644
int pg_timeout;
int flush_on_last_del;
int fast_io_fail;
-@@ -43,12 +52,17 @@ struct mpentry {
+ unsigned int dev_loss;
++ int user_friendly_names;
++ int retain_hwhandler;
++ int detect_prio;
+ char * bl_product;
+ };
+
+ struct mpentry {
+ char * wwid;
char * alias;
- char * getuid;
+- char * getuid;
++ char * uid_attribute;
char * selector;
+ char * features;
@@ -4288,15 +5616,15 @@ index 471eed0..6fcd45e 100644
int pg_timeout;
int flush_on_last_del;
int attribute_flags;
-@@ -58,6 +72,7 @@ struct mpentry {
- };
-
- struct config {
-+ int dmrq;
- int verbosity;
++ int user_friendly_names;
+ uid_t uid;
+ gid_t gid;
+ mode_t mode;
+@@ -62,10 +81,10 @@ struct config {
int dry_run;
int list;
-@@ -66,6 +81,7 @@ struct config {
+ int pgpolicy_flag;
+- int with_sysfs;
int pgpolicy;
enum devtypes dev_type;
int minio;
@@ -4304,7 +5632,7 @@ index 471eed0..6fcd45e 100644
int checkint;
int max_checkint;
int pgfailback;
-@@ -73,19 +89,24 @@ struct config {
+@@ -73,32 +92,42 @@ struct config {
int rr_weight;
int no_path_retry;
int user_friendly_names;
@@ -4326,10 +5654,22 @@ index 471eed0..6fcd45e 100644
mode_t mode;
uint32_t cookie;
+ int reassign_maps;
++ int retain_hwhandler;
++ int detect_prio;
++ unsigned int version[3];
char * dev;
- char * sysfs_dir;
-@@ -99,6 +120,8 @@ struct config {
+- char * sysfs_dir;
+- char * udev_dir;
++ struct udev * udev;
+ char * multipath_dir;
+ char * selector;
+- char * getuid;
++ char * uid_attribute;
+ char * features;
+ char * hwhandler;
+ char * bindings_file;
++ char * wwids_file;
char * prio_name;
char * prio_args;
char * checker_name;
@@ -4339,14 +5679,23 @@ index 471eed0..6fcd45e 100644
vector keywords;
vector mptable;
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
-index c6ca4b6..001c1f0 100644
+index c6ca4b6..e5048eb 100644
--- a/libmultipath/configure.c
+++ b/libmultipath/configure.c
-@@ -35,13 +35,14 @@
+@@ -13,6 +13,7 @@
+ #include <sys/file.h>
+ #include <errno.h>
+ #include <libdevmapper.h>
++#include <libudev.h>
+
+ #include "checkers.h"
+ #include "vector.h"
+@@ -35,13 +36,15 @@
#include "alias.h"
#include "prio.h"
#include "util.h"
+#include "uxsock.h"
++#include "wwids.h"
extern int
-setup_map (struct multipath * mpp)
@@ -4359,15 +5708,16 @@ index c6ca4b6..001c1f0 100644
/*
* don't bother if devmap size is unknown
*/
-@@ -72,6 +73,7 @@ setup_map (struct multipath * mpp)
+@@ -72,6 +75,8 @@ setup_map (struct multipath * mpp)
select_gid(mpp);
select_fast_io_fail(mpp);
select_dev_loss(mpp);
+ select_reservation_key(mpp);
++ select_retain_hwhandler(mpp);
sysfs_set_scsi_tmo(mpp);
/*
-@@ -88,7 +90,7 @@ setup_map (struct multipath * mpp)
+@@ -88,7 +93,7 @@ setup_map (struct multipath * mpp)
if (mpp->pgpolicyfn && mpp->pgpolicyfn(mpp))
return 1;
@@ -4376,7 +5726,7 @@ index c6ca4b6..001c1f0 100644
/*
* ponders each path group and determine highest prio pg
-@@ -100,7 +102,7 @@ setup_map (struct multipath * mpp)
+@@ -100,7 +105,7 @@ setup_map (struct multipath * mpp)
* transform the mp->pg vector of vectors of paths
* into a mp->params strings to feed the device-mapper
*/
@@ -4385,7 +5735,7 @@ index c6ca4b6..001c1f0 100644
condlog(0, "%s: problem assembing map", mpp->alias);
return 1;
}
-@@ -132,7 +134,8 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp)
+@@ -132,7 +137,8 @@ pgcmp (struct multipath * mpp, struct multipath * cmpp)
compute_pgid(pgp);
vector_foreach_slot (cmpp->pg, cpgp, j) {
@@ -4395,16 +5745,54 @@ index c6ca4b6..001c1f0 100644
r = 0;
break;
}
-@@ -170,7 +173,7 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
- if (!find_mp_by_wwid(curmp, mpp->wwid)) {
- condlog(2, "%s: remove (wwid changed)", cmpp->alias);
+@@ -148,12 +154,12 @@ static void
+ select_action (struct multipath * mpp, vector curmp, int force_reload)
+ {
+ struct multipath * cmpp;
++ struct multipath * cmpp_by_name;
+
+- cmpp = find_mp_by_alias(curmp, mpp->alias);
+-
+- if (!cmpp) {
+- cmpp = find_mp_by_wwid(curmp, mpp->wwid);
++ cmpp = find_mp_by_wwid(curmp, mpp->wwid);
++ cmpp_by_name = find_mp_by_alias(curmp, mpp->alias);
+
++ if (!cmpp_by_name) {
+ if (cmpp) {
+ condlog(2, "%s: rename %s to %s", mpp->wwid,
+ cmpp->alias, mpp->alias);
+@@ -167,17 +173,25 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
+ return;
+ }
+
+- if (!find_mp_by_wwid(curmp, mpp->wwid)) {
+- condlog(2, "%s: remove (wwid changed)", cmpp->alias);
++ if (!cmpp) {
++ condlog(2, "%s: remove (wwid changed)", mpp->alias);
dm_flush_map(mpp->alias);
- strncat(cmpp->wwid, mpp->wwid, WWID_SIZE);
-+ strncpy(cmpp->wwid, mpp->wwid, WWID_SIZE);
- drop_multipath(curmp, cmpp->wwid, KEEP_PATHS);
+- drop_multipath(curmp, cmpp->wwid, KEEP_PATHS);
++ strncpy(cmpp_by_name->wwid, mpp->wwid, WWID_SIZE);
++ drop_multipath(curmp, cmpp_by_name->wwid, KEEP_PATHS);
mpp->action = ACT_CREATE;
condlog(3, "%s: set ACT_CREATE (map wwid change)",
-@@ -191,8 +194,8 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
+ mpp->alias);
+ return;
+ }
+
++ if (cmpp != cmpp_by_name) {
++ condlog(2, "%s: unable to rename %s to %s (%s is used by %s)",
++ mpp->wwid, cmpp->alias, mpp->alias,
++ mpp->alias, cmpp_by_name->wwid);
++ mpp->action = ACT_NOTHING;
++ return;
++ }
++
+ if (pathcount(mpp, PATH_UP) == 0) {
+ mpp->action = ACT_NOTHING;
+ condlog(3, "%s: set ACT_NOTHING (no usable path)",
+@@ -191,8 +205,8 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
return;
}
if (cmpp->size != mpp->size) {
@@ -4415,7 +5803,20 @@ index c6ca4b6..001c1f0 100644
mpp->alias);
return;
}
-@@ -284,6 +287,7 @@ lock_multipath (struct multipath * mpp, int lock)
+@@ -204,8 +218,10 @@ select_action (struct multipath * mpp, vector curmp, int force_reload)
+ mpp->alias);
+ return;
+ }
+- if (!cmpp->selector || strncmp(cmpp->hwhandler, mpp->hwhandler,
+- strlen(mpp->hwhandler))) {
++ if (mpp->retain_hwhandler != RETAIN_HWHANDLER_ON &&
++ (strlen(cmpp->hwhandler) != strlen(mpp->hwhandler) ||
++ strncmp(cmpp->hwhandler, mpp->hwhandler,
++ strlen(mpp->hwhandler)))) {
+ mpp->action = ACT_RELOAD;
+ condlog(3, "%s: set ACT_RELOAD (hwhandler change)",
+ mpp->alias);
+@@ -284,6 +300,7 @@ lock_multipath (struct multipath * mpp, int lock)
struct pathgroup * pgp;
struct path * pp;
int i, j;
@@ -4423,7 +5824,7 @@ index c6ca4b6..001c1f0 100644
if (!mpp || !mpp->pg)
return 0;
-@@ -294,12 +298,25 @@ lock_multipath (struct multipath * mpp, int lock)
+@@ -294,12 +311,25 @@ lock_multipath (struct multipath * mpp, int lock)
vector_foreach_slot(pgp->paths, pp, j) {
if (lock && flock(pp->fd, LOCK_EX | LOCK_NB) &&
errno == EWOULDBLOCK)
@@ -4450,7 +5851,7 @@ index c6ca4b6..001c1f0 100644
}
/*
-@@ -312,7 +329,7 @@ lock_multipath (struct multipath * mpp, int lock)
+@@ -312,7 +342,7 @@ lock_multipath (struct multipath * mpp, int lock)
#define DOMAP_DRY 3
extern int
@@ -4459,7 +5860,7 @@ index c6ca4b6..001c1f0 100644
{
int r = 0;
-@@ -352,28 +369,28 @@ domap (struct multipath * mpp)
+@@ -352,28 +382,28 @@ domap (struct multipath * mpp)
break;
}
@@ -4498,7 +5899,12 @@ index c6ca4b6..001c1f0 100644
break;
case ACT_RENAME:
-@@ -392,13 +409,11 @@ domap (struct multipath * mpp)
+@@ -389,16 +419,16 @@ domap (struct multipath * mpp)
+ * DM_DEVICE_CREATE, DM_DEVICE_RENAME, or DM_DEVICE_RELOAD
+ * succeeded
+ */
++ if (mpp->action == ACT_CREATE)
++ remember_wwid(mpp->wwid);
if (!conf->daemon) {
/* multipath client mode */
dm_switchgroup(mpp->alias, mpp->bestpg);
@@ -4513,7 +5919,7 @@ index c6ca4b6..001c1f0 100644
/*
* Required action is over, reset for the stateful daemon.
* But don't do it for creation as we use in the caller the
-@@ -407,6 +422,7 @@ domap (struct multipath * mpp)
+@@ -407,6 +437,7 @@ domap (struct multipath * mpp)
if (mpp->action != ACT_CREATE)
mpp->action = ACT_NOTHING;
}
@@ -4521,7 +5927,7 @@ index c6ca4b6..001c1f0 100644
return DOMAP_OK;
}
return DOMAP_FAIL;
-@@ -434,12 +450,41 @@ deadmap (struct multipath * mpp)
+@@ -434,12 +465,41 @@ deadmap (struct multipath * mpp)
return 1; /* dead */
}
@@ -4563,7 +5969,7 @@ index c6ca4b6..001c1f0 100644
struct multipath * mpp;
struct path * pp1;
struct path * pp2;
-@@ -458,16 +503,20 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
+@@ -458,16 +518,20 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
/* 1. if path has no unique id or wwid blacklisted */
if (memcmp(empty_buff, pp1->wwid, WWID_SIZE) == 0 ||
@@ -4586,7 +5992,7 @@ index c6ca4b6..001c1f0 100644
/* 4. path is out of scope */
if (refwwid && strncmp(pp1->wwid, refwwid, WWID_SIZE))
-@@ -511,8 +560,9 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
+@@ -511,8 +575,9 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
mpp->action = ACT_REJECT;
}
verify_paths(mpp, vecs, NULL);
@@ -4598,7 +6004,7 @@ index c6ca4b6..001c1f0 100644
remove_map(mpp, vecs, 0);
continue;
}
-@@ -520,13 +570,16 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
+@@ -520,13 +585,16 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
if (mpp->action == ACT_UNDEF)
select_action(mpp, curmp, force_reload);
@@ -4616,7 +6022,7 @@ index c6ca4b6..001c1f0 100644
remove_map(mpp, vecs, 0);
continue;
} else /* if (r == DOMAP_RETRY) */
-@@ -535,11 +588,29 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
+@@ -535,11 +603,29 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
if (r == DOMAP_DRY)
continue;
@@ -4651,7 +6057,7 @@ index c6ca4b6..001c1f0 100644
}
if (mpp->pg_timeout != PGTIMEOUT_UNDEF) {
if (mpp->pg_timeout == -PGTIMEOUT_NONE)
-@@ -548,6 +619,9 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
+@@ -548,6 +634,9 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
dm_set_pg_timeout(mpp->alias, mpp->pg_timeout);
}
@@ -4661,7 +6067,7 @@ index c6ca4b6..001c1f0 100644
if (newmp) {
if (mpp->action != ACT_REJECT) {
if (!vector_alloc_slot(newmp))
-@@ -577,11 +651,11 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
+@@ -577,44 +666,60 @@ coalesce_paths (struct vectors * vecs, vector newmp, char * refwwid, int force_r
remove_map(mpp, vecs, 0);
@@ -4676,23 +6082,73 @@ index c6ca4b6..001c1f0 100644
}
}
return 0;
-@@ -598,9 +672,13 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec)
- return NULL;
+ }
- if (dev_type == DEV_DEVNODE) {
-- basenamecpy(dev, buff);
-+ if (basenamecpy(dev, buff, FILE_NAME_SIZE) == 0) {
-+ condlog(1, "basename failed for '%s' (%s)",
-+ dev, buff);
-+ return NULL;
-+ }
+-extern char *
+-get_refwwid (char * dev, enum devtypes dev_type, vector pathvec)
++/*
++ * returns:
++ * 0 - success
++ * 1 - failure
++ * 2 - blacklist
++ */
++extern int
++get_refwwid (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];
+
++ if (!wwid)
++ return 1;
++ *wwid = NULL;
++
+ if (dev_type == DEV_NONE)
+- return NULL;
++ return 1;
+
+ if (dev_type == DEV_DEVNODE) {
+- basenamecpy(dev, buff);
++ if (basenamecpy(dev, buff, FILE_NAME_SIZE) == 0) {
++ condlog(1, "basename failed for '%s' (%s)",
++ dev, buff);
++ return 1;
++ }
+
pp = find_path_by_dev(pathvec, buff);
-
if (!pp) {
- pp = alloc_path();
+- pp = alloc_path();
++ struct udev_device *udevice = udev_device_new_from_subsystem_sysname(conf->udev, "block", buff);
-@@ -622,10 +700,10 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec)
+- if (!pp)
+- return NULL;
+-
+- strncpy(pp->dev, buff, FILE_NAME_SIZE);
+-
+- if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID))
+- return NULL;
+-
+- if (store_path(pathvec, pp)) {
+- free_path(pp);
+- return NULL;
++ 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);
++ udev_device_unref(udevice);
++ if (!pp) {
++ if (ret == 1)
++ condlog(0, "%s can't store path info",
++ buff);
++ return ret;
+ }
+ }
+ refwwid = pp->wwid;
+@@ -622,25 +727,23 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec)
}
if (dev_type == DEV_DEVT) {
@@ -4701,31 +6157,96 @@ index c6ca4b6..001c1f0 100644
-
if (!pp) {
- if (devt2devname(buff, dev))
-+ if (devt2devname(buff, FILE_NAME_SIZE, dev))
- return NULL;
+- return NULL;
++ struct udev_device *udevice = udev_device_new_from_devnum(conf->udev, 'b', parse_devt(dev));
- pp = alloc_path();
-@@ -637,7 +715,7 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec)
-
- if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID))
- return NULL;
+- pp = alloc_path();
+-
+- if (!pp)
+- return NULL;
+-
+- strncpy(pp->dev, buff, FILE_NAME_SIZE);
+-
+- if (pathinfo(pp, conf->hwtable, DI_SYSFS | DI_WWID))
+- return NULL;
-
-+
- if (store_path(pathvec, pp)) {
- free_path(pp);
- return NULL;
-@@ -680,3 +758,38 @@ out:
- return NULL;
+- if (store_path(pathvec, pp)) {
+- free_path(pp);
+- return NULL;
++ 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);
++ udev_device_unref(udevice);
++ if (!pp) {
++ if (ret == 1)
++ condlog(0, "%s can't store path info",
++ buff);
++ return ret;
+ }
+ }
+ refwwid = pp->wwid;
+@@ -650,17 +753,17 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec)
+
+ if (((dm_get_uuid(dev, tmpwwid)) == 0) && (strlen(tmpwwid))) {
+ refwwid = tmpwwid;
+- goto out;
++ goto check;
+ }
+
+ /*
+ * may be a binding
+ */
+- refwwid = get_user_friendly_wwid(dev,
+- conf->bindings_file);
+-
+- if (refwwid)
+- return refwwid;
++ if (get_user_friendly_wwid(dev, tmpwwid,
++ conf->bindings_file) == 0) {
++ refwwid = tmpwwid;
++ goto check;
++ }
+
+ /*
+ * or may be an alias
+@@ -672,11 +775,58 @@ get_refwwid (char * dev, enum devtypes dev_type, vector pathvec)
+ */
+ if (!refwwid)
+ refwwid = dev;
++
++check:
++ if (refwwid && strlen(refwwid)) {
++ if (filter_wwid(conf->blist_wwid, conf->elist_wwid,
++ refwwid) > 0)
++ return 2;
++ }
+ }
+ out:
+- if (refwwid && strlen(refwwid))
+- return STRDUP(refwwid);
++ if (refwwid && strlen(refwwid)) {
++ *wwid = STRDUP(refwwid);
++ return 0;
++ }
+
+- return NULL;
++ return 1;
}
-+extern int reload_map(struct vectors *vecs, struct multipath *mpp)
++extern int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh)
+{
-+ char params[PARAMS_SIZE];
-+ int r;
++ char params[PARAMS_SIZE] = {0};
++ struct path *pp;
++ int i, r;
+
+ update_mpp_paths(mpp, vecs->pathvec);
-+
-+ params[0] = '\0';
++ if (refresh) {
++ vector_foreach_slot (mpp->paths, pp, i)
++ pathinfo(pp, conf->hwtable, DI_PRIO);
++ }
+ if (setup_map(mpp, params, PARAMS_SIZE)) {
+ condlog(0, "%s: failed to setup map", mpp->alias);
+ return 1;
@@ -4754,7 +6275,7 @@ index c6ca4b6..001c1f0 100644
+ return 0;
+}
diff --git a/libmultipath/configure.h b/libmultipath/configure.h
-index 25891ba..6c1c493 100644
+index 25891ba..650f080 100644
--- a/libmultipath/configure.h
+++ b/libmultipath/configure.h
@@ -23,9 +23,10 @@ enum actions {
@@ -4767,19 +6288,21 @@ index 25891ba..6c1c493 100644
+int domap (struct multipath * mpp, char * params);
int reinstate_paths (struct multipath *mpp);
int coalesce_paths (struct vectors *vecs, vector curmp, char * refwwid, int force_reload);
- char * get_refwwid (char * dev, enum devtypes dev_type, vector pathvec);
-+int reload_map(struct vectors *vecs, struct multipath *mpp);
+-char * get_refwwid (char * dev, enum devtypes dev_type, vector pathvec);
++int get_refwwid (char * dev, enum devtypes dev_type, vector pathvec, char **wwid);
++int reload_map(struct vectors *vecs, struct multipath *mpp, int refresh);
diff --git a/libmultipath/defaults.h b/libmultipath/defaults.h
-index 5a38d25..294646a 100644
+index 5a38d25..b83d9fb 100644
--- a/libmultipath/defaults.h
+++ b/libmultipath/defaults.h
@@ -1,10 +1,12 @@
-#define DEFAULT_GETUID "/lib/udev/scsi_id --whitelisted --device=/dev/%n"
-+#define DEFAULT_GETUID "/lib/udev/scsi_id --whitelisted --replace-whitespace --device=/dev/%n"
++#define DEFAULT_UID_ATTRIBUTE "ID_SERIAL"
#define DEFAULT_UDEVDIR "/dev"
#define DEFAULT_MULTIPATHDIR "/" LIB_STRING "/multipath"
- #define DEFAULT_SELECTOR "round-robin 0"
+-#define DEFAULT_SELECTOR "round-robin 0"
++#define DEFAULT_SELECTOR "service-time 0"
+#define DEFAULT_ALIAS_PREFIX "mpath"
#define DEFAULT_FEATURES "0"
#define DEFAULT_HWHANDLER "0"
@@ -4788,21 +6311,29 @@ index 5a38d25..294646a 100644
#define DEFAULT_PGPOLICY FAILOVER
#define DEFAULT_FAILBACK -FAILBACK_MANUAL
#define DEFAULT_RR_WEIGHT RR_WEIGHT_NONE
-@@ -12,10 +14,12 @@
+@@ -12,13 +14,19 @@
#define DEFAULT_PGTIMEOUT -PGTIMEOUT_NONE
#define DEFAULT_USER_FRIENDLY_NAMES 0
#define DEFAULT_VERBOSITY 2
+#define DEFAULT_REASSIGN_MAPS 1
++#define DEFAULT_FAST_IO_FAIL 5
++#define DEFAULT_RETAIN_HWHANDLER RETAIN_HWHANDLER_OFF
++#define DEFAULT_DETECT_PRIO DETECT_PRIO_OFF
#define DEFAULT_CHECKINT 5
#define MAX_CHECKINT(a) (a << 2)
+#define MAX_DEV_LOSS_TMO 0x7FFFFFFF
#define DEFAULT_PIDFILE "/var/run/multipathd.pid"
- #define DEFAULT_SOCKET "/var/run/multipathd.sock"
+-#define DEFAULT_SOCKET "/var/run/multipathd.sock"
++#define DEFAULT_SOCKET "/org/kernel/linux/storage/multipathd"
#define DEFAULT_CONFIGFILE "/etc/multipath.conf"
+ #define DEFAULT_BINDINGS_FILE "/etc/multipath/bindings"
++#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
+
+ char * set_default (char * str);
diff --git a/libmultipath/devmapper.c b/libmultipath/devmapper.c
-index 333659b..de7d446 100644
+index 333659b..67481c4 100644
--- a/libmultipath/devmapper.c
+++ b/libmultipath/devmapper.c
@@ -20,6 +20,7 @@
@@ -4845,16 +6376,9 @@ index 333659b..de7d446 100644
static void
dm_write_log (int level, const char *file, int line, const char *f, ...)
{
-@@ -72,20 +98,28 @@ dm_init(void) {
- dm_log_init_verbose(conf ? conf->verbosity + 3 : 0);
+@@ -73,37 +99,42 @@ dm_init(void) {
}
-+#define VERSION_GE(v, minv) ( \
-+ (v[0] > minv[0]) || \
-+ ((v[0] == minv[0]) && (v[1] > minv[1])) || \
-+ ((v[0] == minv[0]) && (v[1] == minv[1]) && (v[2] >= minv[2])) \
-+)
-+
static int
-dm_libprereq (void)
+dm_lib_prereq (void)
@@ -4878,11 +6402,12 @@ index 333659b..de7d446 100644
return 0;
condlog(0, "libdevmapper version must be >= %d.%.2d.%.2d",
minv[0], minv[1], minv[2]);
-@@ -93,17 +127,16 @@ dm_libprereq (void)
+ return 1;
}
- static int
+-static int
-dm_drvprereq (char * str)
++int
+dm_drv_version (unsigned int * version, char * str)
{
int r = 2;
@@ -4892,13 +6417,17 @@ index 333659b..de7d446 100644
- int minv[3] = {1, 0, 3};
unsigned int *v;
++ version[0] = 0;
++ version[1] = 0;
++ version[2] = 0;
++
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
- return 3;
+ return 1;
dm_task_no_open_count(dmt);
-@@ -123,29 +156,71 @@ dm_drvprereq (char * str)
+@@ -123,29 +154,49 @@ dm_drvprereq (char * str)
} while (last_target != target);
if (r == 2) {
@@ -4924,28 +6453,6 @@ index 333659b..de7d446 100644
return r;
}
-+int
-+dm_drv_get_rq (void)
-+{
-+ unsigned int minv_dmrq[3] = {1, 1, 0};
-+ unsigned int version[3] = {0, 0, 0};
-+ unsigned int * v = version;
-+
-+ if (dm_drv_version(v, TGT_MPATH)) {
-+ /* in doubt return least capable */
-+ return 0;
-+ }
-+
-+ /* test request based multipath capability */
-+ if VERSION_GE(v, minv_dmrq) {
-+ condlog(3, "activate request-based multipathing mode "
-+ "(driver >= v%u.%u.%u)",
-+ minv_dmrq[0], minv_dmrq[1], minv_dmrq[2]);
-+ return 1;
-+ }
-+ return 0;
-+}
-+
+static int
+dm_drv_prereq (void)
+{
@@ -4981,7 +6488,16 @@ index 333659b..de7d446 100644
}
static int
-@@ -188,8 +263,8 @@ dm_simplecmd_noflush (int task, const char *name) {
+@@ -168,7 +219,7 @@ dm_simplecmd (int task, const char *name, int no_flush, int need_sync) {
+ dm_task_no_flush(dmt); /* for DM_DEVICE_SUSPEND/RESUME */
+ #endif
+
+- if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, 0))
++ if (udev_wait_flag && !dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
+ goto out;
+ r = dm_task_run (dmt);
+
+@@ -188,8 +239,8 @@ dm_simplecmd_noflush (int task, const char *name) {
}
extern int
@@ -4992,7 +6508,7 @@ index 333659b..de7d446 100644
int r = 0;
struct dm_task *dmt;
char *prefixed_uuid = NULL;
-@@ -200,7 +275,7 @@ dm_addmap (int task, const char *target, struct multipath *mpp, int use_uuid,
+@@ -200,16 +251,16 @@ dm_addmap (int task, const char *target, struct multipath *mpp, int use_uuid,
if (!dm_task_set_name (dmt, mpp->alias))
goto addout;
@@ -5001,16 +6517,33 @@ index 333659b..de7d446 100644
goto addout;
if (ro)
-@@ -227,6 +302,8 @@ dm_addmap (int task, const char *target, struct multipath *mpp, int use_uuid,
+ dm_task_set_ro(dmt);
+
+- if (use_uuid && mpp->wwid){
++ if (use_uuid && strlen(mpp->wwid) > 0){
+ prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(mpp->wwid) + 1);
+ if (!prefixed_uuid) {
+- condlog(0, "cannot create prefixed uuid : %s\n",
++ condlog(0, "cannot create prefixed uuid : %s",
+ strerror(errno));
+ goto addout;
+ }
+@@ -227,11 +278,13 @@ dm_addmap (int task, const char *target, struct multipath *mpp, int use_uuid,
if (mpp->attribute_flags & (1 << ATTR_GID) &&
!dm_task_set_gid(dmt, mpp->gid))
goto freeout;
-+ condlog(4, "%s: addmap [0 %llu %s %s]\n", mpp->alias, mpp->size,
++ condlog(4, "%s: addmap [0 %llu %s %s]", mpp->alias, mpp->size,
+ target, params);
dm_task_no_open_count(dmt);
-@@ -246,9 +323,9 @@ dm_addmap (int task, const char *target, struct multipath *mpp, int use_uuid,
+ if (task == DM_DEVICE_CREATE &&
+- !dm_task_set_cookie(dmt, &conf->cookie, 0))
++ !dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
+ goto freeout;
+ r = dm_task_run (dmt);
+
+@@ -246,9 +299,9 @@ dm_addmap (int task, const char *target, struct multipath *mpp, int use_uuid,
}
static int
@@ -5022,7 +6555,7 @@ index 333659b..de7d446 100644
/*
* DM_DEVICE_CREATE is actually DM_DEV_CREATE + DM_TABLE_LOAD.
* Failing the second part leaves an empty map. Clean it up.
-@@ -265,23 +342,23 @@ _dm_addmap_create (struct multipath *mpp, int ro) {
+@@ -265,23 +318,23 @@ _dm_addmap_create (struct multipath *mpp, int ro) {
#define ADDMAP_RO 1
extern int
@@ -5054,7 +6587,7 @@ index 333659b..de7d446 100644
}
extern int
-@@ -340,6 +417,10 @@ dm_get_map(char * name, unsigned long long * size, char * outparams)
+@@ -340,6 +393,10 @@ dm_get_map(char * name, unsigned long long * size, char * outparams)
if (size)
*size = length;
@@ -5065,7 +6598,7 @@ index 333659b..de7d446 100644
if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
r = 0;
out:
-@@ -347,8 +428,8 @@ out:
+@@ -347,8 +404,8 @@ out:
return r;
}
@@ -5076,7 +6609,7 @@ index 333659b..de7d446 100644
{
struct dm_task *dmt;
const char *uuidtmp;
-@@ -365,12 +446,8 @@ dm_get_uuid(char *name, char *uuid)
+@@ -365,12 +422,8 @@ dm_get_uuid(char *name, char *uuid)
goto uuidout;
uuidtmp = dm_task_get_uuid(dmt);
@@ -5091,7 +6624,7 @@ index 333659b..de7d446 100644
else
uuid[0] = '\0';
-@@ -381,6 +458,47 @@ uuidout:
+@@ -381,6 +434,47 @@ uuidout:
}
extern int
@@ -5139,7 +6672,7 @@ index 333659b..de7d446 100644
dm_get_status(char * name, char * outstatus)
{
int r = 1;
-@@ -511,6 +629,31 @@ out:
+@@ -511,6 +605,31 @@ out:
}
int
@@ -5171,6 +6704,46 @@ index 333659b..de7d446 100644
dm_get_minor (char * mapname)
{
int r = -1;
+@@ -564,6 +683,30 @@ _dm_flush_map (const char * mapname, int need_sync)
+ }
+
+ extern int
++dm_suspend_and_flush_map (const char * mapname)
++{
++ int s;
++
++ if (!dm_map_present(mapname))
++ return 0;
++
++ if (dm_type(mapname, TGT_MPATH) <= 0)
++ return 0; /* nothing to do */
++
++ s = dm_queue_if_no_path((char *)mapname, 0);
++ if (!s)
++ s = dm_simplecmd_flush(DM_DEVICE_SUSPEND, mapname, 0);
++
++ if (!dm_flush_map(mapname)) {
++ condlog(4, "multipath map %s removed", mapname);
++ return 0;
++ }
++ condlog(2, "failed to remove multipath map %s", mapname);
++ dm_simplecmd_noflush(DM_DEVICE_RESUME, mapname);
++ return 1;
++}
++
++extern int
+ dm_flush_maps (void)
+ {
+ int r = 0;
+@@ -586,7 +729,7 @@ dm_flush_maps (void)
+ goto out;
+
+ do {
+- r |= dm_flush_map(names->name);
++ r |= dm_suspend_and_flush_map(names->name);
+ next = names->next;
+ names = (void *) names + next;
+ } while (next);
@@ -633,7 +776,7 @@ dm_fail_path(char * mapname, char * path)
{
char message[32];
@@ -5251,7 +6824,7 @@ index 333659b..de7d446 100644
- goto out;
+ prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(uuid) + 1);
+ if (!prefixed_uuid) {
-+ condlog(0, "cannot create prefixed uuid : %s\n",
++ condlog(0, "cannot create prefixed uuid : %s",
+ strerror(errno));
+ goto freeout;
}
@@ -5338,14 +6911,14 @@ index 333659b..de7d446 100644
/*
- * and the multipath mapname and the part mapname start
- * the same
-+ * and both uuid end with same suffix starting
-+ * at UUID_PREFIX
- */
+- */
- !strncmp(names->name, mapname, strlen(mapname)) &&
-
- /*
- * and the opencount is 0 for us to allow removal
-- */
++ * and both uuid end with same suffix starting
++ * at UUID_PREFIX
+ */
- !dm_get_opencount(names->name) &&
+ (!dm_compare_uuid(names->name, mapname)) &&
@@ -5387,10 +6960,21 @@ index 333659b..de7d446 100644
next = names->next;
names = (void *) names + next;
-@@ -1119,3 +1278,176 @@ out:
- dm_task_destroy(dmt);
- return r;
- }
+@@ -1109,13 +1268,188 @@ dm_rename (char * old, char * new)
+
+ dm_task_no_open_count(dmt);
+
+- if (!dm_task_set_cookie(dmt, &conf->cookie, 0))
++ if (!dm_task_set_cookie(dmt, &conf->cookie, (conf->daemon)? DM_UDEV_DISABLE_LIBRARY_FALLBACK : 0))
++ goto out;
++ if (!dm_task_run(dmt))
++ goto out;
++
++ r = 1;
++out:
++ dm_task_destroy(dmt);
++ return r;
++}
+
+void dm_reassign_deps(char *table, char *dep, char *newdep)
+{
@@ -5479,21 +7063,23 @@ index 333659b..de7d446 100644
+ int r = 0, i;
+
+ if (dm_dev_t(mapname, &dev_t[0], 32)) {
-+ condlog(3, "%s: failed to get device number\n", mapname);
++ condlog(3, "%s: failed to get device number", mapname);
+ return 1;
+ }
+
-+ if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
++ if (!(dmt = dm_task_create(DM_DEVICE_DEPS))) {
++ condlog(3, "%s: couldn't make dm task", mapname);
+ return 0;
++ }
+
+ if (!dm_task_set_name(dmt, mapname))
-+ goto out;
+ goto out;
+
+ dm_task_no_open_count(dmt);
+
-+ if (!dm_task_run(dmt))
-+ goto out;
-+
+ if (!dm_task_run(dmt))
+ goto out;
+
+ if (!dm_task_get_info(dmt, &info))
+ goto out;
+
@@ -5512,8 +7098,8 @@ index 333659b..de7d446 100644
+
+ dm_task_destroy (dmt);
+
-+ r = 1;
-+out:
+ r = 1;
+ out:
+ return r;
+}
+
@@ -5560,19 +7146,19 @@ index 333659b..de7d446 100644
+
+ r = dm_task_run(dmt);
+out:
-+ dm_task_destroy(dmt);
+ dm_task_destroy(dmt);
+
-+ return r;
-+}
+ return r;
+ }
diff --git a/libmultipath/devmapper.h b/libmultipath/devmapper.h
-index f3ffeaa..0c2e03f 100644
+index f3ffeaa..bf8ee91 100644
--- a/libmultipath/devmapper.h
+++ b/libmultipath/devmapper.h
@@ -8,12 +8,13 @@
void dm_init(void);
int dm_prereq (void);
-+int dm_drv_get_rq (void);
++int dm_drv_version (unsigned int * version, char * str);
int dm_simplecmd_flush (int, const char *, int);
int dm_simplecmd_noflush (int, const char *);
-int dm_addmap_create (struct multipath *mpp);
@@ -5586,7 +7172,15 @@ index f3ffeaa..0c2e03f 100644
int dm_map_present (const char *);
int dm_get_map(char *, unsigned long long *, char *);
int dm_get_status(char *, char *);
-@@ -31,12 +32,18 @@ int dm_enablegroup(char * mapname, int index);
+@@ -21,6 +22,7 @@ int dm_type(const char *, char *);
+ int _dm_flush_map (const char *, int);
+ #define dm_flush_map(mapname) _dm_flush_map(mapname, 1)
+ #define dm_flush_map_nosync(mapname) _dm_flush_map(mapname, 0)
++int dm_suspend_and_flush_map(const char * mapname);
+ int dm_flush_maps (void);
+ int dm_fail_path(char * mapname, char * path);
+ int dm_reinstate_path(char * mapname, char * path);
+@@ -31,12 +33,24 @@ int dm_enablegroup(char * mapname, int index);
int dm_disablegroup(char * mapname, int index);
int dm_get_maps (vector mp);
int dm_geteventnr (char *name);
@@ -5604,10 +7198,16 @@ index f3ffeaa..0c2e03f 100644
+int dm_setgeometry(struct multipath *mpp);
+void udev_wait(unsigned int c);
+void udev_set_sync_support(int c);
++
++#define VERSION_GE(v, minv) ( \
++ (v[0] > minv[0]) || \
++ ((v[0] == minv[0]) && (v[1] > minv[1])) || \
++ ((v[0] == minv[0]) && (v[1] == minv[1]) && (v[2] >= minv[2])) \
++)
#endif /* _DEVMAPPER_H */
diff --git a/libmultipath/dict.c b/libmultipath/dict.c
-index 02aa238..4df3d9b 100644
+index 02aa238..14e7c57 100644
--- a/libmultipath/dict.c
+++ b/libmultipath/dict.c
@@ -6,7 +6,7 @@
@@ -5635,8 +7235,9 @@ index 02aa238..4df3d9b 100644
+ conf->fast_io_fail = MP_FAST_IO_FAIL_OFF;
else if (sscanf(buff, "%d", &conf->fast_io_fail) != 1 ||
- conf->fast_io_fail < -1)
+- conf->fast_io_fail = 0;
+ conf->fast_io_fail < MP_FAST_IO_FAIL_ZERO)
- conf->fast_io_fail = 0;
++ conf->fast_io_fail = MP_FAST_IO_FAIL_UNSET;
+ else if (conf->fast_io_fail == 0)
+ conf->fast_io_fail = MP_FAST_IO_FAIL_ZERO;
@@ -5656,10 +7257,11 @@ index 02aa238..4df3d9b 100644
conf->dev_loss = 0;
FREE(buff);
-@@ -77,6 +85,33 @@ verbosity_handler(vector strvec)
+@@ -77,11 +85,27 @@ verbosity_handler(vector strvec)
}
static int
+-udev_dir_handler(vector strvec)
+max_polling_interval_handler(vector strvec)
+{
+ char *buff;
@@ -5672,25 +7274,36 @@ index 02aa238..4df3d9b 100644
+
+static int
+reassign_maps_handler(vector strvec)
-+{
+ {
+- conf->udev_dir = set_value(strvec);
+ char * buff;
-+
+
+- if (!conf->udev_dir)
+ buff = set_value(strvec);
+ if (!strcmp(buff, "yes"))
+ conf->reassign_maps = 1;
+ else if (!strcmp(buff, "no"))
+ conf->reassign_maps = 0;
+ else
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static int
- udev_dir_handler(vector strvec)
+ return 1;
+
+ return 0;
+@@ -126,11 +150,11 @@ def_pgpolicy_handler(vector strvec)
+ }
+
+ static int
+-def_getuid_callout_handler(vector strvec)
++def_uid_attribute_handler(vector strvec)
{
- conf->udev_dir = set_value(strvec);
-@@ -148,6 +183,17 @@ def_prio_handler(vector strvec)
+- conf->getuid = set_value(strvec);
++ conf->uid_attribute = set_value(strvec);
+
+- if (!conf->getuid)
++ if (!conf->uid_attribute)
+ return 1;
+
+ return 0;
+@@ -148,6 +172,17 @@ def_prio_handler(vector strvec)
}
static int
@@ -5708,7 +7321,7 @@ index 02aa238..4df3d9b 100644
def_prio_args_handler(vector strvec)
{
conf->prio_args = set_value(strvec);
-@@ -197,6 +243,22 @@ def_minio_handler(vector strvec)
+@@ -197,6 +232,22 @@ def_minio_handler(vector strvec)
}
static int
@@ -5731,7 +7344,7 @@ index 02aa238..4df3d9b 100644
get_sys_max_fds(int *max_fds)
{
FILE *file;
-@@ -327,6 +389,10 @@ def_weight_handler(vector strvec)
+@@ -327,6 +378,10 @@ def_weight_handler(vector strvec)
!strcmp(buff, "priorities"))
conf->rr_weight = RR_WEIGHT_PRIO;
@@ -5742,10 +7355,35 @@ index 02aa238..4df3d9b 100644
FREE(buff);
return 0;
-@@ -395,6 +461,25 @@ def_queue_without_daemon(vector strvec)
- }
+@@ -343,6 +398,8 @@ default_failback_handler(vector strvec)
+ conf->pgfailback = -FAILBACK_MANUAL;
+ else if (strlen(buff) == 9 && !strcmp(buff, "immediate"))
+ conf->pgfailback = -FAILBACK_IMMEDIATE;
++ else if (strlen(buff) == 10 && !strcmp(buff, "followover"))
++ conf->pgfailback = -FAILBACK_FOLLOWOVER;
+ else
+ conf->pgfailback = atoi(buff);
- static int
+@@ -381,14 +438,30 @@ def_queue_without_daemon(vector strvec)
+ if (!buff)
+ return 1;
+
+- if (!strncmp(buff, "off", 3) || !strncmp(buff, "no", 2) ||
+- !strncmp(buff, "0", 1))
+- conf->queue_without_daemon = QUE_NO_DAEMON_OFF;
+- else if (!strncmp(buff, "on", 2) || !strncmp(buff, "yes", 3) ||
++ if (!strncmp(buff, "on", 2) || !strncmp(buff, "yes", 3) ||
+ !strncmp(buff, "1", 1))
+ conf->queue_without_daemon = QUE_NO_DAEMON_ON;
+ else
+- conf->queue_without_daemon = QUE_NO_DAEMON_UNDEF;
++ conf->queue_without_daemon = QUE_NO_DAEMON_OFF;
++
++ free(buff);
++ return 0;
++}
++
++static int
+def_checker_timeout_handler(vector strvec)
+{
+ unsigned int checker_timeout;
@@ -5759,19 +7397,23 @@ index 02aa238..4df3d9b 100644
+ conf->checker_timeout = checker_timeout;
+ else
+ conf->checker_timeout = 0;
-+
-+ free(buff);
-+ return 0;
-+}
-+
-+static int
- def_pg_timeout_handler(vector strvec)
- {
- int pg_timeout;
-@@ -443,6 +528,72 @@ def_flush_on_last_del_handler(vector strvec)
+
+ free(buff);
+ return 0;
+@@ -432,7 +505,7 @@ def_flush_on_last_del_handler(vector strvec)
+ if ((strlen(buff) == 2 && strcmp(buff, "no") == 0) ||
+ (strlen(buff) == 1 && strcmp(buff, "0") == 0))
+ conf->flush_on_last_del = FLUSH_DISABLED;
+- if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) ||
++ else if ((strlen(buff) == 3 && strcmp(buff, "yes") == 0) ||
+ (strlen(buff) == 1 && strcmp(buff, "1") == 0))
+ conf->flush_on_last_del = FLUSH_ENABLED;
+ else
+@@ -443,7 +516,141 @@ def_flush_on_last_del_handler(vector strvec)
}
static int
+-names_handler(vector strvec)
+def_log_checker_err_handler(vector strvec)
+{
+ char * buff;
@@ -5838,13 +7480,28 @@ index 02aa238..4df3d9b 100644
+}
+
+static int
- names_handler(vector strvec)
- {
- char * buff;
-@@ -463,6 +614,17 @@ names_handler(vector strvec)
- return 0;
- }
-
++def_names_handler(vector strvec)
++{
++ char * buff;
++
++ buff = set_value(strvec);
++
++ if (!buff)
++ return 1;
++
++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "0")))
++ conf->user_friendly_names = USER_FRIENDLY_NAMES_OFF;
++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "1")))
++ conf->user_friendly_names = USER_FRIENDLY_NAMES_ON;
++ else
++ conf->user_friendly_names = USER_FRIENDLY_NAMES_UNDEF;
++
++ FREE(buff);
++ return 0;
++}
++
+static int
+bindings_file_handler(vector strvec)
+{
@@ -5856,33 +7513,84 @@ index 02aa238..4df3d9b 100644
+ return 0;
+}
+
- /*
- * blacklist block handlers
- */
-@@ -675,6 +837,22 @@ product_handler(vector strvec)
- }
-
- static int
-+revision_handler(vector strvec)
++static int
++wwids_file_handler(vector strvec)
+{
-+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
++ conf->wwids_file = set_value(strvec);
+
-+ if (!hwe)
++ if (!conf->wwids_file)
+ return 1;
+
-+ hwe->revision = set_value(strvec);
++ return 0;
++}
+
-+ if (!hwe->revision)
++static int
++def_retain_hwhandler_handler(vector strvec)
++{
++ char * buff;
++
++ buff = set_value(strvec);
++
++ if (!buff)
+ return 1;
+
++ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "0")))
++ conf->retain_hwhandler = RETAIN_HWHANDLER_OFF;
++ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
++ (strlen(buff) == 1 && !strcmp(buff, "1")))
++ conf->retain_hwhandler = RETAIN_HWHANDLER_ON;
++ else
++ conf->retain_hwhandler = RETAIN_HWHANDLER_UNDEF;
++
++ FREE(buff);
+ return 0;
+}
+
+static int
- bl_product_handler(vector strvec)
++def_detect_prio_handler(vector strvec)
{
- struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
-@@ -697,10 +875,12 @@ hw_fast_io_fail_handler(vector strvec)
+ char * buff;
+
+@@ -454,10 +661,12 @@ names_handler(vector strvec)
+
+ if ((strlen(buff) == 2 && !strcmp(buff, "no")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "0")))
+- conf->user_friendly_names = 0;
++ conf->detect_prio = DETECT_PRIO_OFF;
+ else if ((strlen(buff) == 3 && !strcmp(buff, "yes")) ||
+ (strlen(buff) == 1 && !strcmp(buff, "1")))
+- conf->user_friendly_names = 1;
++ conf->detect_prio = DETECT_PRIO_ON;
++ else
++ conf->detect_prio = DETECT_PRIO_UNDEF;
+
+ FREE(buff);
+ return 0;
+@@ -675,6 +884,22 @@ product_handler(vector strvec)
+ }
+
+ static int
++revision_handler(vector strvec)
++{
++ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
++
++ if (!hwe)
++ return 1;
++
++ hwe->revision = set_value(strvec);
++
++ if (!hwe->revision)
++ return 1;
++
++ return 0;
++}
++
++static int
+ bl_product_handler(vector strvec)
+ {
+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
+@@ -697,10 +922,12 @@ hw_fast_io_fail_handler(vector strvec)
buff = set_value(strvec);
if (strlen(buff) == 3 && !strcmp(buff, "off"))
@@ -5890,14 +7598,15 @@ index 02aa238..4df3d9b 100644
+ hwe->fast_io_fail = MP_FAST_IO_FAIL_OFF;
else if (sscanf(buff, "%d", &hwe->fast_io_fail) != 1 ||
- hwe->fast_io_fail < -1)
+- hwe->fast_io_fail = 0;
+ hwe->fast_io_fail < MP_FAST_IO_FAIL_ZERO)
- hwe->fast_io_fail = 0;
++ hwe->fast_io_fail = MP_FAST_IO_FAIL_UNSET;
+ else if (hwe->fast_io_fail == 0)
+ hwe->fast_io_fail = MP_FAST_IO_FAIL_ZERO;
FREE(buff);
return 0;
-@@ -713,7 +893,12 @@ hw_dev_loss_handler(vector strvec)
+@@ -713,7 +940,12 @@ hw_dev_loss_handler(vector strvec)
struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
buff = set_value(strvec);
@@ -5911,7 +7620,24 @@ index 02aa238..4df3d9b 100644
hwe->dev_loss = 0;
FREE(buff);
-@@ -831,6 +1016,22 @@ hw_prio_handler(vector strvec)
+@@ -738,13 +970,13 @@ hw_pgpolicy_handler(vector strvec)
+ }
+
+ static int
+-hw_getuid_callout_handler(vector strvec)
++hw_uid_attribute_handler(vector strvec)
+ {
+ struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
+
<Skipped 14033 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/multipath-tools.git/commitdiff/81d0f82c939505ab8e223a7d5156bee541ea7656
More information about the pld-cvs-commit
mailing list