[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