diff -urN multipath-0.0.9/ChangeLog multipath-0.0.10.2/ChangeLog
--- multipath-0.0.9/ChangeLog	2003-12-01 18:58:23.000000000 +0100
+++ multipath-0.0.10.2/ChangeLog	2003-12-20 01:04:56.000000000 +0100
@@ -1,3 +1,60 @@
+2003-12-20 multipath-010
+	* big ChangeLog update
+	* start to give a little control over target params :
+	  introduce cmdline arg -i to control polling interval
+	* cope with hotplug-style calling convention :
+	  ie "multipath scsi $DEVPATH" ... to avoid messing with
+	  online maps not concerned by an event
+	* example hotplug agent to drop in /etc/hotplug.d/scsi
+	* revert the run & resched patch : unless someone proves me
+	  wrong, this was overdesigned
+	* move commented out functions in unused.c
+	* update multipath target params to "udm[23] style"
+	* mp target now supports nr_path == 1, so do we
+	* add gratuitous free()
+	* push version forward
+2003-12-15 multipath-009
+	* Make the HW-specific get_unique_id switch pretty
+	* Prepare to field-test by whitelisting all known fibre array,
+	  try to fetch WWID from the standard EVPD 0x83 off 8 for everyone
+	* configure the multipath target with round-robin path selector and
+	  conservative default for a start (udm1 style) :
+	  yes it makes this release the firstreally useful one.
+	* temporarily disable map creation for single path device
+	  due to current restrictive defaults in the kernel target.
+	  Sistina should work it out.
+	* correct the strncmp logic in blacklist function.
+	* update the Makefiles to autodetect libgcc.a & gcc includes
+	  "ulibc-style". Factorisation of udevdirs & others niceties
+	* drop a hint about absent /dev/sd? on failed open()
+	* implement a reschedule flag in /var/run.
+	  Last thing the prog do before exit is check if a call to multipath
+	  was done (but canceled by /var/run/multipath.run check) during its
+	  execution. If so restart themain loop.
+	* implement a blacklist of sysfs bdev to not bother with for now
+	  (hd,md, dm, sr, scd, ram, raw).
+	  This avoid sending SG_IO to unappropiate devices.
+	* Adds a /var/run/multipath.run handling to avoid simultaneous runs.
+	* Remove a commented-out "printf"
+	* drop a libdevmapper copy in extras/multipath;
+	  maybe discussions w/Sistina folks will bring a better solution in the future.
+	* drop a putchar usage in libdevmapper to compile cleanly with klibc
+	* drop another such usage of my own in main.c
+	* massage the Makefile to compile libdevmapper against klibc
+	* use "ld" to produce the binary rather than "gcc -static"
+	* stop being stupid w/ uneeded major, minor & dev in main.c:dm_mk_node()
+	* reverse to creating striped target for now because the multipath target
+	  is more hairy than expected initialy
+	* push the version code to 009 to be in synch w/ udev
+2003-11-27 multipath-007
+	* removes sg_err.[ch] deps
+	* makes sure the core code play nice with klibc
+	* port the sysfs calls to dlist helpers
+	* links against udev's sysfs (need libsysfs.a & dlist.a)
+	* finally define DM_TARGET as "multipath" as Joe posted the code today (not tested yet)
+	* push version forward (do you want it in sync with udev version?)
+2003-11-19
+	* merged in udev-006 tree
 2003-09-18  Christophe Varoqui <christophe.varoqui@free.fr>
 	* multipath 0.0.1 released.
 	* Initial release.
diff -urN multipath-0.0.9/main.c multipath-0.0.10.2/main.c
--- multipath-0.0.9/main.c	2003-12-15 23:42:23.000000000 +0100
+++ multipath-0.0.10.2/main.c	2003-12-20 00:59:18.000000000 +0100
@@ -1,5 +1,5 @@
 /*
- * Soft:        Description here...
+ * Soft:        multipath device mapper target autoconfig
  *
  * Version:     $Id: main.h,v 0.0.1 2003/09/18 15:13:38 cvaroqui Exp $
  *
@@ -258,38 +258,80 @@
 	struct sysfs_directory * sdir;
 	struct sysfs_directory * devp;
 	struct sysfs_link * linkp;
+	char refwwid[WWID_SIZE];
+	char empty_buff[WWID_SIZE];
 	char buff[FILE_NAME_SIZE];
+	char path[FILE_NAME_SIZE];
+	struct path curpath;
 
-	char block_path[FILE_NAME_SIZE];
+	/* if called from udev, only consider the paths that relate to */
+	/* to the device pointed by conf.hotplugdev */
+	memset(empty_buff, 0, WWID_SIZE);
+	memset(refwwid, 0, WWID_SIZE);
+	if (strncmp("/devices", conf->hotplugdev, 8) == 0) {
+		sprintf(buff, "%s%s/block",
+			conf->sysfs_path, conf->hotplugdev);
+		memset(conf->hotplugdev, 0, FILE_NAME_SIZE);
+		readlink(buff, conf->hotplugdev, FILE_NAME_SIZE);
+		basename(conf->hotplugdev, buff);
+		sprintf(curpath.sg_dev, "/dev/%s", buff);
+
+		if ((sg_fd = open(curpath.sg_dev, O_RDONLY)) < 0)
+			exit(1);
+
+		get_lun_strings(sg_fd, &curpath);
+		get_unique_id(sg_fd, &curpath);
+		strcpy(refwwid, curpath.wwid);
+		memset(&curpath, 0, sizeof(path));
+	}
 
