Strip out path testing, we'll do this from userland instead.
--- diff/drivers/md/dm-mpath.c	2004-02-13 15:52:03.000000000 +0000
+++ source/drivers/md/dm-mpath.c	2004-02-13 16:42:56.000000000 +0000
@@ -18,6 +18,7 @@
 #include <linux/time.h>
 #include <asm/atomic.h>
 
+/* FIXME: get rid of these */
 #define MPATH_FAIL_COUNT	1
 #define MPATH_MIN_IO		1000
 
@@ -26,19 +27,11 @@
 	struct list_head list;
 
 	struct dm_dev *dev;
-
 	struct priority_group *pg;
 
 	spinlock_t failed_lock;
-	/* FIXME: put the next 2 fields in a bitset */
-	int tested;
 	int has_failed;
 	unsigned fail_count;
-	unsigned fail_total;
-
-	struct semaphore test_lock;
-	struct bio *test_bio;
-	struct page *test_page;	/* FIXME: share this between all paths ? */
 };
 
 struct priority_group {
@@ -63,16 +56,11 @@
 
 	spinlock_t lock;
 	unsigned nr_valid_paths;
-	unsigned nr_tested_paths;
 
 	struct path *current_path;
 	unsigned current_count;
-	unsigned min_io;
 
 	struct bio_list failed_ios;
-	struct bio_list test_ios;
-
-	unsigned test_interval;
 	unsigned trigger_event;
 };
 
@@ -84,20 +72,6 @@
 		memset(path, 0, sizeof(*path));
 		path->failed_lock = SPIN_LOCK_UNLOCKED;
 		path->fail_count = MPATH_FAIL_COUNT;
-		init_MUTEX_LOCKED(&path->test_lock); /* resume will unlock */
-
-		path->test_bio = bio_alloc(GFP_KERNEL, 1);
-		if (!path->test_bio) {
-			kfree(path);
-			return NULL;
-		}
-
-		path->test_page = alloc_page(GFP_KERNEL);
-		if (!path->test_page) {
-			bio_put(path->test_bio);
-			kfree(path);
-			return NULL;
-		}
 	}
 
 	return path;
@@ -105,9 +79,6 @@
 
 static inline void free_path(struct path *p)
 {
-	ClearPageLocked(p->test_page);
-	__free_page(p->test_page);
-	bio_put(p->test_bio);
 	kfree(p);
 }
 
@@ -168,7 +139,6 @@
 		memset(m, 0, sizeof(*m));
 		INIT_LIST_HEAD(&m->priority_groups);
 		m->lock = SPIN_LOCK_UNLOCKED;
-		m->min_io = MPATH_MIN_IO;
 	}
 
 	return m;
