File multipath-tools-sles11-alpha1-update of Package multipath-tools

--- multipath-tools-0.4.8/Makefile.inc
+++ multipath-tools-0.4.8/Makefile.inc
@@ -13,7 +13,7 @@
 	TOPDIR	= ..
 endif
 
-prefix      = 
+prefix      =
 exec_prefix = $(prefix)
 bindir      = $(exec_prefix)/sbin
 libudevdir  = ${prefix}/lib/udev
--- multipath-tools-0.4.8/kpartx/Makefile
+++ multipath-tools-0.4.8/kpartx/Makefile
@@ -15,21 +15,29 @@
 
 $(EXEC): $(OBJS)
 	$(CC) $(OBJS) -o $(EXEC) $(LDFLAGS)
-	$(GZIP) $(EXEC).8 > $(EXEC).8.gz
-	
+
 install: $(EXEC) $(EXEC).8
 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
 	$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
+	$(INSTALL_PROGRAM) -m 755 activate_dm_linear $(DESTDIR)$(bindir)
 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(libudevdir)
 	$(INSTALL_PROGRAM) -m 755 kpartx_id $(DESTDIR)$(libudevdir)
 	$(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d
-	$(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/
+	$(INSTALL_PROGRAM) -m 644 kpartx.rules $(DESTDIR)/etc/udev/rules.d/70-kpartx.rules
 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
-	$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
+	$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)
+	$(INSTALL_PROGRAM) -d $(DESTDIR)/lib/mkinitrd/scripts
+	$(INSTALL_PROGRAM) -m 755 boot-kpartx.sh $(DESTDIR)/lib/mkinitrd/scripts
+	$(INSTALL_PROGRAM) -m 755 setup-kpartx.sh $(DESTDIR)/lib/mkinitrd/scripts
 
 uninstall:
 	rm -f $(DESTDIR)$(bindir)/$(EXEC)
-	rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
+	rm -f $(DESTDIR)$(bindir)/activate_dm_linear
+	rm -f $(DESTDIR)$(libudevdir)/kpartx_id
+	rm -f $(DESTDIR)/etc/udev/rules.d/70-kpartx.rules
+	rm -f $(DESTDIR)$(mandir)/$(EXEC).8
+	rm -f $(DESTDIR)/lib/mkinitrd/scripts/boot-kpartx.sh
+	rm -f $(DESTDIR)/lib/mkinitrd/scripts/setup-kpartx.sh
 
 clean:
-	rm -f core *.o $(EXEC) *.gz
+	rm -f core *.o $(EXEC)
--- multipath-tools-0.4.8/kpartx/activate_dm_linear
+++ multipath-tools-0.4.8/kpartx/activate_dm_linear
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+# activate_dm_linear
+#
+# Activate a linear mapping on top of an existing block device.
+# This allows for partitions to be mapped via kpartx, so all
+# partitions on a device can be accessed.
+#
+
+RULE=/etc/udev/rules.d/62-dm_linear.rules
+
+if [ -z "$1" ] ; then
+    echo "Usage: $0 [-d] devname"
+    exit 1
+fi
+
+if [ "$1" == "-d" ] ; then
+    remove_only=1
+    shift
+fi
+
+if [ ! -b "$1" ] ; then
+    echo "$1 is not a block device"
+    exit 1
+fi
+
+dev=${1#/dev/}
+
+if [ ! -d /sys/block/$dev ] ; then
+    echo "$1 is not a disk device"
+    exit 1
+fi
+
+blksize=$(/sbin/blockdev --getsize $1)
+if [ $? -ne 0 ] ; then
+    echo "blockdev --getsize $1 failed: $?"
+    exit 1
+fi
+
+for link in $(udevadm info -q symlink -p /block/$dev) ; do
+    case "$link" in
+	*/by-id/ata*)
+            atalink=${link#*/by-id/ata-}
+	    ;;
+	*/by-id/scsi*)
+	    scsilink=${link#*/by-id/scsi-}
+	    ;;
+    esac
+done
+if [ "$atalink" ] ; then
+    # Remove existing rules
+    echo "/$atalink/d
+w
+q
+" | ed $RULE > /dev/null 2>&1
+    [ "$remove_only" = 1 ] && exit 0
+    cat >> $RULE <<EOF
+ACTION=="add", KERNEL=="sd*[!0-9]", ENV{ID_VENDOR}=="ATA", ENV{ID_ATA_COMPAT}=="$atalink", RUN+="/bin/bash -c 'echo 0 $blksize linear \$major:\$minor 0 | /sbin/dmsetup create ata-\$env{ID_ATA_COMPAT} -u linear-ata-\$env{ID_ATA_COMPAT}'"
+EOF
+fi
+if [ "$scsilink" ] ; then
+    # Remove existing rules
+    echo "/$scsilink/d
+w
+q
+" | ed $RULE > /dev/null 2>&1
+    [ "$remove_only" = 1 ] && exit 0
+    # And create a new one
+    cat >> $RULE <<EOF
+ACTION=="add", KERNEL=="sd*[!0-9]", ENV{ID_BUS}=="scsi", ENV{ID_SERIAL}=="$scsilink", RUN+="/bin/bash -c 'echo 0 $blksize linear \$major:\$minor 0 | /sbin/dmsetup create \$env{ID_BUS}-\$env{ID_SERIAL} -u linear-\$env{ID_BUS}-\$env{ID_SERIAL}'"
+EOF
+fi
--- multipath-tools-0.4.8/kpartx/boot-kpartx.sh
+++ multipath-tools-0.4.8/kpartx/boot-kpartx.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+#%stage: block
+#%depends: dmroot
+#%if: "$root_kpartx"
+#%programs: /sbin/kpartx /lib/udev/kpartx_id
--- multipath-tools-0.4.8/kpartx/devmapper.c
+++ multipath-tools-0.4.8/kpartx/devmapper.c
@@ -13,6 +13,7 @@
 
 #define UUID_PREFIX "part%d-"
 #define MAX_PREFIX_LEN 8
+#define PARAMS_SIZE 1024
 
 extern int
 dm_prereq (char * str, int x, int y, int z)
@@ -251,3 +252,63 @@
 	return r;
 }
 
+int
+dm_get_map(int major, int minor, char * outparams)
+{
+	int r = 1;
+	struct dm_task *dmt;
+	void *next = NULL;
+	uint64_t start, length;
+	char *target_type = NULL;
+	char *params = NULL;
+
+	if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+		return 1;
+
+	dm_task_set_major(dmt, major);
+	dm_task_set_minor(dmt, minor);
+	dm_task_no_open_count(dmt);
+
+	if (!dm_task_run(dmt))
+		goto out;
+
+	/* Fetch 1st target */
+	next = dm_get_next_target(dmt, next, &start, &length,
+				  &target_type, &params);
+
+	if (snprintf(outparams, PARAMS_SIZE, "%s", params) <= PARAMS_SIZE)
+		r = 0;
+out:
+	dm_task_destroy(dmt);
+	return r;
+}
+
+#define FEATURE_NO_PART "no_partitions"
+
+int
+dm_no_partitions(int major, int minor)
+{
+	char params[PARAMS_SIZE], *ptr;
+	int i, num_features;
+
+	if (dm_get_map(major, minor, params))
+		return 0;
+
+	ptr = params;
+	num_features = strtoul(params, &ptr, 10);
+	if ((ptr == params) || num_features == 0) {
+		/* No features found, return success */
+		return 0;
+	}
+	for (i = 0; (i < num_features); i++) {
+		if (!ptr || ptr > params + strlen(params))
+			break;
+		/* Skip whitespaces */
+		while(ptr && *ptr == ' ') ptr++;
+		if (!strncmp(ptr, FEATURE_NO_PART, strlen(FEATURE_NO_PART)))
+			return 1;
+		ptr = strchr(ptr, ' ');
+	}
+	return 0;
+}
+
--- multipath-tools-0.4.8/kpartx/devmapper.h
+++ multipath-tools-0.4.8/kpartx/devmapper.h
@@ -7,3 +7,4 @@
 dev_t dm_get_first_dep(char *devname);
 char * dm_mapuuid(int major, int minor);
 int dm_devn (char * mapname, int *major, int *minor);
+int dm_no_partitions(int major, int minor);
--- multipath-tools-0.4.8/kpartx/kpartx.c
+++ multipath-tools-0.4.8/kpartx/kpartx.c
@@ -257,7 +257,7 @@
 	}
 
 	if (dm_prereq(DM_TARGET, 0, 0, 0) && (what == ADD || what == DELETE)) {
-		fprintf(stderr, "device mapper prerequisites not met\n"); 
+		fprintf(stderr, "device mapper prerequisites not met\n");
 		exit(1);
 	}
 
@@ -314,8 +314,13 @@
 	if (!uuid)
 		uuid = device + off;
 
-	if (!mapname)
+	if (!mapname) {
 		mapname = device + off;
+	} else if (dm_no_partitions((unsigned int)MAJOR(buf.st_rdev),
+				  (unsigned int)MINOR(buf.st_rdev))) {
+		/* Feature 'no_partitions' is set, return */
+		return 0;
+	}
 
 	fd = open(device, O_RDONLY);
 
@@ -423,7 +428,7 @@
 			break;
 
 		case ADD:
-			for (j=0, c = 0; j<n; j++) {
+			for (j = 0, c = 0; j < n; j++) {
 				if (slices[j].size == 0)
 					continue;
 
@@ -474,6 +479,7 @@
 			d = c;
 			while (c) {
 				for (j = 0; j < n; j++) {
+					uint64_t start;
 					int k = slices[j].container - 1;
 
 					if (slices[j].size == 0)
@@ -484,7 +490,7 @@
 						continue;
 
 					/* Skip all simple slices */
-					if (k < 0)
+					if (slices[j].container == 0)
 						continue;
 
 					/* Check container slice */
@@ -499,10 +505,11 @@
 					}
 					strip_slash(partname);
 
+					start = slices[j].start - slices[k].start;
 					if (safe_sprintf(params, "%d:%d %" PRIu64,
 							 slices[k].major,
 							 slices[k].minor,
-							 slices[j].start)) {
+							 start)) {
 						fprintf(stderr, "params too small\n");
 						exit(1);
 					}
--- multipath-tools-0.4.8/kpartx/kpartx.rules
+++ multipath-tools-0.4.8/kpartx/kpartx.rules
@@ -9,7 +9,7 @@
 
 ENV{DM_TABLE_STATE}!="LIVE", GOTO="kpartx_end"
 
-ENV{DM_UUID}=="?*", IMPORT{program}=="/lib/udev/kpartx_id %M %m $env{DM_UUID}"
+ENV{DM_UUID}=="?*", IMPORT{program}=="kpartx_id %M %m $env{DM_UUID}"
 
 OPTIONS="link_priority=50"
 
@@ -18,7 +18,11 @@
 	SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
 
 # Create persistent links for dmraid tables
-ENV{DM_UUID}=="mpath-*", \
+ENV{DM_UUID}=="dmraid-*", \
+        SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
+
+# Create persistent links for linear tables
+ENV{DM_UUID}=="linear-*", \
         SYMLINK+="disk/by-id/$env{DM_TYPE}-$env{DM_NAME}"
 
 # Create persistent links for partitions
@@ -27,9 +31,11 @@
 
 # Create dm tables for partitions
 ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="mpath-*", \
-        RUN+="/sbin/kpartx -a -p -part /dev/$kernel"
+        RUN+="/sbin/kpartx -a -p _part /dev/$kernel"
 ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="dmraid-*", \
-        RUN+="/sbin/kpartx -a -p -part /dev/$kernel"
+        RUN+="/sbin/kpartx -a -p _part /dev/$kernel"
+ENV{DM_STATE}=="ACTIVE", ENV{DM_UUID}=="linear-*", \
+        RUN+="/sbin/kpartx -a -p _part /dev/$kernel"
 
 LABEL="kpartx_end"
 
--- multipath-tools-0.4.8/kpartx/kpartx_id
+++ multipath-tools-0.4.8/kpartx/kpartx_id
@@ -50,7 +50,7 @@
 fi
 
 # Set the name of the table. We're only interested in dmraid,
-# multipath, and kpartx tables; everything else is ignored.
+# multipath, linear, and kpartx tables; everything else is ignored.
 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)
@@ -61,6 +61,10 @@
 	mpath-*)
 	    dmdeps=$($DMSETUP deps -u $dmuuid)
 	    ;;
+	linear-*)
+	    dmtbl=linear
+	    dmuuid=${dmuuid#*-}
+	    ;;
     esac
 elif [ "$dmtbl" = "mpath" ] ; then
     dmname=$tblname
@@ -72,8 +76,8 @@
 
 [ -n "$dmpart" ] && echo "DM_PART=$dmpart"
 
-# Figure out the type of the map. For non-multipath maps it's
-# always 'raid'.
+# Figure out the type of the map. For non-multipath non-linear 
+# maps it's always 'raid'.
 if [ -n "$dmdeps" ] ; then
     case "$dmdeps" in
 	*\(94,*)
@@ -86,6 +90,9 @@
             echo "DM_TYPE=scsi"
 	    ;;
     esac
+elif [ "$dmtbl" = linear ]; then
+    echo "DM_TYPE=${dmuuid%%-*}"
+    echo "DM_NAME=${dmuuid#*-}"
 else
     echo "DM_TYPE=raid"
 fi
--- multipath-tools-0.4.8/kpartx/setup-kpartx.sh
+++ multipath-tools-0.4.8/kpartx/setup-kpartx.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+#%stage: partitions
+#
+if [ -x /sbin/dmsetup ]; then
+	kpartx_blockdev=
+
+	# always activate kpartx when using dm block
+	[ "$DM_BLOCK" ] && root_kpartx=1
+	# always activate kpartx for multipathing
+	use_script multipath && root_kpartx=1
+	for bd in $blockdev ; do
+	    update_blockdev $bd
+	    if [ "$blockdriver" = device-mapper ]; then
+		dm_uuid=$(dmsetup info -c --noheadings -o uuid -j $blockmajor -m $blockminor)
+		case $dm_uuid in
+		    part*)
+		    	dm_uuid="${dm_uuid#*-}"
+				kpartx_blockdev="$kpartx_blockdev $(majorminor2blockdev $(dmsetup info -u $dm_uuid --noheadings -c -o major,minor))"
+				root_kpartx=1
+				;;
+			*)
+				kpartx_blockdev="$kpartx_blockdev $bd"
+				;;
+		esac
+	    else
+		kpartx_blockdev="$kpartx_blockdev $bd"
+	    fi
+	done
+
+	blockdev="$kpartx_blockdev"
+fi
+
+if use_script kpartx; then 
+	cp /etc/udev/rules.d/70-kpartx.rules $tmp_mnt/etc/udev/rules.d
+fi
--- multipath-tools-0.4.8/libmultipath/Makefile
+++ multipath-tools-0.4.8/libmultipath/Makefile
@@ -25,9 +25,8 @@
 $(LIBS): $(OBJS)
 	$(CC) $(SHARED_FLAGS) $(CFLAGS) -o $@ $(OBJS)
 
