Use work_queues rather than dm-daemon.  [Mike Christie/Joe Thornber]
--- diff/drivers/md/dm-mpath.c	2004-02-13 16:42:56.000000000 +0000
+++ source/drivers/md/dm-mpath.c	2004-02-16 10:57:08.000000000 +0000
@@ -5,7 +5,6 @@
  */
 
 #include "dm.h"
-#include "dm-daemon.h"
 #include "dm-path-selector.h"
 #include "dm-bio-list.h"
 
@@ -16,6 +15,7 @@
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/time.h>
+#include <linux/workqueue.h>
 #include <asm/atomic.h>
 
 /* FIXME: get rid of these */
@@ -60,10 +60,15 @@
 	struct path *current_path;
 	unsigned current_count;
 
+	struct work_struct dispatch_failed;
 	struct bio_list failed_ios;
-	unsigned trigger_event;
+
+	struct work_struct trigger_event;
 };
 
+static void dispatch_failed_ios(void *data);
+static void trigger_event(void *data);
+
 static struct path *alloc_path(void)
 {
 	struct path *path = kmalloc(sizeof(*path), GFP_KERNEL);
@@ -139,6 +144,8 @@
 		memset(m, 0, sizeof(*m));
 		INIT_LIST_HEAD(&m->priority_groups);
 		m->lock = SPIN_LOCK_UNLOCKED;
+		INIT_WORK(&m->dispatch_failed, dispatch_failed_ios, m);
+		INIT_WORK(&m->trigger_event, trigger_event, m);
 	}
 
 	return m;
@@ -159,10 +166,7 @@
 /*-----------------------------------------------------------------
  * The multipath daemon is responsible for resubmitting failed ios.
  *---------------------------------------------------------------*/
-static struct dm_daemon _kmpathd;
-
-static LIST_HEAD(_mpaths);
-static DECLARE_MUTEX(_mpath_lock);
+static struct workqueue_struct *_kmpathd_wq;
 
 static int __choose_path(struct multipath *m)
 {
@@ -180,7 +184,7 @@
 
 	m->current_path = path;
 	m->current_count = MPATH_MIN_IO;
-;
+
 	return 0;
 }
 
@@ -214,8 +218,10 @@
 	return 0;
 }
 
-static void dispatch_failed_ios(struct multipath *m)
+static void dispatch_failed_ios(void *data)
 {
+	struct multipath *m = (struct multipath *) data;
+
 	int r;
 	unsigned long flags;
 	struct bio *bio = NULL, *next;
@@ -241,31 +247,18 @@
 
 		bio = next;
 	}
+
+	/*
+	 * FIXME: this now gets called once for each mpath
+	 * target, rather than once per daemon cycle.
+	 */
+ 	blk_run_queues();
 }
 
-/*
- * Multipathd does this every time it runs, returning a sleep
- * duration hint.
- */
-static jiffy_t do_work(void)
+static void trigger_event(void *data)
 {
-	unsigned long flags;
-	struct multipath *m;
-
-	down(&_mpath_lock);
-	list_for_each_entry (m, &_mpaths, list) {
-		dispatch_failed_ios(m);
-
-		/* No locking is needed around this */
-		if (m->trigger_event) {
-			m->trigger_event = 0;
-			dm_table_event(m->ti->table);
-		}
-	}
-	up(&_mpath_lock);
-
-	blk_run_queues();
-	return 0;
+	struct multipath *m = (struct multipath *) data;
+	dm_table_event(m->ti->table);
 }
 
 /*-----------------------------------------------------------------
@@ -491,10 +484,6 @@
 	ti->private = m;
 	m->ti = ti;
 
-	down(&_mpath_lock);
-	list_add(&m->list, &_mpaths);
-	up(&_mpath_lock);
-
 	return 0;
 
  bad:
@@ -505,11 +494,6 @@
 static void multipath_dtr(struct dm_target *ti)
 {
 	struct multipath *m = (struct multipath *) ti->private;
-
-	down(&_mpath_lock);
-	list_del(&m->list);
-	up(&_mpath_lock);
-
 	free_multipath(m);
 }
 
@@ -552,11 +536,12 @@
 
 	/* FIXME: path->fail_count is brain dead */
 	if (!path->has_failed && !--path->fail_count) {
+		m = path->pg->m;
+
 		path->has_failed = 1;
 		path->pg->ps->type->fail_path(path->pg->ps, path);
-		path->pg->m->trigger_event = 1;
+		queue_work(_kmpathd_wq, &m->trigger_event);
 
-		m = path->pg->m;
 		spin_lock(&m->lock);
 		m->nr_valid_paths--;
 
@@ -591,7 +576,7 @@
 		bio_list_add(&m->failed_ios, bio);
 		spin_unlock(&m->lock);
 
-		dm_daemon_wake(&_kmpathd);
+		queue_work(_kmpathd_wq, &m->dispatch_failed);
 		return 1;	/* io not complete */
 	}
 
@@ -700,8 +685,8 @@
 		return r;
 	}
 
-	r = dm_daemon_start(&_kmpathd, "kpathd", do_work);
-	if (r) {
+	_kmpathd_wq = create_workqueue("dm-multipath");
+	if (!_kmpathd_wq) {
 		/* FIXME: remove this */
 		dm_unregister_path_selectors();
 		dm_unregister_target(&multipath_target);
@@ -715,7 +700,7 @@
 {
 	int r;
 
-	dm_daemon_stop(&_kmpathd);
+	destroy_workqueue(_kmpathd_wq);
 	dm_unregister_path_selectors();
 	r = dm_unregister_target(&multipath_target);
 	if (r < 0)
