Multipath: dispatch_failed_ios can sleep. It should not                                  
disrupt other users of the default work queue. Under heavy load                                   
or group/ps initializations on a single processor machine, this                                   
conflict becomes painful.  [Mike Christie]
--- diff/drivers/md/dm-mpath.c	2004-04-07 11:33:44.339651544 +0100
+++ source/drivers/md/dm-mpath.c	2004-04-07 11:33:46.367343288 +0100
@@ -285,6 +285,8 @@ static int map_io(struct multipath *m, s
 /*-----------------------------------------------------------------
  * The multipath daemon is responsible for resubmitting failed ios.
  *---------------------------------------------------------------*/
+struct workqueue_struct *kmultipathd;
+
 static void dispatch_failed_ios(void *data)
 {
 	struct multipath *m = (struct multipath *) data;
@@ -592,7 +594,7 @@ static int do_end_io(struct multipath *m
 		bio_list_add(&m->failed_ios, bio);
 		spin_unlock(&m->lock);
 
-		schedule_work(&m->dispatch_failed);
+		queue_work(kmultipathd, &m->dispatch_failed);
 		return 1;	/* io not complete */
 	}
 
@@ -707,6 +709,13 @@ int __init dm_multipath_init(void)
 		return r;
 	}
 
+	kmultipathd = create_workqueue("kmpathd");
+	if (!kmultipathd) {
+		dm_unregister_path_selectors();
+		dm_unregister_target(&multipath_target);
+		kmem_cache_destroy(_details_cache);
+	}
+
 	DMINFO("dm_multipath v0.2.0");
 	return r;
 }
@@ -715,6 +724,7 @@ void __exit dm_multipath_exit(void)
 {
 	int r;
 
+	destroy_workqueue(kmultipathd);
 	dm_unregister_path_selectors();
 	r = dm_unregister_target(&multipath_target);
 	if (r < 0)