-install:
-	$(INSTALL_PROGRAM) -m 755 -d $(DESTDIR)$(libdir)
-	$(INSTALL_PROGRAM) -m 755 $(LIBS) $(DESTDIR)$(libdir)/$(LIBS)
+install: $(LIBS)
+	$(INSTALL_PROGRAM) -D $(LIBS) $(DESTDIR)$(libdir)/$(LIBS)
 
 uninstall:
 	rm -f $(DESTDIR)$(libdir)/$(LIBS)
--- multipath-tools-0.4.8/libmultipath/alias.c
+++ multipath-tools-0.4.8/libmultipath/alias.c
@@ -86,7 +86,7 @@
 	sigset_t set, oldset;
 	struct flock lock;
 	int err;
-	
+
 	memset(&lock, 0, sizeof(lock));
 	lock.l_type = F_WRLCK;
 	lock.l_whence = SEEK_SET;
@@ -149,7 +149,7 @@
 	}
 	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));
@@ -171,7 +171,7 @@
 		fsync(fd);
 		condlog(3, "Initialized new bindings file [%s]", file);
 	}
-	
+
 	return fd;
 
 fail:
--- multipath-tools-0.4.8/libmultipath/blacklist.c
+++ multipath-tools-0.4.8/libmultipath/blacklist.c
@@ -16,7 +16,7 @@
 store_ble (vector blist, char * str, int origin)
 {
 	struct blentry * ble;
-	
+
 	if (!str)
 		return 0;
 
@@ -61,12 +61,12 @@
 	vector_set_slot(blist, ble);
 	return 0;
 }
-	
+
 extern int
 set_ble_device (vector blist, char * vendor, char * product, int origin)
 {
 	struct blentry_device * ble;
-	
+
 	if (!blist)
 		return 1;
 
@@ -142,14 +142,14 @@
 int
 _blacklist_exceptions (vector elist, char * str)
 {
-        int i;
-        struct blentry * ele;
+	int i;
+	struct blentry * ele;
 
-        vector_foreach_slot (elist, ele, i) {
-                if (!regexec(&ele->regex, str, 0, NULL, 0))
+	vector_foreach_slot (elist, ele, i) {
+		if (!regexec(&ele->regex, str, 0, NULL, 0))
 			return 1;
 	}
-        return 0;
+	return 0;
 }
 
 int
@@ -194,11 +194,11 @@
 }
 
 #define LOG_BLIST(M) \
-	if (vendor && product)                                           \
+	if (vendor && product)						 \
 		condlog(3, "%s: (%s:%s) %s", dev, vendor, product, (M)); \
-	else if (wwid)                                                   \
-		condlog(3, "%s: (%s) %s", dev, wwid, (M));               \
-	else                                                             \
+	else if (wwid)							 \
+		condlog(3, "%s: (%s) %s", dev, wwid, (M));		 \
+	else								 \
 		condlog(3, "%s: %s", dev, (M))
 
 void
@@ -300,7 +300,7 @@
 	if (r > 0)
 		return r;
 	r = _filter_device(conf->blist_device, conf->elist_device,
-		 	   pp->vendor_id, pp->product_id);
+			   pp->vendor_id, pp->product_id);
 	if (r > 0)
 		return r;
 	r = _filter_wwid(conf->blist_wwid, conf->elist_wwid, pp->wwid);
--- multipath-tools-0.4.8/libmultipath/callout.c
+++ multipath-tools-0.4.8/libmultipath/callout.c
@@ -83,8 +83,8 @@
 		null_fd = open("/dev/null", O_WRONLY);
 		if (null_fd > 0) {
 			close(STDERR_FILENO);
-			dup(null_fd);
-			close(null_fd);
+			if (dup(null_fd) >= 0)
+				close(null_fd);
 		}
 
 		retval = execv(argv[0], argv);
--- multipath-tools-0.4.8/libmultipath/config.c
+++ multipath-tools-0.4.8/libmultipath/config.c
@@ -50,42 +50,55 @@
 	return ret;
 }
 
+static int
+hwe_regmatch (struct hwentry *hwe1, struct hwentry *hwe2)
+{
+	regex_t vre, pre, rre;
+	int retval = 1;
+
+	if (hwe1->vendor &&
+	    regcomp(&vre, hwe1->vendor, REG_EXTENDED|REG_NOSUB))
+		goto out;
+
+	if (hwe1->product &&
+	    regcomp(&pre, hwe1->product, REG_EXTENDED|REG_NOSUB))
+		goto out_vre;
+
+	if (hwe1->revision &&
+	    regcomp(&rre, hwe1->revision, REG_EXTENDED|REG_NOSUB))
+		goto out_pre;
+
+	if ((!hwe1->vendor || !regexec(&vre, hwe2->vendor, 0, NULL, 0)) &&
+	    (!hwe1->product || !regexec(&pre, hwe2->product, 0, NULL, 0)) &&
+	    (!hwe1->revision || !regexec(&rre, hwe2->revision, 0, NULL, 0)))
+		retval = 0;
+
+	if (hwe1->revision)
+		regfree(&rre);
+out_pre:
+	if (hwe1->product)
+		regfree(&pre);
+out_vre:
+	if (hwe1->vendor)
+		regfree(&vre);
+out:
+	return retval;
+}
+
 struct hwentry *
 find_hwe (vector hwtable, char * vendor, char * product, char * revision)
 {
 	int i;
-	struct hwentry *hwe, *ret = NULL;
-	regex_t vre, pre, rre;
+	struct hwentry hwe, *tmp, *ret = NULL;
 
-	vector_foreach_slot (hwtable, hwe, i) {
-		if (hwe->vendor &&
-		    regcomp(&vre, hwe->vendor, REG_EXTENDED|REG_NOSUB))
-			break;
-		if (hwe->product &&
-		    regcomp(&pre, hwe->product, REG_EXTENDED|REG_NOSUB)) {
-			regfree(&vre);
-			break;
-		}
-		if (hwe->revision &&
-		    regcomp(&rre, hwe->revision, REG_EXTENDED|REG_NOSUB)) {
-			regfree(&vre);
-			regfree(&pre);
-			break;
-		}
-		if ((!hwe->vendor || !regexec(&vre, vendor, 0, NULL, 0)) &&
-		    (!hwe->product || !regexec(&pre, product, 0, NULL, 0)) &&
-		    (!hwe->revision || !regexec(&rre, revision, 0, NULL, 0)))
-			ret = hwe;
-
-		if (hwe->revision)
-			regfree(&rre);
-		if (hwe->product)
-			regfree(&pre);
-		if (hwe->vendor)
-			regfree(&vre);
-
-		if (ret)
-			break;
+	hwe.vendor = vendor;
+	hwe.product = product;
+	hwe.revision = revision;
+	vector_foreach_slot (hwtable, tmp, i) {
+		if (hwe_regmatch(tmp, &hwe))
+			continue;
+		ret = tmp;
+		break;
 	}
 	return ret;
 }
@@ -289,25 +302,25 @@
 
 	if (find_hwe_strmatch(hwtable, dhwe))
 		return 0;
-	
+
 	if (!(hwe = alloc_hwe()))
 		return 1;
 
 	if (!dhwe->vendor || !(hwe->vendor = set_param_str(dhwe->vendor)))
 		goto out;
-	
+
 	if (!dhwe->product || !(hwe->product = set_param_str(dhwe->product)))
 		goto out;
-	
+
 	if (dhwe->revision && !(hwe->revision = set_param_str(dhwe->revision)))
 		goto out;
-	
+
 	if (dhwe->getuid && !(hwe->getuid = set_param_str(dhwe->getuid)))
 		goto out;
 
 	if (dhwe->features && !(hwe->features = set_param_str(dhwe->features)))
 		goto out;
-	
+
 	if (dhwe->hwhandler && !(hwe->hwhandler = set_param_str(dhwe->hwhandler)))
 		goto out;
 
@@ -316,10 +329,10 @@
 
 	if (dhwe->checker_name && !(hwe->checker_name = set_param_str(dhwe->checker_name)))
 		goto out;
-				
+
 	if (dhwe->prio_name && !(hwe->prio_name = set_param_str(dhwe->prio_name)))
 		goto out;
-				
+
 	hwe->pgpolicy = dhwe->pgpolicy;
 	hwe->pgfailback = dhwe->pgfailback;
 	hwe->rr_weight = dhwe->rr_weight;
@@ -348,7 +361,7 @@
 	vector_foreach_slot(hw, hwe1, i) {
 		j = i+1;
 		vector_foreach_slot_after(hw, hwe2, j) {
-			if (hwe_strmatch(hwe1, hwe2))
+			if (hwe_regmatch(hwe1, hwe2))
 				continue;
 			/* dup */
 			merge_hwe(hwe1, hwe2);
@@ -393,6 +406,9 @@
 	if (conf->hwhandler)
 		FREE(conf->hwhandler);
 
+	if (conf->bindings_file)
+		FREE(conf->bindings_file);
+
 	free_blacklist(conf->blist_devnode);
 	free_blacklist(conf->blist_wwid);
 	free_blacklist_device(conf->blist_device);
@@ -425,7 +441,6 @@
 	conf->dev_type = DEV_NONE;
 	conf->minio = 1000;
 	conf->max_fds = 0;
-	conf->bindings_file = DEFAULT_BINDINGS_FILE;
 	conf->multipath_dir = set_default(DEFAULT_MULTIPATHDIR);
 
 	/*
@@ -443,12 +458,15 @@
 	/*
 	 * read the config file
 	 */
+	set_current_keywords(&conf->keywords);
+	alloc_keywords();
 	if (filepresent(file)) {
-		set_current_keywords(&conf->keywords);
 		if (init_data(file, init_keywords)) {
 			condlog(0, "error parsing config file");
 			goto out;
 		}
+	} else {
+		init_keywords();
 	}
 
 	/*
@@ -503,7 +521,6 @@
 
 	if (conf->mptable == NULL) {
 		conf->mptable = vector_alloc();
-
 		if (!conf->mptable)
 			goto out;
 	}
@@ -522,9 +539,12 @@
 	if (conf->hwhandler == NULL)
 		conf->hwhandler = set_default(DEFAULT_HWHANDLER);
 
+	if (conf->bindings_file == NULL)
+		conf->bindings_file = set_default(DEFAULT_BINDINGS_FILE);
+
 	if (!conf->selector  || !conf->udev_dir || !conf->multipath_dir ||
 	    !conf->getuid    || !conf->features ||
-	    !conf->hwhandler)
+	    !conf->hwhandler || !conf->bindings_file)
 		goto out;
 
 	if (!conf->prio_name)
--- multipath-tools-0.4.8/libmultipath/configure.c
+++ multipath-tools-0.4.8/libmultipath/configure.c
@@ -162,7 +162,7 @@
 			mpp->alias);
 		return;
 	}
-		
+
 	if (pathcount(mpp, PATH_UP) == 0) {
 		mpp->action = ACT_NOTHING;
 		condlog(3, "%s: set ACT_NOTHING (no usable path)",
@@ -272,7 +272,7 @@
 
 	if (!mpp || !mpp->pg)
 		return 0;
-	
+
 	vector_foreach_slot (mpp->pg, pgp, i) {
 		if (!pgp->paths)
 			continue;
@@ -402,7 +402,7 @@
 			if (strlen(pp->dev))
 				return 0; /* alive */
 	}
-	
+
 	return 1; /* dead */
 }
 
@@ -460,13 +460,13 @@
 			remove_map(mpp, vecs, 0);
 			continue;
 		}
-		
+
 		for (i = k + 1; i < VECTOR_SIZE(pathvec); i++) {
 			pp2 = VECTOR_SLOT(pathvec, i);
 
 			if (strcmp(pp1->wwid, pp2->wwid))
 				continue;
-			
+
 			if (!pp2->size)
 				continue;
 
--- multipath-tools-0.4.8/libmultipath/defaults.h
+++ multipath-tools-0.4.8/libmultipath/defaults.h
@@ -1,4 +1,4 @@
-#define DEFAULT_GETUID		"/lib/udev/scsi_id -g -u -s /block/%n"
+#define DEFAULT_GETUID		"/lib/udev/scsi_id -g -u /dev/%n"
 #define DEFAULT_UDEVDIR		"/dev"
 #define DEFAULT_MULTIPATHDIR	"/lib/multipath"
 #define DEFAULT_SELECTOR	"round-robin 0"
--- multipath-tools-0.4.8/libmultipath/devmapper.c
+++ multipath-tools-0.4.8/libmultipath/devmapper.c
@@ -161,9 +161,9 @@
 		goto out;
 
 	dm_task_no_open_count(dmt);
-	dm_task_skip_lockfs(dmt);       /* for DM_DEVICE_RESUME */
+	dm_task_skip_lockfs(dmt);	/* for DM_DEVICE_RESUME */
 #ifdef LIBDM_API_FLUSH
-	dm_task_no_flush(dmt);          /* for DM_DEVICE_SUSPEND/RESUME */
+	dm_task_no_flush(dmt);		/* for DM_DEVICE_SUSPEND/RESUME */
 #endif
 
 	r = dm_task_run (dmt);
@@ -340,11 +340,11 @@
 	if (!dmt)
 		return 1;
 
-        if (!dm_task_set_name (dmt, name))
-                goto uuidout;
+	if (!dm_task_set_name (dmt, name))
+		goto uuidout;
 
 	if (!dm_task_run(dmt))
-                goto uuidout;
+		goto uuidout;
 
 	uuidtmp = dm_task_get_uuid(dmt);
 	if (uuidtmp) {
@@ -466,7 +466,7 @@
 	dm_task_destroy(dmt);
 	return r;
 }
-	
+
 int
 dm_get_opencount (const char * mapname)
 {
@@ -491,7 +491,7 @@
 	dm_task_destroy(dmt);
 	return r;
 }
-	
+
 int
 dm_get_minor (char * mapname)
 {
@@ -516,7 +516,7 @@
 	dm_task_destroy(dmt);
 	return r;
 }
-	
+
 extern int
 dm_flush_map (const char * mapname)
 {
@@ -534,7 +534,7 @@
 	if (dm_get_opencount(mapname)) {
 		condlog(2, "%s: map in use", mapname);
 		return 1;
-	}	
+	}
 
 	r = dm_simplecmd(DM_DEVICE_REMOVE, mapname);
 
@@ -746,8 +746,8 @@
 		vector_set_slot(mp, mpp);
 		mpp = NULL;
 next:
-                next = names->next;
-                names = (void *) names + next;
+		next = names->next;
+		names = (void *) names + next;
 	} while (next);
 
 	r = 0;