-	sprintf(block_path, "%s/block", conf->sysfs_path);
-	sdir = sysfs_open_directory(block_path);
+	sprintf(path, "%s/block", conf->sysfs_path);
+	sdir = sysfs_open_directory(path);
 	sysfs_read_directory(sdir);
+
 	dlist_for_each_data(sdir->subdirs, devp, struct sysfs_directory) {
 		if (blacklist(devp->name))
 			continue;
+
 		sysfs_read_directory(devp);
+
 		if(devp->links == NULL)
 			continue;
+
 		dlist_for_each_data(devp->links, linkp, struct sysfs_link) {
 			if (!strncmp(linkp->name, "device", 6))
 				break;
 		}
+
 		if (linkp == NULL) {
 			continue;
 		}
 
 		basename(devp->path, buff);
-		sprintf(all_paths[k].sg_dev, "/dev/%s", buff);
-		strcpy(all_paths[k].dev, all_paths[k].sg_dev);
-		if ((sg_fd = open(all_paths[k].sg_dev, O_RDONLY)) < 0) {
+		sprintf(curpath.sg_dev, "/dev/%s", buff);
+
+		if ((sg_fd = open(curpath.sg_dev, O_RDONLY)) < 0) {
 			if (conf->verbose)
-				fprintf(stderr, "can't open %s. mknod ?",
-					all_paths[k].sg_dev); 
+				fprintf(stderr, "can't open %s\n",
+					curpath.sg_dev); 
 			continue;
 		}
-		get_lun_strings(sg_fd, &all_paths[k]);
-		get_unique_id(sg_fd, &all_paths[k]);
+
+		get_lun_strings(sg_fd, &curpath);
+		get_unique_id(sg_fd, &curpath);
+
+		if (memcmp(empty_buff, refwwid, WWID_SIZE) != 0 && 
+		    strncmp(curpath.wwid, refwwid, WWID_SIZE) != 0) {
+			memset(&curpath, 0, sizeof(path));
+			continue;
+		}
+
+		strcpy(all_paths[k].sg_dev, curpath.sg_dev);
+		strcpy(all_paths[k].dev, curpath.sg_dev);
+		strcpy(all_paths[k].wwid, curpath.wwid);
+		strcpy(all_paths[k].vendor_id, curpath.vendor_id);
+		strcpy(all_paths[k].product_id, curpath.product_id);
+		memset(&curpath, 0, sizeof(path));
 		all_paths[k].state = do_tur(sg_fd);
 		close(sg_fd);
 		basename(linkp->target, buff);
@@ -301,7 +343,6 @@
 		k++;
 	}
 	sysfs_close_directory(sdir);
-
 	return 0;
 }
 
@@ -562,26 +603,6 @@
 
 }
 
-/* future use ?
-static int
-del_map(char * str) {
-	struct dm_task *dmt;
-
-	if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
-		return 0;
-	if (!dm_task_set_name(dmt, str))
-		goto delout;
-	if (!dm_task_run(dmt))
-		goto delout;
-
-	printf("Deleted device map : %s\n", str);
-
-	delout:
-	dm_task_destroy(dmt);
-	return 1;
-}
-*/
-
 static int
 add_map(struct env * conf, struct path * all_paths,
 	struct multipath * mp, int index, int op)
@@ -593,15 +614,9 @@
 	long size = -1;
 
 	/* defaults for multipath target */
-	int dm_nr_path_args         = 2;
-	int dm_path_test_int        = 10;
+	int dm_pg_prio              = 1;
 	char * dm_ps_name           = "round-robin";
-	int dm_ps_nr_args           = 2;
-	int dm_path_failback_int    = 10;
-	int dm_path_nr_fail         = 2;
-	int dm_ps_prio              = 1;
-	int dm_ps_min_io            = 2;
-
+	int dm_ps_nr_args           = 0;
 
 	if (!(dmt = dm_task_create(op)))
 		return 0;
