mpath bug fixes
--- diff/drivers/md/dm-mpath.c	2003-12-29 10:16:52.000000000 +0000
+++ source/drivers/md/dm-mpath.c	2003-12-29 10:16:58.000000000 +0000
@@ -78,7 +78,7 @@
 		}
 
 		path->test_page = alloc_page(GFP_KERNEL);
-		if (!p->test_page) {
+		if (!path->test_page) {
 			bio_put(path->test_bio);
 			kfree(path);
 			return NULL;
@@ -92,7 +92,7 @@
 {
 	ClearPageLocked(p->test_page);
 	__free_page(p->test_page);
-	bio_put(&p->test_bio);
+	bio_put(p->test_bio);
 	kfree(p);
 }
 
@@ -101,10 +101,18 @@
 	struct priority_group *pg;
 
 	pg = kmalloc(sizeof(*pg), GFP_KERNEL);
-	if (pg) {
-		INIT_LIST_HEAD(&pg->valid_paths);
-		INIT_LIST_HEAD(&pg->invalid_paths);
+	if (!pg)
+		return NULL;
+
+	pg->ps = kmalloc(sizeof(*pg->ps), GFP_KERNEL);
+	if (!pg->ps) {
+		kfree(pg);
+		return NULL;
 	}
+	memset(pg->ps, 0, sizeof(*pg->ps));
+
+	INIT_LIST_HEAD(&pg->valid_paths);
+	INIT_LIST_HEAD(&pg->invalid_paths);
 
 	return pg;
 }
@@ -123,11 +131,14 @@
 static void free_priority_group(struct priority_group *pg,
 				struct dm_target *ti)
 {
-	struct path_selector *ps = &pg->ps;
+	struct path_selector *ps = pg->ps;
 
-???	if (ps) {
-		ps->type->dtr(ps);
-		dm_put_path_selector(ps->type);
+	if (ps) {
+		if (ps->type) {
+			ps->type->dtr(ps);
+			dm_put_path_selector(ps->type);
+		}
+		kfree(ps);
 	}
 
 	free_paths(&pg->valid_paths, ti);
@@ -178,12 +189,11 @@
 	path->has_failed = 1;
 //	path->fail_time = jiffies;
 	atomic_inc(&path->fail_total);
-	list_del(&path->list);
-	list_add(&path->list, &path->pg->invalid_paths);
-	path->pg->ps.type->set_path_state(&path->pg->ps, path, 0);
+	list_move(&path->list, &path->pg->invalid_paths);
+	path->pg->ps->type->set_path_state(path->pg->ps, path, 0);
 }
 
-static void test_endio(struct bio *bio, unsigned int done, int error)
+static int test_endio(struct bio *bio, unsigned int done, int error)
 {
 	struct path *path = (struct path *) bio->bi_private;
 
@@ -193,7 +203,8 @@
 	if (error)
 		__fail_path(path);
 
-	up(&p->test_lock);
+	up(&path->test_lock);
+	return 0;
 }
 
 static void test_path(struct path *p)
@@ -201,7 +212,7 @@
 	if (down_trylock(&p->test_lock))
 		return;		/* last test io still pending */
 
-	submit_bio(p->test_bio);
+	generic_make_request(p->test_bio);
 }
 
 /*-----------------------------------------------------------------
@@ -257,7 +268,7 @@
 		iterate_paths(m, test_path);
 
 		if (atomic_dec_and_test(&m->trigger_event))
-			dm_table_event(m->ti);
+			dm_table_event(m->ti->table);
 	}
 	spin_unlock(&_mpath_lock);
 
@@ -298,9 +309,13 @@
 
 static char *shift(struct arg_set *as)
 {
+	char *r;
+
 	if (as->argc) {
 		as->argc--;
-		return *as->argv++;
+		r = *as->argv;
+		as->argv++;
+		return r;
 	}
 
 	return NULL;
@@ -317,12 +332,12 @@
 {
 	struct bio *bio = p->test_bio;
 
-	bio->bi_sector = 0
+	bio->bi_sector = 0;
 	bio->bi_rw |= (1 << BIO_RW_FAILFAST);
-	bio->bi_bdev = path->dev->bdev;
+	bio->bi_bdev = p->dev->bdev;
 	bio->bi_end_io = test_endio;
 	bio->bi_private = p;
-	bio_add_page(bio, p->test_page, ??? hard sect size ???, 0);
+	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,
@@ -371,8 +386,8 @@
 {
 	static struct param _params[] = {
 		{0, 1024, ESTR("invalid priority")},
-		{0, 1024, ESTR("invalid number of selector args")},
-		{1, 1024, ESTR("invalid number of paths")}
+		{1, 1024, ESTR("invalid number of paths")},
+		{0, 1024, ESTR("invalid number of selector args")}
 	};
 
 	int r;
@@ -381,6 +396,7 @@
 	struct path_selector_type *pst;
 
 	if (as->argc < 3) {
+		as->argc = 0;
 		ti->error = ESTR("not enough priority group aruments");
 		return NULL;
 	}
@@ -400,27 +416,28 @@
 		ti->error = ESTR("unknown path selector type");
 		goto bad;
 	}
-	pg->ps.type = pst;
 
-	r = pst->ctr(&pg->ps);
+	r = pst->ctr(pg->ps);
 	if (r) {
 		/* FIXME: need to put the pst ? fix after
 		 * factoring out the register */
 		goto bad;
 	}
+	pg->ps->type = pst;
 
-	r = read_param(_params + 1, shift(as), &nr_selector_args, &ti->error);
-	if (r)
-		goto bad;
 
 	/*
 	 * read the paths
 	 */
-	nr_params = 1 + nr_selector_args;
-	r = read_param(_params + 2, shift(as), &nr_paths, &ti->error);
+	r = read_param(_params + 1, shift(as), &nr_paths, &ti->error);
 	if (r)
 		goto bad;
 
+	r = read_param(_params + 2, shift(as), &nr_selector_args, &ti->error);
+	if (r)
+		goto bad;
+
+	nr_params = 1 + nr_selector_args;
 	for (i = 0; i < nr_paths; i++) {
 		struct path *path;
 		struct arg_set path_args;
@@ -431,7 +448,7 @@
 		path_args.argc = nr_params;
 		path_args.argv = as->argv;
 
-		path = parse_path(&path_args, &pg->ps, ti);
+		path = parse_path(&path_args, pg->ps, ti);
 		if (!path)
 			goto bad;
 
@@ -503,7 +520,9 @@
 
 	/* parse the priority groups */
 	while (as.argc) {
-		struct priority_group *pg = parse_priority_group(&as, m, ti);
+		struct priority_group *pg;
+		DMERR("calling parse priority group");
+		pg = parse_priority_group(&as, m, ti);
 		if (pg)
 			__insert_priority_group(m, pg);
 	}
@@ -557,7 +576,7 @@
 		return -EIO;
 
 	/* select a path */
-	path = pg->ps.type->select_path(&pg->ps);
+	path = pg->ps->type->select_path(pg->ps);
 	if (!path)
 		return -EIO;	/* No valid path found */
 
@@ -683,8 +702,8 @@
 	return r;
 }
 
-static void lock_path(struct path *p) {down(&path->test_lock);}
-static void unlock_path(struct path *p) {up(&path->test_lock);}
+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)
 {
@@ -715,6 +734,8 @@
 	.dtr = multipath_dtr,
 	.map = multipath_map,
 	.end_io = multipath_end_io,
+	.suspend = multipath_suspend,
+	.resume = multipath_resume,
 	.status = multipath_status,
 };
 