@@ -927,7 +927,7 @@
 		     */
 		    strstr(params, dev_t)
 		   ) {
-		    		/*
+				/*
 				 * then it's a kpartx generated partition.
 				 * remove it.
 				 */
@@ -957,7 +957,7 @@
 {
 	int r = 1;
 	struct dm_task *dmt = NULL;
-	
+
 	if (!mapname)
 		return 1;
 
@@ -1045,7 +1045,7 @@
 		     */
 		    strstr(buff, dev_t)
 		   ) {
-		    		/*
+				/*
 				 * then it's a kpartx generated partition.
 				 * Rename it.
 				 */
@@ -1083,7 +1083,7 @@
 
 	if (!dm_task_set_newname(dmt, new))
 		goto out;
-	
+
 	dm_task_no_open_count(dmt);
 
 	if (!dm_task_run(dmt))
--- multipath-tools-0.4.8/libmultipath/dict.c
+++ multipath-tools-0.4.8/libmultipath/dict.c
@@ -88,7 +88,7 @@
 
 	if (!conf->getuid)
 		return 1;
-	
+
 	return 0;
 }
 
@@ -267,6 +267,17 @@
 	return 0;
 }
 
+static int
+bindings_file_handler(vector strvec)
+{
+	conf->bindings_file = set_value(strvec);
+
+	if (!conf->bindings_file)
+		return 1;
+
+	return 0;
+}
+
 /*
  * blacklist block handlers
  */
@@ -338,12 +349,12 @@
 static int
 ble_except_wwid_handler(vector strvec)
 {
-        char * buff;
+	char * buff;
 
-        buff = set_value(strvec);
+	buff = set_value(strvec);
 
-        if (!buff)
-                return 1;
+	if (!buff)
+		return 1;
 
 	return store_ble(conf->elist_wwid, buff, ORIGIN_CONFIG);
 }
@@ -453,7 +464,7 @@
 
 	if (!hwe)
 		return 1;
-	
+
 	hwe->vendor = set_value(strvec);
 
 	if (!hwe->vendor)
@@ -469,7 +480,7 @@
 
 	if (!hwe)
 		return 1;
-	
+
 	hwe->product = set_value(strvec);
 
 	if (!hwe->product)
@@ -527,7 +538,7 @@
 hw_selector_handler(vector strvec)
 {
 	struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
-	
+
 	if (!hwe)
 		return 1;
 
@@ -559,7 +570,7 @@
 hw_features_handler(vector strvec)
 {
 	struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
-	
+
 	if (!hwe)
 		return 1;
 
@@ -575,7 +586,7 @@
 hw_handler_handler(vector strvec)
 {
 	struct hwentry * hwe = VECTOR_LAST_SLOT(conf->hwtable);
-	
+
 	if (!hwe)
 		return 1;
 
@@ -781,7 +792,7 @@
 	if (!mpe)
 		return 1;
 
-        mpe->alias = set_value(strvec);
+	mpe->alias = set_value(strvec);
 
 	if (!mpe->alias)
 		return 1;
@@ -813,7 +824,7 @@
 mp_selector_handler(vector strvec)
 {
 	struct mpentry * mpe = VECTOR_LAST_SLOT(conf->mptable);
-	
+
 	if (!mpe)
 		return 1;
 
@@ -981,7 +992,7 @@
 	if (!mpe->pgpolicy)
 		return 0;
 	get_pgpolicy_name(str, POLICY_NAME_SIZE, mpe->pgpolicy);
-	
+
 	return snprintf(buff, len, "%s", str);
 }
 
@@ -1194,7 +1205,7 @@
 		return 0;
 
 	get_pgpolicy_name(str, POLICY_NAME_SIZE, hwe->pgpolicy);
-	
+
 	return snprintf(buff, len, "%s", str);
 }
 
@@ -1362,7 +1373,7 @@
 		return 0;
 
 	get_pgpolicy_name(str, POLICY_NAME_SIZE, conf->pgpolicy);
-	
+
 	return snprintf(buff, len, "%s", str);
 }
 
@@ -1454,7 +1465,7 @@
 		return 0;
 
 	if (conf->max_fds < 0)
-		return snprintf(buff, len, "unlimited");	
+		return snprintf(buff, len, "unlimited");
 	return snprintf(buff, len, "%d", conf->max_fds);
 }
 
@@ -1520,6 +1531,18 @@
 }
 
 static int
+snprint_def_bindings_file (char * buff, int len, void * data)
+{
+	if (conf->bindings_file == NULL)
+		return 0;
+	if (strlen(conf->bindings_file) == strlen(DEFAULT_BINDINGS_FILE) &&
+	    !strcmp(conf->bindings_file, DEFAULT_BINDINGS_FILE))
+		return 0;
+
+	return snprintf(buff, len, "%s", conf->bindings_file);
+}
+
+static int
 snprint_ble_simple (char * buff, int len, void * data)
 {
 	struct blentry * ble = (struct blentry *)data;
@@ -1534,7 +1557,7 @@
 
 	return snprintf(buff, len, "\"%s\"", bled->vendor);
 }
-	
+
 static int
 snprint_bled_product (char * buff, int len, void * data)
 {
@@ -1542,7 +1565,7 @@
 
 	return snprintf(buff, len, "\"%s\"", bled->product);
 }
-	
+
 #define __deprecated
 
 void
@@ -1566,6 +1589,7 @@
 	install_keyword("no_path_retry", &def_no_path_retry_handler, &snprint_def_no_path_retry);
 	install_keyword("pg_timeout", &def_pg_timeout_handler, &snprint_def_pg_timeout);
 	install_keyword("user_friendly_names", &names_handler, &snprint_def_user_friendly_names);
+	install_keyword("bindings_file", &bindings_file_handler, &snprint_def_bindings_file);
 	__deprecated install_keyword("default_selector", &def_selector_handler, NULL);
 	__deprecated install_keyword("default_path_grouping_policy", &def_pgpolicy_handler, NULL);
 	__deprecated install_keyword("default_getuid_callout", &def_getuid_callout_handler, NULL);
--- multipath-tools-0.4.8/libmultipath/discovery.c
+++ multipath-tools-0.4.8/libmultipath/discovery.c
@@ -70,7 +70,7 @@
 		condlog(0, "path too small");
 		return 1;
 	}
-			
+
 	if (strncmp(devname,"cciss",5) && !filepresent(path)) {
 		condlog(4, "path %s not present", path);
 		return 0;
@@ -179,7 +179,7 @@
 
 	return 0;
 }
