Change message ioctl to use argc/argv;
Remove test implementation from dm-zero;
Add reinstate message to dm-mpath.
--- diff/drivers/md/dm-ioctl.c	2004-09-28 20:40:32.000000000 +0100
+++ source/drivers/md/dm-ioctl.c	2004-09-28 19:49:52.000000000 +0100
@@ -1102,7 +1102,8 @@
  */
 static int target_message(struct dm_ioctl *param, size_t param_size)
 {
-	int r;
+	int r, argc;
+	char **argv;
 	struct mapped_device *md;
 	struct dm_table *table;
 	struct dm_target *ti;
@@ -1123,9 +1124,15 @@
 		goto out;
 	}
 
+	r = dm_split_args(&argc, &argv, tmsg->message);
+	if (r) {
+		DMWARN("Failed to split target message parameters");
+		goto out;
+	}
+
 	table = dm_get_table(md);
 	if (!table)
-		goto out;
+		goto out_argv;
 
 	if (tmsg->sector >= dm_table_get_size(table)) {
 		DMWARN("Target message sector outside device.");
@@ -1135,7 +1142,7 @@
 
 	ti = dm_table_find_target(table, tmsg->sector);
 	if (ti->type->message)
-		r = ti->type->message(ti, tmsg->message);
+		r = ti->type->message(ti, argc, argv);
 	else {
 		DMWARN("Target type does not support messages");
 		r = -EINVAL;
@@ -1143,7 +1150,8 @@
 
  out_table:
 	dm_table_put(table);
-
+ out_argv:
+	kfree(argv);
  out:
 	param->data_size = 0;
 	dm_put(md);
--- diff/drivers/md/dm-mpath.c	2004-09-28 20:40:32.000000000 +0100
+++ source/drivers/md/dm-mpath.c	2004-09-28 20:41:36.000000000 +0100
@@ -542,6 +542,25 @@
 	return r;
 }
 
+/*
+ * Reinstate all matching failed paths
+ */
+static int reinstate_dev(struct multipath *m, struct dm_dev *dev)
+{
+	int r = 0;
+	struct path *path;
+	struct priority_group *pg;
+
+	list_for_each_entry(pg, &m->priority_groups, list) {
+		list_for_each_entry(path, &pg->paths, list) {
+			if (path->dev == dev)
+				r = reinstate_path(path);
+		}
+	}
+
+	return r;
+}
+
 static int do_end_io(struct multipath *m, struct bio *bio,
 		     int error, struct mpath_io *mpio)
 {
@@ -647,6 +666,32 @@
 	return 0;
 }
 
+static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r;
+	struct dm_dev *dev;
+	struct multipath *m = (struct multipath *) ti->private;
+
+	if (argc != 2 || strnicmp(argv[0], "reinstate", 10)) {
+		DMWARN("Unrecognised multipath message received.");
+		return -EINVAL;
+	}
+
+	r = dm_get_device(ti, argv[1], ti->begin, ti->len,
+			  dm_table_get_mode(ti->table), &dev);
+	if (r) {
+		DMWARN("dm-multipath message: error getting device %s",
+		       argv[1]);
+		return -EINVAL;
+	}
+
+	r = reinstate_dev(m, dev);
+
+	dm_put_device(ti, dev);
+
+	return r;
+}
+
 /*-----------------------------------------------------------------
  * Module setup
  *---------------------------------------------------------------*/
@@ -659,6 +704,7 @@
 	.map = multipath_map,
 	.end_io = multipath_end_io,
 	.status = multipath_status,
+	.message = multipath_message,
 };
 
 static int __init dm_multipath_init(void)
--- diff/drivers/md/dm-table.c	2004-09-28 20:40:32.000000000 +0100
+++ source/drivers/md/dm-table.c	2004-09-28 19:49:55.000000000 +0100
@@ -575,7 +575,7 @@
 /*
  * Destructively splits up the argument list to pass to ctr.
  */
-static int split_args(int *argc, char ***argvp, char *input)
+int dm_split_args(int *argc, char ***argvp, char *input)
 {
 	char *start, *end = input, *out, **argv = NULL;
 	unsigned array_size = 0;
@@ -688,7 +688,7 @@
 		goto bad;
 	}
 
-	r = split_args(&argc, &argv, params);
+	r = dm_split_args(&argc, &argv, params);
 	if (r) {
 		tgt->error = "couldn't split parameters (insufficient memory)";
 		goto bad;
--- diff/drivers/md/dm-zero.c	2004-09-28 20:40:32.000000000 +0100
+++ source/drivers/md/dm-zero.c	2004-09-28 20:39:55.000000000 +0100
@@ -64,19 +64,12 @@
 	return 0;
 }
 
-static int zero_message(struct dm_target *ti, char *message)
-{
-	DMERR("dm-zero message received: %s", message);
-	return 0;
-}
-
 static struct target_type zero_target = {
 	.name   = "zero",
 	.version = {1, 0, 0},
 	.module = THIS_MODULE,
 	.ctr    = zero_ctr,
 	.map    = zero_map,
-	.message = zero_message,
 };
 
 int __init dm_zero_init(void)
--- diff/drivers/md/dm.h	2004-09-28 20:40:32.000000000 +0100
+++ source/drivers/md/dm.h	2004-09-28 19:43:37.000000000 +0100
@@ -165,6 +165,8 @@
 	return (n << 9);
 }
 
+int dm_split_args(int *argc, char ***argvp, char *input);
+
 /*
  * The device-mapper can be driven through one of two interfaces;
  * ioctl or filesystem, depending which patch you have applied.
--- diff/include/linux/device-mapper.h	2004-09-28 20:40:32.000000000 +0100
+++ source/include/linux/device-mapper.h	2004-09-28 19:55:13.000000000 +0100
@@ -57,7 +57,7 @@
 typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type,
 			     char *result, unsigned int maxlen);
 
-typedef int (*dm_message_fn) (struct dm_target *ti, char *message);
+typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);
 
 void dm_error(const char *message);