@@ -187,119 +157,6 @@
 }
 
 /*-----------------------------------------------------------------
- * All paths should be tested periodically.
- *---------------------------------------------------------------*/
-static void iterate_paths(struct multipath *m, void (*fn)(struct path *p))
-{
-	struct priority_group *pg;
-	struct path *p;
-
-	list_for_each_entry (pg, &m->priority_groups, list) {
-		list_for_each_entry (p, &pg->paths, list)
-			fn(p);
-	}
-}
-
-static void clear_tested(struct path *p)
-{
-	p->tested = 0;
-}
-
-static void fail_path(struct path *path)
-{
-	unsigned long flags;
-	struct multipath *m;
-
-	spin_lock_irqsave(&path->failed_lock, flags);
-
-	/* FIXME: path->fail_count is brain dead */
-	if (!path->has_failed && !--path->fail_count) {
-		path->has_failed = 1;
-		path->fail_total++;
-		path->pg->ps->type->set_path_state(path->pg->ps, path, 0);
-		path->pg->m->trigger_event = 1;
-
-		m = path->pg->m;
-		spin_lock(&m->lock);
-		m->nr_valid_paths--;
-		if (!m->nr_valid_paths) {
-			iterate_paths(m, clear_tested);
-			m->nr_tested_paths = 0;
-		}
-
-		if (path == m->current_path)
-			m->current_path = NULL;
-
-		spin_unlock(&m->lock);
-	}
-
-	if (!path->tested) {
-		path->tested = 1;
-
-		m = path->pg->m;
-		spin_lock(&m->lock);
-		m->nr_tested_paths++;
-		spin_unlock(&m->lock);
-	}
-
-	spin_unlock_irqrestore(&path->failed_lock, flags);
-}
-
-static void recover_path(struct path *path)
-{
-	unsigned long flags;
-	struct multipath *m = path->pg->m;
-
-	spin_lock_irqsave(&path->failed_lock, flags);
-
-	if (path->has_failed) {
-		path->has_failed = 0;
-		path->fail_count = MPATH_FAIL_COUNT;
-		path->pg->ps->type->set_path_state(path->pg->ps, path, 1);
-		m->trigger_event = 1;
-
-		spin_lock(&m->lock);
-		m->nr_valid_paths++;
-		spin_unlock(&m->lock);
-	}
-
-	spin_unlock_irqrestore(&path->failed_lock, flags);
-}
-
-static int test_endio(struct bio *bio, unsigned int done, int error)
-{
-	struct path *path = (struct path *) bio->bi_private;
-
-	if (bio->bi_size)
-		return 1;
-
-	if (error)
-		fail_path(path);
-	else
-		recover_path(path);
-
-	up(&path->test_lock);
-	return 0;
-}
-
-static void test_path(struct path *p)
-{
-	/*
-	 * If we get this lock we're allowed to issue a test io
-	 * for this path.
-	 */
-	if (down_trylock(&p->test_lock))
-		return;
-
-	p->test_bio->bi_sector = 0;
-	p->test_bio->bi_bdev = p->dev->bdev;
-	p->test_bio->bi_size = bdev_hardsect_size(p->dev->bdev);
-	p->test_bio->bi_idx = 0;
-
-	bio_list_add(&p->pg->m->test_ios, p->test_bio);
-}
-
-/*-----------------------------------------------------------------
  * The multipath daemon is responsible for resubmitting failed ios.
  *---------------------------------------------------------------*/
 static struct dm_daemon _kmpathd;
@@ -307,18 +164,6 @@
 static LIST_HEAD(_mpaths);
 static DECLARE_MUTEX(_mpath_lock);
 
-static void submit_ios(struct bio *bio)
-{
-	struct bio *next;
-
-	while (bio) {
-		next = bio->bi_next;
-		bio->bi_next = NULL;
-		generic_make_request(bio);
-		bio = next;
-	}
-}
-
 static int __choose_path(struct multipath *m)
 {
 	struct priority_group *pg;
@@ -334,7 +179,8 @@
 	}
 
 	m->current_path = path;
-	m->current_count = m->min_io;
+	m->current_count = MPATH_MIN_IO;
+;
 	return 0;
 }
 
@@ -375,11 +221,9 @@
 	struct bio *bio = NULL, *next;
 
 	spin_lock_irqsave(&m->lock, flags);
-	if (m->nr_valid_paths || (m->nr_tested_paths == m->nr_paths))
-		bio = bio_list_get(&m->failed_ios);
+	bio = bio_list_get(&m->failed_ios);
 	spin_unlock_irqrestore(&m->lock, flags);
 