-	
+
 int
 sysfs_get_fc_nodename (struct sysfs_device * dev, char * node,
 		       unsigned int host, unsigned int channel,
@@ -187,7 +187,7 @@
 {
 	char attr_path[SYSFS_PATH_SIZE], *attr;
 
-	if (safe_sprintf(attr_path, 
+	if (safe_sprintf(attr_path,
 			 "/class/fc_transport/target%i:%i:%i",
 			 host, channel, target)) {
 		condlog(0, "attr_path too small");
@@ -202,10 +202,7 @@
 
 	return 1;
 }
-	
-/*
- * udev might be slow creating node files : wait
- */
+
 static int
 opennode (char * dev, int mode)
 {
@@ -244,11 +241,11 @@
 		condlog(0, "Cannot open /proc/partitions");
 		return 1;
 	}
-	
+
 	while (!feof(fd)) {
 		int r = fscanf(fd,"%u %u %*d %s",&tmpmaj, &tmpmin, dev);
 		if (!r) {
-			fscanf(fd,"%*s\n");
+			r = fscanf(fd,"%*s\n");
 			continue;
 		}
 		if (r != 3)
@@ -280,62 +277,62 @@
 do_inq(int sg_fd, int cmddt, int evpd, unsigned int pg_op,
        void *resp, int mx_resp_len, int noisy)
 {
-        unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
-            { INQUIRY_CMD, 0, 0, 0, 0, 0 };
-        unsigned char sense_b[SENSE_BUFF_LEN];
-        struct sg_io_hdr io_hdr;
-
-        if (cmddt)
-                inqCmdBlk[1] |= 2;
-        if (evpd)
-                inqCmdBlk[1] |= 1;
-        inqCmdBlk[2] = (unsigned char) pg_op;
+	unsigned char inqCmdBlk[INQUIRY_CMDLEN] =
+		{ INQUIRY_CMD, 0, 0, 0, 0, 0 };
+	unsigned char sense_b[SENSE_BUFF_LEN];
+	struct sg_io_hdr io_hdr;
+
+	if (cmddt)
+		inqCmdBlk[1] |= 2;
+	if (evpd)
+		inqCmdBlk[1] |= 1;
+	inqCmdBlk[2] = (unsigned char) pg_op;
 	inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
 	inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff);
-        memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
-        io_hdr.interface_id = 'S';
-        io_hdr.cmd_len = sizeof (inqCmdBlk);
-        io_hdr.mx_sb_len = sizeof (sense_b);
-        io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
-        io_hdr.dxfer_len = mx_resp_len;
-        io_hdr.dxferp = resp;
-        io_hdr.cmdp = inqCmdBlk;
-        io_hdr.sbp = sense_b;
-        io_hdr.timeout = DEF_TIMEOUT;
-
-        if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
-                return -1;
-
-        /* treat SG_ERR here to get rid of sg_err.[ch] */
-        io_hdr.status &= 0x7e;
-        if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
-            (0 == io_hdr.driver_status))
-                return 0;
-        if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
-            (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
-            (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
-                if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
-                        int sense_key;
-                        unsigned char * sense_buffer = io_hdr.sbp;
-                        if (sense_buffer[0] & 0x2)
-                                sense_key = sense_buffer[1] & 0xf;
-                        else
-                                sense_key = sense_buffer[2] & 0xf;
-                        if(RECOVERED_ERROR == sense_key)
-                                return 0;
-                }
-        }
-        return -1;
+	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
+	io_hdr.interface_id = 'S';
+	io_hdr.cmd_len = sizeof (inqCmdBlk);
+	io_hdr.mx_sb_len = sizeof (sense_b);
+	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+	io_hdr.dxfer_len = mx_resp_len;
+	io_hdr.dxferp = resp;
+	io_hdr.cmdp = inqCmdBlk;
+	io_hdr.sbp = sense_b;
+	io_hdr.timeout = DEF_TIMEOUT;
+
+	if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
+		return -1;
+
+	/* treat SG_ERR here to get rid of sg_err.[ch] */
+	io_hdr.status &= 0x7e;
+	if ((0 == io_hdr.status) && (0 == io_hdr.host_status) &&
+	    (0 == io_hdr.driver_status))
+		return 0;
+	if ((SCSI_CHECK_CONDITION == io_hdr.status) ||
+	    (SCSI_COMMAND_TERMINATED == io_hdr.status) ||
+	    (SG_ERR_DRIVER_SENSE == (0xf & io_hdr.driver_status))) {
+		if (io_hdr.sbp && (io_hdr.sb_len_wr > 2)) {
+			int sense_key;
+			unsigned char * sense_buffer = io_hdr.sbp;
+			if (sense_buffer[0] & 0x2)
+				sense_key = sense_buffer[1] & 0xf;
+			else
+				sense_key = sense_buffer[2] & 0xf;
+			if(RECOVERED_ERROR == sense_key)
+				return 0;
+		}
+	}
+	return -1;
 }
 
 static int
 get_serial (char * str, int maxlen, int fd)
 {
-        int len = 0;
-        char buff[MX_ALLOC_LEN + 1] = {0};
+	int len = 0;
+	char buff[MX_ALLOC_LEN + 1] = {0};
 
 	if (fd < 0)
-                return 1;
+		return 1;
 
 	if (0 == do_inq(fd, 0, 1, 0x80, buff, MX_ALLOC_LEN, 0)) {
 		len = buff[3];
@@ -347,7 +344,7 @@
 		}
 		return 0;
 	}
-        return 1;
+	return 1;
 }
 
 static int
@@ -459,7 +456,7 @@
 
 	/*
 	 * host / bus / target / lun
-	 */	
+	 */
 	basename(parent->devpath, attr_path);
 	pp->sg_id.lun = 0;
 	sscanf(attr_path, "%i.%i.%x",
--- multipath-tools-0.4.8/libmultipath/dmparser.c
+++ multipath-tools-0.4.8/libmultipath/dmparser.c
@@ -59,7 +59,7 @@
 	minio = mp->minio;
 	p = mp->params;
 	freechar = sizeof(mp->params);
-	
+
 	shift = snprintf(p, freechar, "%s %s %i %i",
 			 mp->features, mp->hwhandler,
 			 VECTOR_SIZE(mp->pg), mp->bestpg);
@@ -70,7 +70,7 @@
 	}
 	p += shift;
 	freechar -= shift;
-	
+
 	vector_foreach_slot (mp->pg, pgp, i) {
 		pgp = VECTOR_SLOT(mp->pg, i);
 		shift = snprintf(p, freechar, " %s %i 1", mp->selector,
@@ -184,11 +184,11 @@
 	num_pg = atoi(word);
 	FREE(word);
 
-	if (num_pg > 0 && !mpp->pg) {
+	if (num_pg > 0 && !mpp->pg)
 		mpp->pg = vector_alloc();
-		if (!mpp->pg)
-			return 1;
-	}
+
+	if (!mpp->pg)
+		return 1;
 
 	/*
 	 * first pg to try
@@ -221,7 +221,7 @@
 				goto out;
 
 			num_pg_args = atoi(word);
-			
+
 			if (merge_words(&mpp->selector, word, 1)) {
 				FREE(word);
 				goto out1;
@@ -239,7 +239,7 @@
 		 * paths
 		 */
 		pgp = alloc_pathgroup();
-		
+
 		if (!pgp)
 			goto out;
 
--- multipath-tools-0.4.8/libmultipath/hwtable.c
+++ multipath-tools-0.4.8/libmultipath/hwtable.c
@@ -92,7 +92,7 @@
 	{
 		/* MSA 1000/MSA1500 EVA 3000/5000 with old firmware */
 		.vendor        = "(COMPAQ|HP)",
-		.product       = "(MSA|HSV)1.0.*",
+		.product       = "(MSA|HSV)1[01]0.*",
 		.getuid        = DEFAULT_GETUID,
 		.features      = "1 queue_if_no_path",
 		.hwhandler     = "1 hp-sw",
@@ -172,7 +172,7 @@
 		/* HP Smart Array */
 		.vendor        = "HP",
 		.product       = "LOGICAL VOLUME.*",
-		.getuid        = "/lib/udev/scsi_id -n -g -u -s /block/%n",
+		.getuid        = "/lib/udev/scsi_id -n -g -u /dev/%n",
 		.features      = DEFAULT_FEATURES,
 		.hwhandler     = DEFAULT_HWHANDLER,
 		.selector      = DEFAULT_SELECTOR,
@@ -214,7 +214,7 @@
 	{
 		.vendor        = "EMC",
 		.product       = "SYMMETRIX",
-		.getuid        = "/lib/udev/scsi_id -g -u -ppre-spc3-83 -s /block/%n",
+		.getuid        = "/lib/udev/scsi_id -g -u -ppre-spc3-83 /dev/%n",
 		.features      = DEFAULT_FEATURES,
 		.hwhandler     = DEFAULT_HWHANDLER,
 		.selector      = DEFAULT_SELECTOR,
@@ -533,7 +533,7 @@
 		.no_path_retry = NO_PATH_RETRY_UNDEF,
 		.minio         = 128,
 		.checker_name  = DIRECTIO,
-		.prio_name     = PRIO_NETAPP,
+		.prio_name     = PRIO_ONTAP,
 	},
 	/*
 	 * IBM NSeries (NETAPP) controller family
@@ -554,7 +554,7 @@
 		.no_path_retry = NO_PATH_RETRY_UNDEF,
 		.minio         = 128,
 		.checker_name  = DIRECTIO,
-		.prio_name     = PRIO_NETAPP,
+		.prio_name     = PRIO_ONTAP,
 	},
 	/*
 	 * Pillar Data controller family
--- multipath-tools-0.4.8/libmultipath/log.c
+++ multipath-tools-0.4.8/libmultipath/log.c
@@ -18,7 +18,7 @@
 static void dump_logarea (void)
 {
 	struct logmsg * msg;
-	
+
 	logdbg(stderr, "\n==== area: start addr = %p, end addr = %p ====\n",
 		la->start, la->end);
 	logdbg(stderr, "|addr     |next     |prio|msg\n");
@@ -34,12 +34,12 @@
 	logdbg(stderr, "\n\n");
 }
 #endif
-		
+
 static int logarea_init (int size)
 {
 	logdbg(stderr,"enter logarea_init\n");
 	la = (struct logarea *)MALLOC(sizeof(struct logarea));
-	
+
 	if (!la)
 		return 1;
 
@@ -107,7 +107,7 @@
 	lastmsg = (struct logmsg *)la->tail;
 
 	if (!la->empty) {
-		fwd = sizeof(struct logmsg) + 
+		fwd = sizeof(struct logmsg) +
 		      strlen((char *)&lastmsg->str) * sizeof(char) + 1;
 		la->tail += ALIGN(fwd, sizeof(void *));
 	}
@@ -118,11 +118,11 @@
 	/* not enough space on tail : rewind */
 	if (la->head <= la->tail && len > (la->end - la->tail)) {
 		logdbg(stderr, "enqueue: rewind tail to %p\n", la->tail);
-                if (la->head == la->start ) {
-                        logdbg(stderr, "enqueue: can not rewind tail, drop msg\n");
-                        la->tail = lastmsg;
-                        return 1;  /* can't reuse */
-                }
+		if (la->head == la->start ) {
+			logdbg(stderr, "enqueue: can not rewind tail, drop msg\n");
+			la->tail = lastmsg;
+			return 1;  /* can't reuse */
+		}
 		la->tail = la->start;
 
 		if (la->empty)
--- multipath-tools-0.4.8/libmultipath/log_pthread.c
+++ multipath-tools-0.4.8/libmultipath/log_pthread.c
@@ -53,17 +53,17 @@
 void log_thread_start (void)
 {
 	pthread_attr_t attr;
-	
+
 	logdbg(stderr,"enter log_thread_start\n");
 
 	logq_lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
 	logev_lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
 	logev_cond = (pthread_cond_t *) malloc(sizeof(pthread_cond_t));
-	
+
 	pthread_mutex_init(logq_lock, NULL);
 	pthread_mutex_init(logev_lock, NULL);
 	pthread_cond_init(logev_cond, NULL);
-	
+
 	pthread_attr_init(&attr);
 	pthread_attr_setstacksize(&attr, 64 * 1024);
 
@@ -90,5 +90,11 @@
 	pthread_mutex_destroy(logev_lock);
 	pthread_cond_destroy(logev_cond);
 
+	free(logq_lock);
+	logq_lock = NULL;
+	free(logev_lock);
+	logev_lock = NULL;
+	free(logev_cond);
+	logev_cond = NULL;
 	free_logarea();
-}	
+}
--- multipath-tools-0.4.8/libmultipath/parser.c
+++ multipath-tools-0.4.8/libmultipath/parser.c
@@ -1,11 +1,11 @@
-/* 
+/*
  * Part:        Configuration file parser/reader. Place into the dynamic
  *              data structure representation the conf file
- *  
+ *
  * Version:     $Id: parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
- * 
+ *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
- *              
+ *
  *              This program is distributed in the hope that it will be useful,
  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
  *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -43,7 +43,7 @@
 
 	if (!keyword)
 		return 1;
-	
+
 	if (!vector_alloc_slot(keywords)) {
 		FREE(keyword);
 		return 1;
@@ -450,7 +450,7 @@
 				break;
 			}
 		}
-		
+
 		free_strvec(strvec);
 	}
 
@@ -458,16 +458,23 @@
 	return r;
 }
 
+int alloc_keywords(void)
+{
+	if (!keywords)
+		keywords = vector_alloc();
+
+	if (!keywords)
+		return 1;
+
+	return 0;
+}
+
 /* Data initialization */
 int
 init_data(char *conf_file, void (*init_keywords) (void))
 {
 	int r;
 
-	if (!keywords)
-		keywords = vector_alloc();
-	if (!keywords)
-		return 1;
 	stream = fopen(conf_file, "r");
 	if (!stream) {
 		syslog(LOG_WARNING, "Configuration file open problem");
--- multipath-tools-0.4.8/libmultipath/parser.h
+++ multipath-tools-0.4.8/libmultipath/parser.h
@@ -74,6 +74,7 @@
 extern int alloc_value_block(vector strvec, void (*alloc_func) (vector));
 extern void *set_value(vector strvec);
 extern int process_stream(vector keywords);
+extern int alloc_keywords(void);
 extern int init_data(char *conf_file, void (*init_keywords) (void));
 extern struct keyword * find_keyword(vector v, char * name);
 void set_current_keywords (vector *k);
--- multipath-tools-0.4.8/libmultipath/pgpolicies.c
+++ multipath-tools-0.4.8/libmultipath/pgpolicies.c
@@ -67,7 +67,7 @@
 	struct path * pp;
 	struct pathgroup * pgp;
 	struct path * pp2;
-	
+
 	if (!mp->pg)
 		mp->pg = vector_alloc();
 
@@ -103,12 +103,12 @@
 		bitmap[i] = 1;
 
 		for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) {
-			
+
 			if (bitmap[j])
 				continue;
 
 			pp2 = VECTOR_SLOT(mp->paths, j);
-			
+
 			if (!strncmp(pp->tgt_node_name, pp2->tgt_node_name,
 					NODE_NAME_SIZE)) {
 				if (store_path(pgp->paths, pp2))
@@ -140,7 +140,7 @@
 	struct path * pp;
 	struct pathgroup * pgp;
 	struct path * pp2;
-	
+
 	if (!mp->pg)
 		mp->pg = vector_alloc();
 
@@ -172,16 +172,16 @@
 		/* feed the first path */
 		if (store_path(pgp->paths, pp))
 			goto out1;
-				
+
 		bitmap[i] = 1;
 
 		for (j = i + 1; j < VECTOR_SIZE(mp->paths); j++) {
-			
+
 			if (bitmap[j])
 				continue;
 
 			pp2 = VECTOR_SLOT(mp->paths, j);
-			
+
 			if (0 == strcmp(pp->serial, pp2->serial)) {
 				if (store_path(pgp->paths, pp2))
 					goto out1;
@@ -211,7 +211,7 @@
 
 	if (!mp->pg)
 		mp->pg = vector_alloc();
-	
+
 	if (!mp->pg)
 		return 1;
 
@@ -224,7 +224,7 @@
 
 		if (store_pathgroup(mp->pg, pgp))
 			goto out;
-		
+
 		if (store_path(pgp->paths, pp))
 			goto out;
 	}
@@ -252,10 +252,10 @@
 		return 1;
 
 	pgp = alloc_pathgroup();
-	
+
 	if (!pgp)
 		goto out;
-	
+
 	vector_free(pgp->paths);
 	pgp->paths = mp->paths;
 	mp->paths = NULL;
@@ -306,7 +306,7 @@
 
 		if (!pgp)
 			goto out;
-		
+
 		if (store_path(pgp->paths, VECTOR_SLOT(mp->paths, 0)))
 				goto out;
 
--- multipath-tools-0.4.8/libmultipath/print.c
+++ multipath-tools-0.4.8/libmultipath/print.c
@@ -29,7 +29,7 @@
 #define PAD(x)   while ((int)(c - s) < (x) && (c < (line + len - 1))) \
 			*c++ = ' '; s = c
 #define PRINT(var, size, format, args...)      \
-	         fwd = snprintf(var, size, format, ##args); \
+		fwd = snprintf(var, size, format, ##args); \
 		 c += (fwd >= size) ? size : fwd;
 
 /*
@@ -60,7 +60,7 @@
 	char fmt[6] = {};
 	char units[] = {'K','M','G','T','P'};
 	char *u = units;
-	
+
 	while (s >= 1024 && *u != 'P') {
 		s = s / 1024;
 		u++;
@@ -112,7 +112,7 @@
 	int j = PROGRESS_LEN - i;
 	char * c = buff;
 	char * end = buff + len;
-	
+
 	while (i-- > 0) {
 		c += snprintf(c, len, "X");
 		if ((len = (end - c)) <= 1) goto out;
@@ -129,7 +129,7 @@
 	buff[c - buff + 1] = '\0';
 	return (c - buff + 1);
 }
-	
+
 static int
 snprint_failback (char * buff, size_t len, struct multipath * mpp)
 {
@@ -239,7 +239,7 @@
 	if (!pp)
 		return 0;
 	return snprintf(buff, len, "%s,%s",
-		        pp->vendor_id, pp->product_id);
+			pp->vendor_id, pp->product_id);
 }
 
 static int
@@ -335,7 +335,7 @@
 snprint_vpr (char * buff, size_t len, struct path * pp)
 {
 	return snprintf(buff, len, "%s,%s",
-		        pp->vendor_id, pp->product_id);
+			pp->vendor_id, pp->product_id);
 }
 
 static int
@@ -530,10 +530,10 @@
 			continue;
 		}
 		f++;
-		
+
 		if (!(data = mpd_lookup(*f)))
 			break; /* unknown wildcard */
-		
+
 		PRINT(c, TAIL, data->header);
 		PAD(data->width);
 	} while (*f++);
@@ -565,10 +565,10 @@
 			continue;
 		}
 		f++;
-		
+
 		if (!(data = mpd_lookup(*f)))
 			break;
-		
+
 		data->snprint(buff, MAX_FIELD_LEN, mpp);
 		PRINT(c, TAIL, buff);
 		PAD(data->width);
@@ -600,10 +600,10 @@
 			continue;
 		}
 		f++;
-		
+
 		if (!(data = pd_lookup(*f)))
 			break; /* unknown wildcard */
-		
+
 		PRINT(c, TAIL, data->header);
 		PAD(data->width);
 	} while (*f++);
@@ -635,10 +635,10 @@
 			continue;
 		}
 		f++;
-		
+
 		if (!(data = pd_lookup(*f)))
 			break;
-		
+
 		data->snprint(buff, MAX_FIELD_LEN, pp);
 		PRINT(c, TAIL, buff);
 		PAD(data->width);
@@ -671,10 +671,10 @@
 			continue;
 		}
 		f++;
-		
+
 		if (!(data = pgd_lookup(*f)))
 			break;
-		
+
 		data->snprint(buff, MAX_FIELD_LEN, pgp);
 		PRINT(c, TAIL, buff);
 		PAD(data->width);
@@ -718,7 +718,7 @@
 			c += sprintf(c, "%%A: ");
 
 	c += sprintf(c, "%%n");
-	
+
 	if (strncmp(mpp->alias, mpp->wwid, WWID_SIZE))
 		c += sprintf(c, " (%%w)");
 
@@ -890,7 +890,6 @@
 	if (fwd > len)
 		return len;
 	return fwd;
-	
 }
 
 static int
@@ -956,7 +955,7 @@
 	if ((len - fwd - threshold) <= 0)
 		return len;
 	fwd += snprintf(buff + fwd, len - fwd, "device node rules:\n"
-			                       "- blacklist:\n");
+					       "- blacklist:\n");
 	if (!snprint_blacklist_group(buff, len, &fwd, &conf->blist_devnode))
 		return len;
 
@@ -969,7 +968,7 @@
 	if ((len - fwd - threshold) <= 0)
 		return len;
 	fwd += snprintf(buff + fwd, len - fwd, "wwid rules:\n"
-			                       "- blacklist:\n");
+					       "- blacklist:\n");
 	if (snprint_blacklist_group(buff, len, &fwd, &conf->blist_wwid) == 0)
 		return len;
 
@@ -982,7 +981,7 @@
 	if ((len - fwd - threshold) <= 0)
 		return len;
 	fwd += snprintf(buff + fwd, len - fwd, "device rules:\n"
-			                       "- blacklist:\n");
+					       "- blacklist:\n");
 	if (snprint_blacklist_devgroup(buff, len, &fwd, &conf->blist_device) == 0)
 		return len;
 
@@ -1258,7 +1257,7 @@
 			fprintf(stdout, "===== no paths =====\n");
 		return;
 	}
-	
+
 	if (banner)
 		fprintf(stdout, "===== paths list =====\n");
 
--- multipath-tools-0.4.8/libmultipath/prio.h
+++ multipath-tools-0.4.8/libmultipath/prio.h
@@ -21,6 +21,7 @@
 #define PRIO_HDS "hds"
 #define PRIO_HP_SW "hp_sw"
 #define PRIO_NETAPP "netapp"
+#define PRIO_ONTAP "ontap"
 #define PRIO_RANDOM "random"
 #define PRIO_RDAC "rdac"
 
--- multipath-tools-0.4.8/libmultipath/prioritizers/Makefile
+++ multipath-tools-0.4.8/libmultipath/prioritizers/Makefile
@@ -11,7 +11,7 @@
 	libprioemc.so \
 	libpriordac.so \
 	libprioalua.so \
-	libprionetapp.so \
+	libprioontap.so \
 	libpriohds.so
 
 CFLAGS += -I..
--- multipath-tools-0.4.8/libmultipath/prioritizers/alua.c
+++ multipath-tools-0.4.8/libmultipath/prioritizers/alua.c
@@ -23,6 +23,7 @@
 #define ALUA_PRIO_RTPG_FAILED			2
 #define ALUA_PRIO_GETAAS_FAILED			3
 #define ALUA_PRIO_TPGS_FAILED			4
+#define ALUA_PRIO_NO_INFORMATION		5
 
 int
 get_alua_info(int fd)