--- diff/drivers/md/dm-path-selector.c	2003-12-29 10:16:39.000000000 +0000
+++ source/drivers/md/dm-path-selector.c	2003-12-29 10:16:58.000000000 +0000
@@ -6,7 +6,6 @@
  * This file is released under the GPL.
  *
  * Path selector housekeeping (register/unregister/...)
- *
  */
 
 #include "dm.h"
@@ -257,10 +256,9 @@
 	if (!pi)
 		DMWARN("asked to change the state of an unknown path");
 
-	else {
-		list_del(&pi->list);
-		list_add(&pi->list, valid ? &s->valid_paths : &s->invalid_paths);
-	}
+	else
+		list_move(&pi->list,
+			  valid ? &s->valid_paths : &s->invalid_paths);
 
 	spin_unlock_irqrestore(&s->lock, flags);
 }
@@ -275,8 +273,7 @@
 	spin_lock_irqsave(&s->lock, flags);
 	if (!list_empty(&s->valid_paths)) {
 		pi = list_entry(s->valid_paths.next, struct path_info, list);
-		list_del(&pi->list);
-		list_add_tail(&pi->list, &s->valid_paths);
+		list_move_tail(&pi->list, &s->valid_paths);
 	}
 	spin_unlock_irqrestore(&s->lock, flags);