-
 	while (bio) {
 		next = bio->bi_next;
 		bio->bi_next = NULL;
@@ -389,10 +233,9 @@
 			/*
 			 * This wont loop forever because the
 			 * end_io function will fail the ios if
-			 * we've tested all the paths.
+			 * we've no valid paths left.
 			 */
 			bio_io_error(bio, bio->bi_size);
-
 		else
 			generic_make_request(bio);
 
@@ -408,33 +251,21 @@
 {
 	unsigned long flags;
 	struct multipath *m;
-	unsigned interval = 0;
-	int event;
 
 	down(&_mpath_lock);
 	list_for_each_entry (m, &_mpaths, list) {
 		dispatch_failed_ios(m);
-		iterate_paths(m, test_path);
-		submit_ios(bio_list_get(&m->test_ios));
 
-		spin_lock_irqsave(&m->lock, flags);
-		event = 0;
+		/* No locking is needed around this */
 		if (m->trigger_event) {
-			event = 1;
 			m->trigger_event = 0;
-		}
-		spin_unlock_irqrestore(&m->lock, flags);
-
-		if (event)
 			dm_table_event(m->ti->table);
-
-		interval = min_not_zero(interval, m->test_interval);
+		}
 	}
 	up(&_mpath_lock);
 
 	blk_run_queues();
-
-	return ((jiffy_t) interval) * HZ;
+	return 0;
 }
 
 /*-----------------------------------------------------------------
@@ -489,18 +320,6 @@
 	as->argv += n;
 }
 
-static void init_test_bio(struct path *p)
-{
-	struct bio *bio = p->test_bio;
-
-	bio->bi_sector = 0;
-	bio->bi_rw |= (1 << BIO_RW_FAILFAST);
-	bio->bi_bdev = p->dev->bdev;
-	bio->bi_end_io = test_endio;
-	bio->bi_private = p;
-	bio_add_page(bio, p->test_page, bdev_hardsect_size(p->dev->bdev), 0);
-}
-
 static struct path *parse_path(struct arg_set *as, struct path_selector *ps,
 			       struct dm_target *ti)
 {
@@ -523,7 +342,6 @@
 		ti->error = ESTR("error getting device");
 		goto bad;
 	}
-	init_test_bio(p);
 
 	r = ps->type->add_path(ps, p, as->argc, as->argv, &ti->error);
 	if (r) {
@@ -621,20 +439,6 @@
 	return NULL;
 }
 
-/*
- * Debug only.
- */
-static void __check_ordered(struct list_head *head)
-{
-	struct priority_group *pg;
-	unsigned last = 0;
-
-	list_for_each_entry (pg, head, list) {
-		BUG_ON (pg->priority < last);
-		last = pg->priority;
-	}
-}
-
 static void __insert_priority_group(struct multipath *m,
 				    struct priority_group *pg)
 {
@@ -646,9 +450,6 @@
 
 	list_add_tail(&pg->list, &tmp->list);
 	pg->m = m;
-
-	/* FIXME: remove debug later */
-	__check_ordered(&m->priority_groups);
 }
 
 static int multipath_ctr(struct dm_target *ti, unsigned int argc,
@@ -656,7 +457,6 @@
 {
 	/* target parameters */
 	static struct param _params[] = {
-		{1, 60 * 60, ESTR("invalid path test interval")},
 		{1, 1024, ESTR("invalid number of priority groups")},
 	};
 
@@ -673,11 +473,7 @@
 		return -EINVAL;
 	}
 
-	r = read_param(_params, shift(&as), &m->test_interval, &ti->error);
-	if (r)
-		goto bad;
-
-	r = read_param(_params + 1, shift(&as), &m->nr_priority_groups, &ti->error);
+	r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error);
 	if (r)
 		goto bad;
 
@@ -747,6 +543,32 @@
 	return NULL;
 }
 