@@ -54,13 +55,18 @@
 		return -ALUA_PRIO_GETAAS_FAILED;
 
 	condlog(3, "aas = [%s]",
-		(aas_string[rc]) ? aas_string[rc] : "invalid/reserved");
+		(rc < 4) ? aas_string[rc] : "invalid/reserved");
 	return rc;
 }
 
 int getprio (struct path * pp)
 {
-	int rc = get_alua_info(pp->fd);
+	int rc;
+
+	if (pp->fd < 0)
+		return -ALUA_PRIO_NO_INFORMATION;
+
+	rc = get_alua_info(pp->fd);
 	if (rc >= 0) {
 		switch(rc) {
 			case AAS_OPTIMIZED:
--- multipath-tools-0.4.8/libmultipath/prioritizers/alua_rtpg.c
+++ multipath-tools-0.4.8/libmultipath/prioritizers/alua_rtpg.c
@@ -74,7 +74,7 @@
 scsi_error(struct sg_io_hdr *hdr)
 {
 	/* Treat SG_ERR here to get rid of sg_err.[ch] */
-        hdr->status &= 0x7e;
+	hdr->status &= 0x7e;
 
 	if (
 		(hdr->status == 0)        &&
@@ -125,18 +125,18 @@
 	set_uint16(cmd.length, resplen);
 	PRINT_HEX((unsigned char *) &cmd, sizeof(cmd));
 
-        memset(&hdr, 0, sizeof(hdr));
-        hdr.interface_id	= 'S';
-        hdr.cmdp		= (unsigned char *) &cmd;
-        hdr.cmd_len		= sizeof(cmd);
-        hdr.dxfer_direction	= SG_DXFER_FROM_DEV;
-        hdr.dxferp		= resp;
-        hdr.dxfer_len		= resplen;
-        hdr.sbp			= sense;
-        hdr.mx_sb_len		= sizeof(sense);
-        hdr.timeout		= DEF_TIMEOUT;
- 
-        if (ioctl(fd, SG_IO, &hdr) < 0) {
+	memset(&hdr, 0, sizeof(hdr));
+	hdr.interface_id	= 'S';
+	hdr.cmdp		= (unsigned char *) &cmd;
+	hdr.cmd_len		= sizeof(cmd);
+	hdr.dxfer_direction	= SG_DXFER_FROM_DEV;
+	hdr.dxferp		= resp;
+	hdr.dxfer_len		= resplen;
+	hdr.sbp			= sense;
+	hdr.mx_sb_len		= sizeof(sense);
+	hdr.timeout		= DEF_TIMEOUT;
+
+	if (ioctl(fd, SG_IO, &hdr) < 0) {
 		PRINT_DEBUG("do_inquiry: IOCTL failed!\n");
 		return -RTPG_INQUIRY_FAILED;
 	}
@@ -146,8 +146,8 @@
 		return -RTPG_INQUIRY_FAILED;
 	}
 	PRINT_HEX((unsigned char *) resp, resplen);
- 
-        return 0;
+
+	return 0;
 }
 
 /*
@@ -160,6 +160,7 @@
 	struct inquiry_data	inq;
 	int			rc;
 
+	memset((unsigned char *)&inq, 0, sizeof(inq));
 	rc = do_inquiry(fd, 0, 0x00, &inq, sizeof(inq));
 	if (!rc) {
 		rc = inquiry_data_get_tpgs(&inq);
@@ -176,6 +177,7 @@
 	struct vpd83_dscr *	dscr;
 	int			rc;
 
+	memset(buf, 0, sizeof(buf));
 	rc = do_inquiry(fd, 1, 0x83, buf, sizeof(buf));
 	if (!rc) {
 		vpd83 = (struct vpd83_data *) buf;
@@ -221,19 +223,19 @@
 	set_uint32(cmd.length, resplen);
 	PRINT_HEX((unsigned char *) &cmd, sizeof(cmd));
 
-        memset(&hdr, 0, sizeof(hdr));
+	memset(&hdr, 0, sizeof(hdr));
 	hdr.interface_id	= 'S';
-        hdr.cmdp		= (unsigned char *) &cmd;
-        hdr.cmd_len		= sizeof(cmd);
-        hdr.dxfer_direction	= SG_DXFER_FROM_DEV;
-        hdr.dxferp		= resp;
-        hdr.dxfer_len		= resplen;
-        hdr.mx_sb_len		= sizeof(sense);
-        hdr.sbp			= sense;
-        hdr.timeout		= DEF_TIMEOUT;
- 
+	hdr.cmdp		= (unsigned char *) &cmd;
+	hdr.cmd_len		= sizeof(cmd);
+	hdr.dxfer_direction	= SG_DXFER_FROM_DEV;
+	hdr.dxferp		= resp;
+	hdr.dxfer_len		= resplen;
+	hdr.mx_sb_len		= sizeof(sense);
+	hdr.sbp			= sense;
+	hdr.timeout		= DEF_TIMEOUT;
+
 	if (ioctl(fd, SG_IO, &hdr) < 0)
-                return -RTPG_RTPG_FAILED;
+		return -RTPG_RTPG_FAILED;
 
 	if (scsi_error(&hdr)) {
 		PRINT_DEBUG("do_rtpg: SCSI error!\n");
@@ -241,8 +243,8 @@
 	}
 	PRINT_HEX(resp, resplen);
 
-        return 0;
-} 
+	return 0;
+}
 
 int
 get_asymmetric_access_state(int fd, unsigned int tpg)
@@ -261,6 +263,7 @@
 			"%u bytes\n", buflen);
 		return -RTPG_RTPG_FAILED;
 	}
+	memset(buf, 0, buflen);
 	rc = do_rtpg(fd, buf, buflen);
 	if (rc < 0)
 		return rc;
@@ -274,11 +277,11 @@
 			return -RTPG_RTPG_FAILED;
 		}
 		buflen = scsi_buflen;
+		memset(buf, 0, buflen);
 		rc = do_rtpg(fd, buf, buflen);
 		if (rc < 0)
 			goto out;
 	}
-		
 
 	tpgd = (struct rtpg_data *) buf;
 	rc   = -RTPG_TPG_NOT_FOUND;
@@ -289,7 +292,7 @@
 					"more than one entry with same port "
 					"group.\n");
 			} else {
-				PRINT_DEBUG("pref=%i\n", dscr->pref);
+				PRINT_DEBUG("pref=%i\n", dscr->b0);
 				rc = rtpg_tpg_dscr_get_aas(dscr);
 			}
 		}
--- multipath-tools-0.4.8/libmultipath/prioritizers/hds.c
+++ multipath-tools-0.4.8/libmultipath/prioritizers/hds.c
@@ -86,7 +86,7 @@
 int hds_modular_prio (const char *dev, int fd)
 {
 	int k;
-	char vendor[8];
+	char vendor[9];
 	char product[32];
 	char serial[32];
 	char ldev[32];
--- multipath-tools-0.4.8/libmultipath/prioritizers/netapp.c
+++ multipath-tools-0.4.8/libmultipath/prioritizers/netapp.c
@@ -1,243 +0,0 @@
-/* 
- * Copyright 2005 Network Appliance, Inc., All Rights Reserved
- * Author:  David Wysochanski available at davidw@netapp.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License v2 for more details.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <assert.h>
-
-#include <sg_include.h>
-#include <debug.h>
-#include <prio.h>
-
-#define INQUIRY_CMD	0x12
-#define INQUIRY_CMDLEN	6
-#define DEFAULT_PRIOVAL	10
-#define RESULTS_MAX	256
-#define SG_TIMEOUT	30000
-
-#define pp_netapp_log(prio, fmt, args...) \
-        condlog(prio, "%s: netapp prio: " fmt, dev, ##args)
-
-static void dump_cdb(unsigned char *cdb, int size)
-{
-	int i;
-	char buf[10*5+1];
-	char * p = &buf[0];
-	
-	condlog(0, "- SCSI CDB: ");
-	for (i=0; i<size; i++) {
-		p += snprintf(p, 10*(size-i), "0x%02x ", cdb[i]);
-	}
-	condlog(0, "%s", buf);
-}
-
-static void process_sg_error(struct sg_io_hdr *io_hdr)
-{
-	int i;
-	char buf[128*5+1];
-	char * p = &buf[0];
-	
-	condlog(0, "- masked_status=0x%02x, host_status=0x%02x, "
-		"driver_status=0x%02x", io_hdr->masked_status,
-		io_hdr->host_status, io_hdr->driver_status);
-	if (io_hdr->sb_len_wr > 0) {
-		condlog(0, "- SCSI sense data: ");
-		for (i=0; i<io_hdr->sb_len_wr; i++) {
-			p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ",
-				      io_hdr->sbp[i]);
-		}
-		condlog(0, "%s", buf);
-	}
-}
-
-/*
- * Returns:
- * -1: error, errno set
- *  0: success
- */
-static int send_gva(const char *dev, int fd, unsigned char pg,
-		    unsigned char *results, int *results_size)
-{
-	unsigned char sb[128];
-	unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa,
-				 pg, sizeof(sb), 0, 0};
-	struct sg_io_hdr io_hdr;
-	int ret = -1;
-
-	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
-	io_hdr.interface_id = 'S';
-	io_hdr.cmd_len = sizeof (cdb);
-	io_hdr.mx_sb_len = sizeof (sb);
-	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
-	io_hdr.dxfer_len = *results_size;
-	io_hdr.dxferp = results;
-	io_hdr.cmdp = cdb;
-	io_hdr.sbp = sb;
-	io_hdr.timeout = SG_TIMEOUT;
-	io_hdr.pack_id = 0;
-	if (ioctl(fd, SG_IO, &io_hdr) < 0) {
-		pp_netapp_log(0, "SG_IO ioctl failed, errno=%d", errno);
-		dump_cdb(cdb, sizeof(cdb));
-		goto out;
-	}
-	if (io_hdr.info & SG_INFO_OK_MASK) {
-		pp_netapp_log(0, "SCSI error");
-		dump_cdb(cdb, sizeof(cdb));
-		process_sg_error(&io_hdr);
-		goto out;
-	}
-
-	if (results[4] != 0x0a || results[5] != 0x98 ||
-	    results[6] != 0x0a ||results[7] != 0x01) {
-		dump_cdb(cdb, sizeof(cdb));
-		pp_netapp_log(0, "GVA return wrong format ");
-		pp_netapp_log(0, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x",
-			results[4], results[5], results[6], results[7]);
-		goto out;
-	}
-	ret = 0;
- out:
-	return(ret);
-}
-
-/*
- * Retuns:
- * -1: Unable to obtain proxy info
- *  0: Device _not_ proxy path
- *  1: Device _is_ proxy path
- */
-static int get_proxy(const char *dev, int fd)
-{
-	unsigned char results[256];
-	unsigned char sb[128];
-	unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0,
-						   sizeof(sb), 0};
-	struct sg_io_hdr io_hdr;
-	int ret = -1;
-
-	memset(&results, 0, sizeof (results));
-	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
-	io_hdr.interface_id = 'S';
-	io_hdr.cmd_len = sizeof (cdb);
-	io_hdr.mx_sb_len = sizeof (sb);
-	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
-	io_hdr.dxfer_len = sizeof (results);
-	io_hdr.dxferp = results;
-	io_hdr.cmdp = cdb;
-	io_hdr.sbp = sb;
-	io_hdr.timeout = SG_TIMEOUT;
-	io_hdr.pack_id = 0;
-	if (ioctl(fd, SG_IO, &io_hdr) < 0) {
-		pp_netapp_log(0, "ioctl sending inquiry command failed, "
-			"errno=%d", errno);
-		dump_cdb(cdb, sizeof(cdb));
-		goto out;
-	}
-	if (io_hdr.info & SG_INFO_OK_MASK) {
-		pp_netapp_log(0, "SCSI error");
-		dump_cdb(cdb, sizeof(cdb));
-		process_sg_error(&io_hdr);
-		goto out;
-	}
-
-	if (results[1] != 0xc1 || results[8] != 0x0a ||
-	    results[9] != 0x98 || results[10] != 0x0a ||
-	    results[11] != 0x0 || results[12] != 0xc1 ||
-	    results[13] != 0x0) {
-		pp_netapp_log(0,"proxy info page in unknown format - ");
-		pp_netapp_log(0,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x "
-			"0x%02x 0x%02x",
-			results[8], results[9], results[10],
-			results[11], results[12], results[13]);
-		dump_cdb(cdb, sizeof(cdb));
-		goto out;
-	}
-	ret = (results[19] & 0x02) >> 1;
-
- out:
-	return(ret);
-}
-
-/*
- * Returns priority of device based on device info.
- *
- * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol
- * 3: iSCSI HBA
- * 2: iSCSI software
- * 1: FCP proxy
- */
-static int netapp_prio(const char *dev, int fd)
-{
-	unsigned char results[RESULTS_MAX];
-	int results_size=RESULTS_MAX;
-	int rc;
-	int is_proxy;
-	int is_iscsi_software;
-	int is_iscsi_hardware;
-	int tot_len;
-
-	is_iscsi_software = is_iscsi_hardware = is_proxy = 0;
-
-	memset(&results, 0, sizeof (results));
-	rc = send_gva(dev, fd, 0x41, results, &results_size);
-	if (rc == 0) {
-		tot_len = results[0] << 24 | results[1] << 16 |
-			  results[2] << 8 | results[3];
-		if (tot_len <= 8) {
-			goto try_fcp_proxy;
-		}
-		if (results[8] != 0x41) {
-			pp_netapp_log(0, "GVA page 0x41 error - "
-				"results[8] = 0x%x", results[8]);
-			goto try_fcp_proxy;
-		}
-		if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) ||
-		    (strncmp((char *)&results[12], "iswt", 4) == 0)) {
-			is_iscsi_software = 1;
-			goto prio_select;
-		}
-		else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) {
-			is_iscsi_hardware = 1;
-			goto prio_select;
-		}
-	}
-	
- try_fcp_proxy:	
-	rc = get_proxy(dev, fd);
-	if (rc >= 0) {
-		is_proxy = rc;
-	}
-
- prio_select:
-	if (is_iscsi_hardware) {
-		return 3;
-	} else if (is_iscsi_software) {
-		return 2;
-	} else {
-		if (is_proxy) {
-			return 1;
-		} else {
-			/* Either non-proxy, or couldn't get proxy info */
-			return 4;
-		}
-	}
-}
-
-int getprio (struct path * pp)
-{
-	return netapp_prio(pp->dev, pp->fd);
-}
--- multipath-tools-0.4.8/libmultipath/prioritizers/netapp.h
+++ multipath-tools-0.4.8/libmultipath/prioritizers/netapp.h
@@ -1,7 +0,0 @@
-#ifndef _NETAPP_H
-#define _NETAPP_H
-
-#define PRIO_NETAPP "netapp"
-int prio_netapp(struct path * pp);
-
-#endif
--- multipath-tools-0.4.8/libmultipath/prioritizers/ontap.c
+++ multipath-tools-0.4.8/libmultipath/prioritizers/ontap.c
@@ -0,0 +1,243 @@
+/* 
+ * Copyright 2005 Network Appliance, Inc., All Rights Reserved
+ * Author:  David Wysochanski available at davidw@netapp.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License v2 for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <sg_include.h>
+#include <debug.h>
+#include <prio.h>
+
+#define INQUIRY_CMD	0x12
+#define INQUIRY_CMDLEN	6
+#define DEFAULT_PRIOVAL	10
+#define RESULTS_MAX	256
+#define SG_TIMEOUT	30000
+
+#define pp_ontap_log(prio, fmt, args...) \
+	condlog(prio, "%s: ontap prio: " fmt, dev, ##args)
+
+static void dump_cdb(unsigned char *cdb, int size)
+{
+	int i;
+	char buf[10*5+1];
+	char * p = &buf[0];
+
+	condlog(0, "- SCSI CDB: ");
+	for (i=0; i<size; i++) {
+		p += snprintf(p, 10*(size-i), "0x%02x ", cdb[i]);
+	}
+	condlog(0, "%s", buf);
+}
+
+static void process_sg_error(struct sg_io_hdr *io_hdr)
+{
+	int i;
+	char buf[128*5+1];
+	char * p = &buf[0];
+
+	condlog(0, "- masked_status=0x%02x, host_status=0x%02x, "
+		"driver_status=0x%02x", io_hdr->masked_status,
+		io_hdr->host_status, io_hdr->driver_status);
+	if (io_hdr->sb_len_wr > 0) {
+		condlog(0, "- SCSI sense data: ");
+		for (i=0; i<io_hdr->sb_len_wr; i++) {
+			p += snprintf(p, 128*(io_hdr->sb_len_wr-i), "0x%02x ",
+				      io_hdr->sbp[i]);
+		}
+		condlog(0, "%s", buf);
+	}
+}
+
+/*
+ * Returns:
+ * -1: error, errno set
+ *  0: success
+ */
+static int send_gva(const char *dev, int fd, unsigned char pg,
+		    unsigned char *results, int *results_size)
+{
+	unsigned char sb[128];
+	unsigned char cdb[10] = {0xc0, 0, 0x1, 0xa, 0x98, 0xa,
+				 pg, sizeof(sb), 0, 0};
+	struct sg_io_hdr io_hdr;
+	int ret = -1;
+
+	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
+	io_hdr.interface_id = 'S';
+	io_hdr.cmd_len = sizeof (cdb);
+	io_hdr.mx_sb_len = sizeof (sb);
+	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+	io_hdr.dxfer_len = *results_size;
+	io_hdr.dxferp = results;
+	io_hdr.cmdp = cdb;
+	io_hdr.sbp = sb;
+	io_hdr.timeout = SG_TIMEOUT;
+	io_hdr.pack_id = 0;
+	if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+		pp_ontap_log(0, "SG_IO ioctl failed, errno=%d", errno);
+		dump_cdb(cdb, sizeof(cdb));
+		goto out;
+	}
+	if (io_hdr.info & SG_INFO_OK_MASK) {
+		pp_ontap_log(0, "SCSI error");
+		dump_cdb(cdb, sizeof(cdb));
+		process_sg_error(&io_hdr);
+		goto out;
+	}
+
+	if (results[4] != 0x0a || results[5] != 0x98 ||
+	    results[6] != 0x0a ||results[7] != 0x01) {
+		dump_cdb(cdb, sizeof(cdb));
+		pp_ontap_log(0, "GVA return wrong format ");
+		pp_ontap_log(0, "results[4-7] = 0x%02x 0x%02x 0x%02x 0x%02x",
+			results[4], results[5], results[6], results[7]);
+		goto out;
+	}
+	ret = 0;
+ out:
+	return(ret);
+}
+
+/*
+ * Retuns:
+ * -1: Unable to obtain proxy info
+ *  0: Device _not_ proxy path
+ *  1: Device _is_ proxy path
+ */
+static int get_proxy(const char *dev, int fd)
+{
+	unsigned char results[256];
+	unsigned char sb[128];
+	unsigned char cdb[INQUIRY_CMDLEN] = {INQUIRY_CMD, 1, 0xc1, 0,
+						   sizeof(sb), 0};
+	struct sg_io_hdr io_hdr;
+	int ret = -1;
+
+	memset(&results, 0, sizeof (results));
+	memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
+	io_hdr.interface_id = 'S';
+	io_hdr.cmd_len = sizeof (cdb);
+	io_hdr.mx_sb_len = sizeof (sb);
+	io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+	io_hdr.dxfer_len = sizeof (results);
+	io_hdr.dxferp = results;
+	io_hdr.cmdp = cdb;
+	io_hdr.sbp = sb;
+	io_hdr.timeout = SG_TIMEOUT;
+	io_hdr.pack_id = 0;
+	if (ioctl(fd, SG_IO, &io_hdr) < 0) {
+		pp_ontap_log(0, "ioctl sending inquiry command failed, "
+			"errno=%d", errno);
+		dump_cdb(cdb, sizeof(cdb));
+		goto out;
+	}
+	if (io_hdr.info & SG_INFO_OK_MASK) {
+		pp_ontap_log(0, "SCSI error");
+		dump_cdb(cdb, sizeof(cdb));
+		process_sg_error(&io_hdr);
+		goto out;
+	}
+
+	if (results[1] != 0xc1 || results[8] != 0x0a ||
+	    results[9] != 0x98 || results[10] != 0x0a ||
+	    results[11] != 0x0 || results[12] != 0xc1 ||
+	    results[13] != 0x0) {
+		pp_ontap_log(0,"proxy info page in unknown format - ");
+		pp_ontap_log(0,"results[8-13]=0x%02x 0x%02x 0x%02x 0x%02x "
+			"0x%02x 0x%02x",
+			results[8], results[9], results[10],
+			results[11], results[12], results[13]);
+		dump_cdb(cdb, sizeof(cdb));
+		goto out;
+	}
+	ret = (results[19] & 0x02) >> 1;
+
+ out:
+	return(ret);
+}
+
+/*
+ * Returns priority of device based on device info.
+ *
+ * 4: FCP non-proxy, FCP proxy unknown, or unable to determine protocol
+ * 3: iSCSI HBA
+ * 2: iSCSI software
+ * 1: FCP proxy
+ */
+static int ontap_prio(const char *dev, int fd)
+{
+	unsigned char results[RESULTS_MAX];
+	int results_size=RESULTS_MAX;
+	int rc;
+	int is_proxy;
+	int is_iscsi_software;
+	int is_iscsi_hardware;
+	int tot_len;
+
+	is_iscsi_software = is_iscsi_hardware = is_proxy = 0;
+
+	memset(&results, 0, sizeof (results));
+	rc = send_gva(dev, fd, 0x41, results, &results_size);
+	if (rc == 0) {
+		tot_len = results[0] << 24 | results[1] << 16 |
+			  results[2] << 8 | results[3];
+		if (tot_len <= 8) {
+			goto try_fcp_proxy;
+		}
+		if (results[8] != 0x41) {
+			pp_ontap_log(0, "GVA page 0x41 error - "
+				"results[8] = 0x%x", results[8]);
+			goto try_fcp_proxy;
+		}
+		if ((strncmp((char *)&results[12], "ism_sw", 6) == 0) ||
+		    (strncmp((char *)&results[12], "iswt", 4) == 0)) {
+			is_iscsi_software = 1;
+			goto prio_select;
+		}
+		else if (strncmp((char *)&results[12], "ism_sn", 6) == 0) {
+			is_iscsi_hardware = 1;
+			goto prio_select;
+		}
+	}
+
+ try_fcp_proxy:
+	rc = get_proxy(dev, fd);
+	if (rc >= 0) {
+		is_proxy = rc;
+	}
+
+ prio_select:
+	if (is_iscsi_hardware) {
+		return 3;
+	} else if (is_iscsi_software) {
+		return 2;
+	} else {
+		if (is_proxy) {
+			return 1;
+		} else {
+			/* Either non-proxy, or couldn't get proxy info */
+			return 4;
+		}
+	}
+}
+
+int getprio (struct path * pp)
+{
+	return ontap_prio(pp->dev, pp->fd);
+}
--- multipath-tools-0.4.8/libmultipath/prioritizers/ontap.h
+++ multipath-tools-0.4.8/libmultipath/prioritizers/ontap.h
@@ -0,0 +1,7 @@
+#ifndef _ONTAP_H
+#define _ONTAP_H
+
+#define PRIO_ONTAP "ontap"
+int prio_ontap(struct path * pp);
+
+#endif
--- multipath-tools-0.4.8/libmultipath/prioritizers/rdac.c
+++ multipath-tools-0.4.8/libmultipath/prioritizers/rdac.c
@@ -39,9 +39,9 @@
 		pp_rdac_log(0, "inquiry command indicates error");
 		goto out;
 	}