@@ -618,14 +633,13 @@
 	}
 	if (np == 0)
 		goto addout;
-	/* temporarily disable creation of single path maps */
-	/* Sistina should modify the target limits */
-	if (np < 2)
+
+	if (np < 1)
 		goto addout;
 
-	params_p += sprintf(params_p, "%i %i %i %s %i",
-			    np, dm_nr_path_args, dm_path_test_int,
-			    dm_ps_name, dm_ps_nr_args);
+	params_p += sprintf(params_p, "%i %i %s %i %i",
+			    conf->dm_path_test_int, dm_pg_prio, 
+			    dm_ps_name, np, dm_ps_nr_args);
 	
 	for (i=0; i<=mp[index].npaths; i++) {
 		if (( 0 == all_paths[PINDEX(index,i)].state) ||
@@ -633,10 +647,8 @@
 			continue;
 		if (size < 0)
 			size = get_disk_size(conf, all_paths[PINDEX(index,0)].dev);
-		params_p += sprintf(params_p, " %s %i %i %i %i",
-				    all_paths[PINDEX(index,i)].dev,
-				    dm_path_failback_int, dm_path_nr_fail,
-				    dm_ps_prio, dm_ps_min_io);
+		params_p += sprintf(params_p, " %s",
+				    all_paths[PINDEX(index,i)].dev);
 	}
 
 	if (size < 0)
@@ -665,44 +677,6 @@
 	return 1;
 }
 
-/*
-static int
-get_table(const char * str)
-{
-	int r = 0;
-	struct dm_task *dmt;
-	void *next = NULL;
-	uint64_t start, length;
-	char *target_type = NULL;
-	char *params;
-
-        if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
-                return 0;
-
-        if (!dm_task_set_name(dmt, str))
-                goto out;
-
-        if (!dm_task_run(dmt))
-                goto out;
-
-        do {
-                next = dm_get_next_target(dmt, next, &start, &length,
-                                          &target_type, &params);
-                if (target_type) {
-                        printf("%" PRIu64 " %" PRIu64 " %s %s\n",
-                               start, length, target_type, params);
-                }
-        } while (next);
-
-        r = 1;
-
-      out:
-        dm_task_destroy(dmt);
-        return r;
-
-}
-*/
-
 static int
 map_present(char * str)
 {
@@ -740,28 +714,18 @@
 usage(char * progname)
 {
 	fprintf(stderr, VERSION_STRING);
-	fprintf(stderr, "Usage: %s [-v|-q] [-d] [-m max_devs]\n", progname);
-	fprintf(stderr, "\t-v\t\tverbose, print all paths and multipaths\n");
-	fprintf(stderr, "\t-q\t\tquiet, no output at all\n");
+	fprintf(stderr, "Usage: %s [-v|-q] [-d] [-i int] [-m max_devs]\n", progname);
 	fprintf(stderr, "\t-d\t\tdry run, do not create or update devmaps\n");
+	fprintf(stderr, "\t-i\t\tmultipath target param : polling interval\n");
 	fprintf(stderr, "\t-m max_devs\tscan {max_devs} devices at most\n");
+	fprintf(stderr, "\t-q\t\tquiet, no output at all\n");
+	fprintf(stderr, "\t-v\t\tverbose, print all paths and multipaths\n");
 	exit(1);
 }
 
-static int
-filepresent(char * run) {
-	struct stat buf;
-
-	if(!stat(run, &buf))
-		return 1;
-	return 0;
-}
-
 int
 main(int argc, char *argv[])
 {
-	char * run = "/var/run/multipath.run";
-	char * resched = "/var/run/multipath.reschedule";
 	struct multipath * mp;
 	struct path * all_paths;
 	struct scsi_dev * all_scsi_ids;
@@ -774,6 +738,7 @@
 	conf.verbose = 0;	/* 1 == Print all_paths and mp */
 	conf.quiet = 0;		/* 1 == Do not even print devmaps */
 	conf.with_sysfs = 0;	/* Default to compat / suboptimal behaviour */
+	conf.dm_path_test_int = 10;
 
 	/* kindly provided by libsysfs */
 	if (0 == sysfs_get_mnt_path(conf.sysfs_path, FILE_NAME_SIZE))
@@ -794,6 +759,10 @@
 			conf.quiet = 1;
 		} else if (0 == strcmp("-d", argv[i]))
 			conf.dry_run = 1;
+		else if (0 == strcmp("-i", argv[i]))
+			conf.dm_path_test_int = atoi(argv[++i]);
+		else if (0 == strcmp("scsi", argv[i]))
+			strcpy(conf.hotplugdev, argv[++i]);
 		else if (*argv[i] == '-') {
 			fprintf(stderr, "Unknown switch: %s\n", argv[i]);
 			usage(argv[0]);
@@ -804,27 +773,11 @@
 
 	}
 
-	if (filepresent(run)) {
-		if (conf.verbose) {
-			fprintf(stderr, "Already running.\n");
-			fprintf(stderr, "If you know what you do, please ");
-			fprintf(stderr, "remove %s\n", run);
-		}
-		/* leave a trace that we were called while already running */
-		open(resched, O_CREAT);
-		return 1;
-	}
-
 	/* dynamic allocations */
 	mp = malloc(conf.max_devs * sizeof(struct multipath));
 	all_paths = malloc(conf.max_devs * sizeof(struct path));
 	all_scsi_ids = malloc(conf.max_devs * sizeof(struct scsi_dev));
-	if (mp == NULL || all_paths == NULL || all_scsi_ids == NULL) {
-		unlink(run);
-		exit(1);
-	}
-start:
-	if(!open(run, O_CREAT))
+	if (mp == NULL || all_paths == NULL || all_scsi_ids == NULL)
 		exit(1);
 
 	if (!conf.with_sysfs) {
@@ -842,10 +795,8 @@
 		fprintf(stdout, "\n");
 	}
 
-	if (conf.dry_run) {
-		unlink(run);
+	if (conf.dry_run)
 		exit(0);
-	}
 
 	for (k=0; k<=nmp; k++) {
 		if (map_present(mp[k].wwid)) {
@@ -854,13 +805,11 @@
 			add_map(&conf, all_paths, mp, k, DM_DEVICE_CREATE);
 		}
 	}
-	unlink(run);
 
-	/* start again if we were ask to during this process run */
-	/* ie. do not loose an event-asked run */
-	if (filepresent(resched)) {
-		unlink(resched);
-		goto start;
-	}
+	/* free allocs */
+	free(mp);
+	free(all_paths);
+	free(all_scsi_ids);
+
 	exit(0);
 }