+static void fail_path(struct path *path)
+{
+	unsigned long flags;
+	struct multipath *m;
+
+	spin_lock_irqsave(&path->failed_lock, flags);
+
+	/* FIXME: path->fail_count is brain dead */
+	if (!path->has_failed && !--path->fail_count) {
+		path->has_failed = 1;
+		path->pg->ps->type->fail_path(path->pg->ps, path);
+		path->pg->m->trigger_event = 1;
+
+		m = path->pg->m;
+		spin_lock(&m->lock);
+		m->nr_valid_paths--;
+
+		if (path == m->current_path)
+			m->current_path = NULL;
+
+		spin_unlock(&m->lock);
+	}
+
+	spin_unlock_irqrestore(&path->failed_lock, flags);
+}
+
 static int multipath_end_io(struct dm_target *ti, struct bio *bio,
 			    int error, union map_info *map_context)
 {
@@ -755,7 +577,7 @@
 
 	if (error) {
 		spin_lock(&m->lock);
-		if (!m->nr_valid_paths && (m->nr_tested_paths == m->nr_paths)) {
+		if (!m->nr_valid_paths) {
 			spin_unlock(&m->lock);
 			return -EIO;
 		}
@@ -776,27 +598,12 @@
 	return 0;
 }
 
-static void lock_path(struct path *p) {down(&p->test_lock);}
-static void unlock_path(struct path *p) {up(&p->test_lock);}
-
-static void multipath_suspend(struct dm_target *ti)
-{
-	struct multipath *m = (struct multipath *) ti->private;
-	iterate_paths(m, lock_path);
-}
-
-static void multipath_resume(struct dm_target *ti)
-{
-	struct multipath *m = (struct multipath *) ti->private;
-	iterate_paths(m, unlock_path);
-}
-
 /*
  * Info string has the following format:
- * num_groups [num_paths num_selector_args [path_dev A|F fail_count fail_total [selector_args]* ]+ ]+
+ * num_groups [num_paths num_selector_args [path_dev A|F fail_count [selector_args]* ]+ ]+
  *
  * Table string has the following format (identical to the constructor string):
- * test_interval num_groups [priority selector-name num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
+ * num_groups [priority selector-name num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
  */
 static int multipath_status(struct dm_target *ti, status_type_t type,
 			    char *result, unsigned int maxlen)
@@ -821,9 +628,9 @@
 				format_dev_t(buffer, p->dev->bdev->bd_dev);
 				spin_lock_irqsave(&p->failed_lock, flags);
 				sz += snprintf(result + sz, maxlen - sz,
-					       "%s %s %u %u ", buffer,
+					       "%s %s %u ", buffer,
 					       p->has_failed ? "F" : "A",
-					       p->fail_count, p->fail_total);
+					       p->fail_count);
 				pg->ps->type->status(pg->ps, p, type,
 						     result + sz, maxlen - sz);
 				spin_unlock_irqrestore(&p->failed_lock, flags);
@@ -837,8 +644,7 @@
 		break;
 
 	case STATUSTYPE_TABLE:
-		sz += snprintf(result + sz, maxlen - sz, "%u %u ",
-			       m->test_interval, m->nr_priority_groups);
+		sz += snprintf(result + sz, maxlen - sz, "%u ", m->nr_priority_groups);
 
 		list_for_each_entry(pg, &m->priority_groups, list) {
 			sz += snprintf(result + sz, maxlen - sz, "%u %s %u %u ",
@@ -875,8 +681,6 @@
 	.dtr = multipath_dtr,
 	.map = multipath_map,
 	.end_io = multipath_end_io,
-	.suspend = multipath_suspend,
-	.resume = multipath_resume,
 	.status = multipath_status,
 };
 
@@ -926,4 +730,3 @@
 MODULE_DESCRIPTION(DM_NAME " multipath target");
 MODULE_AUTHOR("Sistina software <dm@uk.sistina.com>");
 MODULE_LICENSE("GPL");
-
--- diff/drivers/md/dm-path-selector.c	2004-02-09 11:27:38.000000000 +0000
+++ source/drivers/md/dm-path-selector.c	2004-02-13 16:13:58.000000000 +0000
@@ -237,8 +237,7 @@
 	return 0;
 }
 
-static void rr_set_path_state(struct path_selector *ps,
-			      struct path *p, int valid)
+static void rr_fail_path(struct path_selector *ps, struct path *p)
 {
 	unsigned long flags;
 	struct selector *s = (struct selector *) ps->context;
@@ -257,8 +256,7 @@
 		DMWARN("asked to change the state of an unknown path");
 
 	else
-		list_move(&pi->list,
-			  valid ? &s->valid_paths : &s->invalid_paths);
+		list_move(&pi->list, &s->invalid_paths);
 
 	spin_unlock_irqrestore(&s->lock, flags);
 }
@@ -294,7 +292,7 @@
 	.ctr = rr_ctr,
 	.dtr = rr_dtr,
 	.add_path = rr_add_path,
-	.set_path_state = rr_set_path_state,
+	.fail_path = rr_fail_path,
 	.select_path = rr_select_path,
 	.status = rr_status,
 };
--- diff/drivers/md/dm-path-selector.h	2004-02-09 11:32:28.000000000 +0000
+++ source/drivers/md/dm-path-selector.h	2004-02-13 16:10:55.000000000 +0000
@@ -54,8 +54,8 @@
 /*
  * Notify the selector that a path has failed.
  */
-typedef	void (*ps_set_path_state_fn) (struct path_selector *ps,
-				      struct path *p, int valid);
+typedef	void (*ps_fail_path_fn) (struct path_selector *ps,
+				 struct path *p);
 
 /*
  * Table content based on parameters added in ps_add_path_fn
@@ -75,7 +75,7 @@
 	ps_dtr_fn dtr;
 
 	ps_add_path_fn add_path;
-	ps_set_path_state_fn set_path_state;
+	ps_fail_path_fn fail_path;
 	ps_select_path_fn select_path;
 	ps_status_fn status;
 };