-	
+
 	if (/* Verify the code page - right page & page identifier */
-	    sense_buffer[1] != 0xc9 || 
+	    sense_buffer[1] != 0xc9 ||
 	    sense_buffer[3] != 0x2c ||
 	    sense_buffer[4] != 'v' ||
 	    sense_buffer[5] != 'a' ||
@@ -49,24 +49,24 @@
 		pp_rdac_log(0, "volume access control page in unknown format");
 		goto out;
 	}
-	
+
 	if ( /* Current Volume Path Bit */
 		( sense_buffer[8] & 0x01) == 0x01 ) {
-		/* 
+		/*
 		 * This volume was owned by the controller receiving
 		 * the inquiry command.
 		 */
-		ret |= 0x01;
+		ret |= 0x02;
 	}
 
 	/* Volume Preferred Path Priority */
 	switch ( sense_buffer[9] & 0x0F ) {
 	case 0x01:
-		/* 
+		/*
 		 * Access to this volume is most preferred through
 		 * this path and other paths with this value.
 		 */
-		ret |= 0x02;
+		ret |= 0x04;
 		break;
 	case 0x02:
 		/*
@@ -74,12 +74,13 @@
 		 * as a secondary path. Typically this path would be used
 		 * for fail-over situations.
 		 */
-		/* Fallthrough */
+		ret |= 0x01;
+		break;
 	default:
 		/* Reserved values */
 		break;
 	}
-	
+
 out:
 	return(ret);
 }
--- multipath-tools-0.4.8/libmultipath/regex.c
+++ multipath-tools-0.4.8/libmultipath/regex.c
@@ -116,7 +116,7 @@
 /* True if `size1' is non-NULL and PTR is pointing anywhere inside
    `string1' or just past its end.  This works if PTR is NULL, which is
    a good thing.  */
-#define FIRST_STRING_P(ptr) 						\
+#define FIRST_STRING_P(ptr)						\
 	(size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
 
 /* (Re)Allocate N items of type T using malloc, or fail.  */
@@ -188,7 +188,7 @@
 #define EXTRACT_NUMBER_AND_INCR(destination, source)			\
   do {									\
     EXTRACT_NUMBER (destination, source);				\
-    (source) += 2; 							\
+    (source) += 2;							\
   } while (0)
 
 #undef assert
@@ -267,14 +267,14 @@
 #define PATFETCH(c)							\
   do {if (p == pend) return REG_EEND;					\
     c = (unsigned char) *p++;						\
-    if (translate) c = translate[c]; 					\
+    if (translate) c = translate[c];					\
   } while (0)
 
 /* Fetch the next character in the uncompiled pattern, with no
    translation.  */
 #define PATFETCH_RAW(c)							\
   do {if (p == pend) return REG_EEND;					\
-    c = (unsigned char) *p++; 						\
+    c = (unsigned char) *p++;						\
   } while (0)
 
 /* Go backwards one character in the pattern.  */
@@ -354,27 +354,27 @@
    correct places in the new one.  If extending the buffer results in it
    being larger than MAX_BUF_SIZE, then flag memory exhausted.  */
 #define EXTEND_BUFFER()							\
-  do { 									\
+  do {									\
     unsigned char *old_buffer = bufp->buffer;				\
-    if (bufp->allocated == MAX_BUF_SIZE) 				\
+    if (bufp->allocated == MAX_BUF_SIZE)				\
       return REG_ESIZE;							\
     bufp->allocated <<= 1;						\
     if (bufp->allocated > MAX_BUF_SIZE)					\
-      bufp->allocated = MAX_BUF_SIZE; 					\
+      bufp->allocated = MAX_BUF_SIZE;					\
     bufp->buffer = (unsigned char *) REALLOC(bufp->buffer, bufp->allocated);\
     if (bufp->buffer == NULL)						\
       return REG_ESPACE;						\
     /* If the buffer moved, move all the pointers into it.  */		\
     if (old_buffer != bufp->buffer)					\
       {									\
-        b = (b - old_buffer) + bufp->buffer;				\
-        begalt = (begalt - old_buffer) + bufp->buffer;			\
-        if (fixup_alt_jump)						\
-          fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
-        if (laststart)							\
-          laststart = (laststart - old_buffer) + bufp->buffer;		\
-        if (pending_exact)						\
-          pending_exact = (pending_exact - old_buffer) + bufp->buffer;	\
+	b = (b - old_buffer) + bufp->buffer;				\
+	begalt = (begalt - old_buffer) + bufp->buffer;			\
+	if (fixup_alt_jump)						\
+	  fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
+	if (laststart)							\
+	  laststart = (laststart - old_buffer) + bufp->buffer;		\
+	if (pending_exact)						\
+	  pending_exact = (pending_exact - old_buffer) + bufp->buffer;	\
       }									\
   } while (0)
 
@@ -428,20 +428,20 @@
 
 
 /* Get the next unsigned number in the uncompiled pattern.  */
-#define GET_UNSIGNED_NUMBER(num) 					\
+#define GET_UNSIGNED_NUMBER(num)					\
   { if (p != pend)							\
      {									\
-       PATFETCH (c); 							\
-       while (ISDIGIT (c)) 						\
-         { 								\
-           if (num < 0)							\
-              num = 0;							\
-           num = num * 10 + c - '0'; 					\
-           if (p == pend) 						\
-              break; 							\
-           PATFETCH (c);						\
-         } 								\
-       } 								\
+       PATFETCH (c);							\
+       while (ISDIGIT (c))						\
+	 {								\
+	   if (num < 0)							\
+	      num = 0;							\
+	   num = num * 10 + c - '0';					\
+	   if (p == pend)						\
+	      break;							\
+	   PATFETCH (c);						\
+	 }								\
+       }								\
     }
 
 #define CHAR_CLASS_MAX_LENGTH  6	/* Namely, `xdigit'.  */
@@ -1524,14 +1524,14 @@
   ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS		\
    ? 0									\
    : ((fail_stack).stack = (fail_stack_elt_t *)				\
-        REGEX_REALLOCATE ((fail_stack).stack, 				\
-          (fail_stack).size * sizeof (fail_stack_elt_t),		\
-          ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)),	\
+	REGEX_REALLOCATE ((fail_stack).stack,				\
+	  (fail_stack).size * sizeof (fail_stack_elt_t),		\
+	  ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)),	\
 									\
       (fail_stack).stack == NULL					\
       ? 0								\
-      : ((fail_stack).size <<= 1, 					\
-         1)))
+      : ((fail_stack).size <<= 1,					\
+	 1)))
 
 
 /* Push PATTERN_OP on FAIL_STACK.
@@ -1577,7 +1577,7 @@
        is wide enough to hold a value of something to which pointer can \
        be assigned */							\
     s_reg_t this_reg;							\
-    									\
+									\
     DEBUG_STATEMENT (failure_id++);					\
     DEBUG_STATEMENT (nfailure_points_pushed++);				\
     DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);		\
@@ -1663,7 +1663,7 @@
 
 /* We actually push this many items.  */
 #define NUM_FAILURE_ITEMS						\
-  ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS 	\
+  ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS		\
     + NUM_NONREG_ITEMS)
 
 /* How many items can still be added to the stack without overflowing it.  */
@@ -2255,13 +2255,13 @@
 /* Call before fetching a character with *d.  This switches over to
    string2 if necessary.  */
 #define PREFETCH()							\