diff -urN multipath-0.0.9/main.h multipath-0.0.10.2/main.h
--- multipath-0.0.9/main.h	2003-12-09 22:18:38.000000000 +0100
+++ multipath-0.0.10.2/main.h	2003-12-20 00:58:41.000000000 +0100
@@ -99,14 +99,16 @@
 	int quiet;
 	int dry_run;
 	int with_sysfs;
+	int dm_path_test_int;
 	char sysfs_path[FILE_NAME_SIZE];
+	char hotplugdev[FILE_NAME_SIZE];
 };
 
 /* Build version */
 #define PROG    "multipath"
 
-#define VERSION_CODE 0x000009
-#define DATE_CODE    0x0C0503
+#define VERSION_CODE 0x000010
+#define DATE_CODE    0x0C1503
 
 #define MULTIPATH_VERSION(version)	\
 	(version >> 16) & 0xFF,		\
diff -urN multipath-0.0.9/multipath.hotplug multipath-0.0.10.2/multipath.hotplug
--- multipath-0.0.9/multipath.hotplug	1970-01-01 01:00:00.000000000 +0100
+++ multipath-0.0.10.2/multipath.hotplug	2003-12-20 00:39:42.000000000 +0100
@@ -0,0 +1,3 @@
+. /etc/hotplug/hotplug.functions
+sleep 1
+mesg `/root/multipath scsi $DEVPATH`
diff -urN multipath-0.0.9/unsused.c multipath-0.0.10.2/unsused.c
--- multipath-0.0.9/unsused.c	1970-01-01 01:00:00.000000000 +0100
+++ multipath-0.0.10.2/unsused.c	2003-12-19 14:37:17.000000000 +0100
@@ -0,0 +1,52 @@
+static int
+del_map(char * str) {
+        struct dm_task *dmt;
+
+        if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
+                return 0;
+        if (!dm_task_set_name(dmt, str))
+                goto delout;
+        if (!dm_task_run(dmt))
+                goto delout;
+
+        printf("Deleted device map : %s\n", str);
+
+        delout:
+        dm_task_destroy(dmt);
+        return 1;
+}
+
+get_table(const char * str)
+{
+        int r = 0;
+        struct dm_task *dmt;
+        void *next = NULL;
+        uint64_t start, length;
+        char *target_type = NULL;
+        char *params;
+
+        if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
+                return 0;
+
+        if (!dm_task_set_name(dmt, str))
+                goto out;
+
+        if (!dm_task_run(dmt))
+                goto out;
+
+        do {
+                next = dm_get_next_target(dmt, next, &start, &length,
+                                          &target_type, &params);
+                if (target_type) {
+                        printf("%" PRIu64 " %" PRIu64 " %s %s\n",
+                               start, length, target_type, params);
+                }
+        } while (next);
+
+        r = 1;
+
+      out:
+        dm_task_destroy(dmt);
+        return r;
+
+}