-  while (d == dend)						    	\
+  while (d == dend)							\
     {									\
       /* End of string2 => fail.  */					\
-      if (dend == end_match_2) 						\
-        goto fail;							\
-      /* End of string1 => advance to string2.  */ 			\
-      d = string2;						        \
+      if (dend == end_match_2)						\
+	goto fail;							\
+      /* End of string1 => advance to string2.  */			\
+      d = string2;							\
       dend = end_match_2;						\
     }
 
@@ -2278,7 +2278,7 @@
    string2, look at the last character in string1.  */
 #define WORDCHAR_P(d)							\
   (SYNTAX ((d) == end1 ? *string2					\
-           : (d) == string2 - 1 ? *(end1 - 1) : *(d))			\
+	   : (d) == string2 - 1 ? *(end1 - 1) : *(d))			\
    == Sword)
 
 /* Test if the character before D and the one at D differ with respect
--- multipath-tools-0.4.8/libmultipath/structs.c
+++ multipath-tools-0.4.8/libmultipath/structs.c
@@ -22,7 +22,7 @@
 alloc_path (void)
 {
 	struct path * pp;
-	
+
 	pp = (struct path *)MALLOC(sizeof(struct path));
 
 	if (pp) {
@@ -243,7 +243,7 @@
 {
 	int i;
 	struct multipath * mpp;
-	
+
 	if (!mpvec)
 		return NULL;
 
@@ -262,7 +262,7 @@
 {
 	int i;
 	struct multipath * mpp;
-	
+
 	if (!mpvec)
 		return NULL;
 
@@ -279,7 +279,7 @@
 	int i;
 	int len;
 	struct multipath * mpp;
-	
+
 	if (!mpvec)
 		return NULL;
 
@@ -287,7 +287,7 @@
 
 	if (!len)
 		return NULL;
-	
+
 	vector_foreach_slot (mpvec, mpp, i) {
 		if (strlen(mpp->alias) == len &&
 		    !strncmp(mpp->alias, alias, len))
@@ -315,7 +315,7 @@
 
 	if (!pathvec)
 		return NULL;
-	
+
 	vector_foreach_slot (pathvec, pp, i)
 		if (!strcmp_chomp(pp->dev, dev))
 			return pp;
--- multipath-tools-0.4.8/libmultipath/structs_vec.c
+++ multipath-tools-0.4.8/libmultipath/structs_vec.c
@@ -280,13 +280,13 @@
 retry:
 	if (dm_get_info(mpp->alias, &mpp->dmi)) {
 		/* Error accessing table */
-		condlog(3, "%s: cannot access table", mpp->alias); 
+		condlog(3, "%s: cannot access table", mpp->alias);
 		goto out;
 	}
 
 	if (!dm_map_present(mpp->alias)) {
 		/* Table has been removed */
-		condlog(3, "%s: table does not exist", mpp->alias); 
+		condlog(3, "%s: table does not exist", mpp->alias);
 		goto out;
 	}
 
--- multipath-tools-0.4.8/libmultipath/switchgroup.c
+++ multipath-tools-0.4.8/libmultipath/switchgroup.c
@@ -35,7 +35,7 @@
 
 	if (!mpp->pg)
 		return 1;
-	
+
 	vector_foreach_slot (mpp->pg, pgp, i) {
 		if (!pgp->paths)
 			continue;
--- multipath-tools-0.4.8/libmultipath/uevent.c
+++ multipath-tools-0.4.8/libmultipath/uevent.c
@@ -157,7 +157,7 @@
 		}
 
 		/* enable receiving of the sender credentials */
-		setsockopt(sock, SOL_SOCKET, SO_PASSCRED, 
+		setsockopt(sock, SOL_SOCKET, SO_PASSCRED,
 			   &feature_on, sizeof(feature_on));
 
 	} else {
--- multipath-tools-0.4.8/libmultipath/util.c
+++ multipath-tools-0.4.8/libmultipath/util.c
@@ -14,7 +14,7 @@
 {
 	int i;
 	char s1[PARAMS_SIZE],s2[PARAMS_SIZE];
- 
+
 	if(!str1 || !str2)
 		return 1;
 
@@ -67,7 +67,7 @@
 	char * p;
 	int len;
 	int skip = 0;
-	
+
 	if (word)
 		*word = NULL;
 
--- multipath-tools-0.4.8/libmultipath/uxsock.c
+++ multipath-tools-0.4.8/libmultipath/uxsock.c
@@ -26,17 +26,17 @@
 int ux_socket_connect(const char *name)
 {
 	int fd;
-        struct sockaddr_un addr;
+	struct sockaddr_un addr;
 
-        memset(&addr, 0, sizeof(addr));
-        addr.sun_family = AF_UNIX;
-        strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	strncpy(addr.sun_path, name, sizeof(addr.sun_path));
 
 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
 	if (fd == -1) {
 		return -1;
 	}
-	
+
 	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
 		close(fd);
 		return -1;
@@ -47,12 +47,13 @@
 
 /*
  * create a unix domain socket and start listening on it
- * return a file descriptor open on the socket 
+ * return a file descriptor open on the socket
  */
 int ux_socket_listen(const char *name)
 {
 	int fd;
-        struct sockaddr_un addr;
+	struct sockaddr_un addr;
+
 
 	/* get rid of any old socket */
 	unlink(name);
@@ -60,16 +61,16 @@
 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
 	if (fd == -1) return -1;
 
-        memset(&addr, 0, sizeof(addr));
-        addr.sun_family = AF_UNIX;
-        strncpy(addr.sun_path, name, sizeof(addr.sun_path));
+	memset(&addr, 0, sizeof(addr));
+	addr.sun_family = AF_UNIX;
+	strncpy(addr.sun_path, name, sizeof(addr.sun_path));
 
-        if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
+	if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
 		close(fd);
 		return -1;
-	}	
+	}
 
-        if (listen(fd, 10) == -1) {
+	if (listen(fd, 10) == -1) {
 		close(fd);
 		return -1;
 	}
--- multipath-tools-0.4.8/libmultipath/vector.c
+++ multipath-tools-0.4.8/libmultipath/vector.c
@@ -1,10 +1,10 @@
-/* 
+/*
  * Part:        Vector structure manipulation.
- *  
+ *
  * Version:     $Id: vector.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
- * 
+ *
  * Author:      Alexandre Cassen, <acassen@linux-vs.org>
- *              
+ *
  *              This program is distributed in the hope that it will be useful,
  *              but WITHOUT ANY WARRANTY; without even the implied warranty of
  *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -23,7 +23,7 @@
 #include <stdlib.h>
 #include "vector.h"
 
-/* 
+/*
  * Initialize vector struct.
  * allocated 'size' slot elements then return vector.
  */
@@ -54,7 +54,7 @@
 vector_insert_slot(vector v, int slot, void *value)
 {
 	int i;
-	
+
 	if (!vector_alloc_slot(v))
 		return NULL;
 
--- multipath-tools-0.4.8/libmultipath/waiter.c
+++ multipath-tools-0.4.8/libmultipath/waiter.c
@@ -58,7 +58,7 @@
 void stop_waiter_thread (struct multipath *mpp, struct vectors *vecs)
 {
 	struct event_thread *wp = (struct event_thread *)mpp->waiter;
-	
+
 	if (!wp) {
 		condlog(3, "%s: no waiter thread", mpp->alias);
 		return;
@@ -113,7 +113,7 @@
 	}
 
 	dm_task_no_open_count(waiter->dmt);
-	
+
 	/* accept wait interruption */
 	set = unblock_signals();
 
@@ -154,7 +154,7 @@
 		lock_cleanup_pop(waiter->vecs->lock);
 
 		if (r) {
-			condlog(2, "%s: event checker exit", 
+			condlog(2, "%s: event checker exit",
 				waiter->mapname);
 			return -1; /* stop the thread */
 		}
--- multipath-tools-0.4.8/multipath.conf.annotated
+++ multipath-tools-0.4.8/multipath.conf.annotated
@@ -134,6 +134,15 @@
 #	# default : no
 #	user_friendly_names no
 #
+#	#
+#	# name    : bindings_file
+#	# scope   : multipath
+#	# desc    : The location of the bindings file that is used with
+#	#           the user_friendly_names option.
+#	# values  : <full_pathname>
+#	# default : "/var/lib/multipath/bindings"
+#	bindings_file "/etc/multipath_bindings"
+#
 #}
 #	
 ##
--- multipath-tools-0.4.8/multipath/Makefile
+++ multipath-tools-0.4.8/multipath/Makefile
@@ -16,24 +16,27 @@
 
 $(EXEC): $(OBJS)
 	$(CC) $(CFLAGS) $(OBJS) -o $(EXEC) $(LDFLAGS)
-	$(GZIP) $(EXEC).8 > $(EXEC).8.gz
-	$(GZIP) $(EXEC).conf.5 > $(EXEC).conf.5.gz
 
 install:
 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
-	$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)/
+	$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
+	$(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir)
+	$(INSTALL_PROGRAM) -m 755 multipath.init.suse $(DESTDIR)$(rcdir)/boot.multipath
 	$(INSTALL_PROGRAM) -d $(DESTDIR)/etc/udev/rules.d
-	$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/
+	$(INSTALL_PROGRAM) -m 644 multipath.rules $(DESTDIR)/etc/udev/rules.d/71-multipath.rules
 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
-	$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
+	$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)
 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(man5dir)
-	$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5.gz $(DESTDIR)$(man5dir)
+	$(INSTALL_PROGRAM) -m 644 $(EXEC).conf.5 $(DESTDIR)$(man5dir)
+	$(INSTALL_PROGRAM) -d $(DESTDIR)/lib/mkinitrd/scripts
+	$(INSTALL_PROGRAM) -m 755 boot-multipath.sh $(DESTDIR)/lib/mkinitrd/scripts
+	$(INSTALL_PROGRAM) -m 755 setup-multipath.sh $(DESTDIR)/lib/mkinitrd/scripts
 
 uninstall:
 	rm $(DESTDIR)/etc/udev/rules.d/multipath.rules
 	rm $(DESTDIR)$(bindir)/$(EXEC)
-	rm $(DESTDIR)$(mandir)/$(EXEC).8.gz
-	rm $(DESTDIR)$(man5dir)/$(EXEC).conf.5.gz
+	rm -f $(DESTDIR)/lib/mkinitrd/scripts/boot-multipath.sh
+	rm -f $(DESTDIR)/lib/mkinitrd/scripts/setup-multipath.sh
 
 clean:
-	rm -f core *.o $(EXEC) *.gz
+	rm -f core *.o $(EXEC)
--- multipath-tools-0.4.8/multipath/boot-multipath.sh
+++ multipath-tools-0.4.8/multipath/boot-multipath.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+#%stage: block
+#%depends: dm
+#%provides: dmroot
+#%programs: /sbin/multipath /lib/multipath/*
+#%if: "$root_mpath"
+#%modules: dm-multipath dm-round-robin dm-emc dm-hp_sw dm-rdac
+#
+##### Multipath
+##
+## If the root device can be accessed using multiple device paths, 
+## this initializes and waits for them
+##
+## Command line parameters
+## -----------------------
+##
+## root_mpath=1		use multipath
+## mpath_status=off	do not use multipath
+## 
+
+load_modules
+
+# check for multipath parameter in /proc/cmdline
+mpath_status=$(get_param multipath)
+
+mpath_list=$(sed -n '/multipath/p' /proc/modules)
+if [ -z "$mpath_list" ] ; then
+  mpath_status=off
+fi
+if [ "$mpath_status" != "off" ] ; then
+  # We are waiting for a device-mapper device
+  root_major=$(sed -n 's/\(.*\) device-mapper/\1/p' /proc/devices)
+  # Rescan for multipath
+  echo -n "Setup multipath devices: "
+  /sbin/multipath -v0
+  wait_for_events
+  echo 'ok.'
+fi
+
--- multipath-tools-0.4.8/multipath/main.c
+++ multipath-tools-0.4.8/multipath/main.c
@@ -79,6 +79,7 @@
 	fprintf (stderr, "  %s [-d] [-r] [-v lvl] [-p pol] [-b fil] [dev]\n", progname);
 	fprintf (stderr, "  %s -l|-ll|-f [-v lvl] [-b fil] [dev]\n", progname);
 	fprintf (stderr, "  %s -F [-v lvl]\n", progname);
+	fprintf (stderr, "  %s -t\n", progname);
 	fprintf (stderr, "  %s -h\n", progname);
 	fprintf (stderr,
 		"\n"
@@ -89,6 +90,7 @@
 		"  -f      flush a multipath device map\n" \
 		"  -F      flush all multipath device maps\n" \
 		"  -d      dry run, do not create or update devmaps\n" \
+		"  -t      dump internal hardware table\n" \
 		"  -r      force devmap reload\n" \
 		"  -p      policy failover|multibus|group_by_serial|group_by_prio\n" \
 		"  -b fil  bindings file location\n" \
@@ -241,14 +243,14 @@
 		else
 			dev = conf->dev;
 	}
-	
+
 	/*
 	 * if we have a blacklisted device parameter, exit early
 	 */
-	if (dev && 
+	if (dev &&
 	    (filter_devnode(conf->blist_devnode, conf->elist_devnode, dev) > 0))
 			goto out;
-	
+
 	/*
 	 * scope limiting must be translated into a wwid
 	 * failing the translation is fatal (by policy)
@@ -315,6 +317,55 @@
 	return r;
 }
 
+static int
+dump_config (void)
+{
+	char * c;
+	char * reply;
+	unsigned int maxlen = 256;
+	int again = 1;
+
+	reply = MALLOC(maxlen);
+
+	while (again) {
+		if (!reply)
+			return 1;
+		c = reply;
+		c += snprint_defaults(c, reply + maxlen - c);
+		again = ((c - reply) == maxlen);
+		if (again) {
+			reply = REALLOC(reply, maxlen *= 2);
+			continue;
+		}
+		c += snprint_blacklist(c, reply + maxlen - c);
+		again = ((c - reply) == maxlen);
+		if (again) {
+			reply = REALLOC(reply, maxlen *= 2);
+			continue;
+		}
+		c += snprint_blacklist_except(c, reply + maxlen - c);
+		again = ((c - reply) == maxlen);
+		if (again) {
+			reply = REALLOC(reply, maxlen *= 2);
+			continue;
+		}
+		c += snprint_hwtable(c, reply + maxlen - c, conf->hwtable);
+		again = ((c - reply) == maxlen);
+		if (again) {
+			reply = REALLOC(reply, maxlen *= 2);
+			continue;
+		}
+		c += snprint_mptable(c, reply + maxlen - c, conf->mptable);
+		again = ((c - reply) == maxlen);
+		if (again)
+			reply = REALLOC(reply, maxlen *= 2);
+	}
+
+	printf("%s", reply);
+	FREE(reply);
+	return 0;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -346,7 +397,7 @@
 		condlog(0, "multipath tools need sysfs mounted");
 		exit(1);
 	}
-	while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:r")) != EOF ) {
+	while ((arg = getopt(argc, argv, ":dhl::FfM:v:p:b:rt")) != EOF ) {
 		switch(arg) {
 		case 1: printf("optarg : %s\n",optarg);
 			break;
@@ -387,16 +438,19 @@
 			if (conf->pgpolicy_flag == -1) {
 				printf("'%s' is not a valid policy\n", optarg);
 				usage(argv[0]);
-			}                
+			}
 			break;
 		case 'r':
 			conf->force_reload = 1;
 			break;
+		case 't':
+			dump_config();
+			goto out;
 		case 'h':
 			usage(argv[0]);
 		case ':':
 			fprintf(stderr, "Missing option arguement\n");
-			usage(argv[0]);        
+			usage(argv[0]);
 		case '?':
 			fprintf(stderr, "Unknown switch: %s\n", optarg);
 			usage(argv[0]);
--- multipath-tools-0.4.8/multipath/multipath.8
+++ multipath-tools-0.4.8/multipath/multipath.8
@@ -6,7 +6,7 @@
 .RB [\| \-v\ \c
 .IR verbosity \|]
 .RB [\| \-d \|]
-.RB [\| \-h | \-l | \-ll | \-f | \-F \|]
+.RB [\| \-h | \-l | \-ll | \-f | \-t | \-F \|]
 .RB [\| \-p\ \c
 .BR failover | multibus | group_by_serial | group_by_prio | group_by_node_name \|]
 .RB [\| device \|]
@@ -47,6 +47,9 @@
 .B \-F
 flush all unused multipath device maps
 .TP
+.B \-t
+print internal hardware table to stdout
+.TP
 .BI \-p " policy"
 force maps to specified policy:
 .RS 1.2i
@@ -76,6 +79,9 @@
 .I device
 may alternatively be a multipath mapname
 .SH "SEE ALSO"
+.BR multipathd (8),
+.BR multipath.conf (5),
+.BR kpartx (8),
 .BR udev (8),
 .BR dmsetup (8)
 .BR hotplug (8)
--- multipath-tools-0.4.8/multipath/multipath.conf.5
+++ multipath-tools-0.4.8/multipath/multipath.conf.5
@@ -147,13 +147,24 @@
 .RE
 .TP
 .B features
-Specify any device-mapper features to be used. The most common of
-these features is
-.I "1 queue_if_no_path" 
-Note that this can also be set via the
+Specify any device-mapper features to be used. Syntax is
+.I num list
+where
+.I num
+is the number of features in
+.I list.
+Possible values for the feature list are
+.RS
+.TP 12
+.B queue_if_no_path
+Queue IO if no path is active; identical to the
 .I no_path_retry
 keyword.
 .TP
+.B no_partitions
+Disable automatic partitions generation via kpartx.
+.RE
+.TP
 .B path_checker
 The default method used to determine the paths' state. Possible values
 are
@@ -225,6 +236,10 @@
 be overriden by any specific aliases in the \fImultipaths\fR section.
 Default is
 .I no
+.TP
+.B bindings_file
+The full pathname of the binding file to be used when the user_friendly_names option is set. Defaults to
+.I /var/lib/multipath/bindings
 .
 .SH "blacklist section"
 The
--- multipath-tools-0.4.8/multipath/multipath.init.suse
+++ multipath-tools-0.4.8/multipath/multipath.init.suse
@@ -0,0 +1,137 @@
+#! /bin/sh
+# Copyright (c) 2005 SuSE GmbH Nuernberg, Germany.
+#
+# Author: Hannes Reinecke <feedback@suse.de>
+#
+# init.d/boot.multipath
+#
+### BEGIN INIT INFO
+# Provides:          boot.multipath
+# Required-Start:    boot.device-mapper boot.udev
+# Required-Stop:     boot.device-mapper boot.udev
+# Default-Start:     B
+# Default-Stop:
+# Short-Description:       Create multipath device targets
+# Description:       Setup initial multipath device-mapper targets
+### END INIT INFO
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+PROGRAM=/sbin/multipath
+
+# Set the maximum number of open files
+MAX_OPEN_FDS=4096
+
+test -x $PROGRAM || exit 5
+
+# Shell functions sourced from /etc/rc.status:
+#      rc_check         check and set local and overall rc status
+#      rc_status        check and set local and overall rc status
+#      rc_status -v     ditto but be verbose in local rc status
+#      rc_status -v -r  ditto and clear the local rc status
+#      rc_failed        set local and overall rc status to failed
+#      rc_reset         clear local rc status (overall remains)
+#      rc_exit          exit appropriate to overall rc status
+. /etc/rc.status
+
+# First reset status of this service
+rc_reset
+
+# Return values acc. to LSB for all commands but status:
+# 0 - success
+# 1 - misc error
+# 2 - invalid or excess args
+# 3 - unimplemented feature (e.g. reload)
+# 4 - insufficient privilege
+# 5 - program not installed
+# 6 - program not configured
+# 7 - program is not running
+# 
+# Note that starting an already running service, stopping
+# or restarting a not-running service as well as the restart
+# with force-reload (in case signalling is not supported) are
+# considered a success.
+
+case "$1" in
+    start)
+	echo -n "Creating multipath targets:"
+	# Check whether multipath daemon is already running
+	if /sbin/multipathd -k"list paths" > /dev/null 2>&1 ; then
+	    echo -n " (multipathd running)"
+	    rc_status -v
+	    rc_exit
+	fi
+
+	# Load prerequisite module
+	modprobe dm-multipath
+	
+	# Be a chicken and flush all existing maps
+	$PROGRAM -F
+
+	# Clear /dev/disk/by-name/ prior to start-up; multipath will
+	# recreate them.
+	rm -f /dev/disk/by-name/* 2>&1 >/dev/null
+
+	# Set the maximum number of open files
+	if [ -n "$MAX_OPEN_FDS" ] ; then
+	    ulimit -n $MAX_OPEN_FDS
+	fi
+
+	# Start the program directly as checkproc doesn't work here
+	$PROGRAM -v 0
+
+	# Create all partitions which might have been missing
+	for map in $(/sbin/dmsetup ls --target multipath | sed '/No devices/d' | sort -n +2 | sed -n 's/.*, \(.*\))/\1/p' ) ; do
+	    wait=5
+	    while [ $wait -gt 0 ] ; do
+		[ -e /dev/dm-$map ] && break
+		wait=$((wait - 1))
+		sleep 1;
+	    done
+	    if [ $wait -le 0 ] ; then
+		echo -n "timeout waiting for devices"
+		rc_failed 1
+		break;
+	    fi
+	    /sbin/kpartx -a -p _part /dev/dm-$map
+	done
+
+	# Remember status and be verbose
+	rc_status -v
+	sleep 1
+	;;
+    stop)
+	echo -n "Removing multipath targets:"
+
+	# Remove all partition mappings
+	if /sbin/dmsetup ls | sed '/No devices/d' | grep -q -- -part; then
+	    /sbin/dmsetup ls --target multipath --exec "/sbin/kpartx -d -p _part" 2> /dev/null
+	fi
+
+	# Flush all existing maps
+	$PROGRAM -F
+
+	rc_failed 0
+	rc_status -v
+	;;
+    status)
+	echo -n "Checking multipath targets: "
+	# Display active multipath tables
+	tblnum=$(/sbin/dmsetup ls --target multipath | sed '/No devices/d' | wc --lines)
+	if [ "$tblnum" ] && [ $tblnum -gt 0 ] ; then
+	    echo -n "($tblnum multipath devices) "
+	    rc_failed 0
+	else
+	    rc_failed 3
+	fi
+	rc_status -v
+	;;
+    reload)
+	$0 stop
+	$0 start
+	;;
+    *)
+	echo "Usage: $0 {start|stop|status}"
+	exit 1
+	;;
+esac
+rc_exit
--- multipath-tools-0.4.8/multipath/setup-multipath.sh
+++ multipath-tools-0.4.8/multipath/setup-multipath.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+#
+#%stage: devicemapper
+#%provides: dmroot
+#
+# force multipath and dm usage if multipath was forced
+if use_script multipath; then
+    root_mpath=1
+    root_dm=1
+fi
+
+if [ -x /sbin/multipath -a -x /sbin/dmsetup ] ; then
+    for bd in $blockdev ; do
+	update_blockdev $bd
+	if [ $blockdriver = device-mapper ]; then
+	    dm_uuid=$(dmsetup info -c --noheadings -o uuid -j $blockmajor -m $blockminor)
+	    dm_creator=${dm_uuid%-*}
+	    if [ "$dm_creator" = "mpath" ]; then
+		tmp_root_dm=1 # multipath needs dm
+		root_mpath=1
+	    fi
+	fi
+    done
+fi
+
+if use_script multipath; then
+    if [ -f /etc/multipath.conf ] ; then
+	cp -a /etc/multipath.conf $tmp_mnt/etc
+    fi
+    if [ -f /var/lib/multipath/bindings ] ; then
+	mkdir -p /var/lib/multipath
+	cp -a /var/lib/multipath/bindings $tmp_mnt/var/lib/multipath
+    fi
+    if [ -e /etc/udev/rules.d/71-multipath.rules ]; then
+	cp /etc/udev/rules.d/71-multipath.rules $tmp_mnt/etc/udev/rules.d
+    fi
+    if [ -e /etc/udev/rules.d/72-multipath-compat.rules ]; then
+	cp /etc/udev/rules.d/72-multipath-compat.rules $tmp_mnt/etc/udev/rules.d
+    fi
+    if [ -d /lib/multipath ]; then
+	mkdir $tmp_mnt/lib/multipath
+    fi
+fi
+
+save_var root_mpath
--- multipath-tools-0.4.8/multipathd/Makefile
+++ multipath-tools-0.4.8/multipathd/Makefile
@@ -29,20 +29,19 @@
 
 $(EXEC): $(OBJS)
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $(EXEC) $(OBJS)
-	$(GZIP) $(EXEC).8 > $(EXEC).8.gz
 
 install:
 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(bindir)
 	$(INSTALL_PROGRAM) -m 755 $(EXEC) $(DESTDIR)$(bindir)
 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(rcdir)
+	$(INSTALL_PROGRAM) -m 755 multipathd.init.suse $(DESTDIR)$(rcdir)/multipathd
 	$(INSTALL_PROGRAM) -d $(DESTDIR)$(mandir)
-	$(INSTALL_PROGRAM) -m 644 $(EXEC).8.gz $(DESTDIR)$(mandir)
+	$(INSTALL_PROGRAM) -m 644 $(EXEC).8 $(DESTDIR)$(mandir)
 
 uninstall:
 	rm -f $(DESTDIR)$(bindir)/$(EXEC)
 	rm -f $(DESTDIR)$(rcdir)/$(EXEC)
-	rm -f $(DESTDIR)$(mandir)/$(EXEC).8.gz
 
 clean:
-	rm -f core *.o $(EXEC) *.gz
+	rm -f core *.o $(EXEC)
 
--- multipath-tools-0.4.8/multipathd/main.c
+++ multipath-tools-0.4.8/multipathd/main.c
@@ -944,19 +944,25 @@
 			enable_group(pp);
 	}
 	else if (newstate == PATH_UP || newstate == PATH_GHOST) {
-		LOG_MSG(4, checker_message(&pp->checker));
-		/*
-		 * double the next check delay.
-		 * max at conf->max_checkint
-		 */
-		if (pp->checkint < (conf->max_checkint / 2))
-			pp->checkint = 2 * pp->checkint;
-		else
-			pp->checkint = conf->max_checkint;
+		if (pp->dmstate == PSTATE_FAILED ||
+		    pp->dmstate == PSTATE_UNDEF) {
+			/* Clear IO errors */
+			reinstate_path(pp, 0);
+		} else {
+			LOG_MSG(4, checker_message(&pp->checker));
+			/*
+			 * double the next check delay.
+			 * max at conf->max_checkint
+			 */
+			if (pp->checkint < (conf->max_checkint / 2))
+				pp->checkint = 2 * pp->checkint;
+			else
+				pp->checkint = conf->max_checkint;
 
-		pp->tick = pp->checkint;
-		condlog(4, "%s: delay next check %is",
+			pp->tick = pp->checkint;
+			condlog(4, "%s: delay next check %is",
 				pp->dev_t, pp->tick);
+		}
 	}
 	else if (newstate == PATH_DOWN)
 		LOG_MSG(2, checker_message(&pp->checker));
@@ -1341,9 +1347,7 @@
 	/*
 	 * exit path
 	 */
-	lock(vecs->lock);
 	remove_maps_and_stop_waiters(vecs);
-	free_pathvec(vecs->pathvec, FREE_PATHS);
 
 	pthread_cancel(check_thr);
 	pthread_cancel(uevent_thr);
@@ -1357,6 +1361,9 @@
 	handlers = NULL;
 	free_polls();
 
+	lock(vecs->lock);
+	free_pathvec(vecs->pathvec, FREE_PATHS);
+	vecs->pathvec = NULL;
 	unlock(vecs->lock);
 	pthread_mutex_destroy(vecs->lock);
 	FREE(vecs->lock);
@@ -1421,15 +1428,28 @@
 	}
 
 	close(STDIN_FILENO);
-	dup(in_fd);
+	if (dup(in_fd) < 0) {
+		fprintf(stderr, "cannot duplicate /dev/null for input"
+			": %s\n", strerror(errno));
+		_exit(0);
+	}
 	close(STDOUT_FILENO);
-	dup(out_fd);
+	if (dup(out_fd) < 0) {
+		fprintf(stderr, "cannot duplicate /dev/console for output"
+			": %s\n", strerror(errno));
+		_exit(0);
+	}
 	close(STDERR_FILENO);
-	dup(out_fd);
-
+	if (dup(out_fd) < 0) {
+		fprintf(stderr, "cannot duplicate /dev/console for error"
+			": %s\n", strerror(errno));
+		_exit(0);
+	}
 	close(in_fd);
 	close(out_fd);
-	chdir("/");
+	if (chdir("/") < 0)
+		fprintf(stderr, "cannot chdir to '/', continuing\n");
+
 	umask(0);
 	return 0;
 }
@@ -1451,7 +1471,9 @@
 	}
 
 	/* make sure we don't lock any path */
-	chdir("/");
+	if (chdir("/") < 0)
+		fprintf(stderr, "couldn't chdir to '/', continuing\n");
+
 	umask(umask(077) | 022);
 
 	conf = alloc_config();
--- multipath-tools-0.4.8/multipathd/multipathd.init.suse
+++ multipath-tools-0.4.8/multipathd/multipathd.init.suse
@@ -12,10 +12,11 @@
 ### BEGIN INIT INFO
 # Provides:          multipathd
 # Required-Start:    $syslog
-# Required-Stop:
+# Required-Stop:     $syslog
 # Default-Start:     3 5
 # Default-Stop:	     0 1 2 4 6
-# Description:       Starts multipath daemon
+# Short-Description: Starts multipath daemon
+# Description:       Starts the multipath daemon
 ### END INIT INFO
 
 PATH=/bin:/usr/bin:/sbin:/usr/sbin
--- multipath-tools-0.4.8/multipathd/uxlsnr.c
+++ multipath-tools-0.4.8/multipathd/uxlsnr.c
@@ -168,5 +168,6 @@
 		}
 	}
 
+	close(ux_sock);
 	return NULL;
 }
openSUSE Build Service is sponsored by