From: David Teigland <[email-masked]>

Attached two patches:
  dm-error-device.patch - adds dm_error_device() function that gfs
  can call to shut down access to a device.

  dm-error-device-symbols.patch - exports symbols so gfs can call
  dm_error_device() on its fs device.

I've tested this minimally with dmsetup by setting up a dm device, starting a
write to it with dd, then installing the following module to force the device
to shut down and return errors, and removing the device when I'm done.

The GFS code will want to include a header with prototypes for the functions
exported by the second patch.  Currently that's dm.h, should those prototypes
be moved to device-mapper.h?

Index: linux-2.6.16-rc5/drivers/md/dm.c
===================================================================
--- linux-2.6.16-rc5.orig/drivers/md/dm.c	2006-03-14 18:25:47.000000000 +0000
+++ linux-2.6.16-rc5/drivers/md/dm.c	2006-03-15 23:31:07.000000000 +0000
@@ -1262,6 +1262,38 @@ out:
 	return r;
 }
 
+int dm_error_device(struct mapped_device *md)
+{
+	struct dm_table *t;
+	sector_t dev_size = 0;
+	int r;
+
+	t = dm_get_table(md);
+	if (t) {
+		dev_size = dm_table_get_size(t);
+		dm_table_put(t);
+	}
+
+	r = dm_table_create(&t, FMODE_READ, 1);
+	if (r)
+		goto out;
+
+	r = dm_table_add_target(t, "error", 0, dev_size, NULL);
+	if (r)
+		goto out;
+
+	r = dm_table_complete(t);
+	if (r)
+		goto out;
+
+	r = dm_swap_table(md, t);
+
+out:
+	if (r && t)
+		dm_table_put(t);
+	return r;
+}
+
 /*-----------------------------------------------------------------
  * Event notification.
  *---------------------------------------------------------------*/
@@ -1298,6 +1330,11 @@ static struct block_device_operations dm
 };
 
 EXPORT_SYMBOL(dm_get_mapinfo);
+EXPORT_SYMBOL_GPL(dm_get_md);
+EXPORT_SYMBOL_GPL(dm_suspend);
+EXPORT_SYMBOL_GPL(dm_resume);
+EXPORT_SYMBOL_GPL(dm_error_device);
+EXPORT_SYMBOL_GPL(dm_put);
 
 /*
  * module hooks
Index: linux-2.6.16-rc5/drivers/md/dm.h
===================================================================
--- linux-2.6.16-rc5.orig/drivers/md/dm.h	2006-03-14 18:25:47.000000000 +0000
+++ linux-2.6.16-rc5/drivers/md/dm.h	2006-03-15 23:31:07.000000000 +0000
@@ -92,6 +92,11 @@ int dm_suspended(struct mapped_device *m
 int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo);
 int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo);
 
+/*
+ * Make a device return errors.
+ */
+int dm_error_device(struct mapped_device *md);
+
 /*-----------------------------------------------------------------
  * Functions for manipulating a table.  Tables are also reference
  * counted.
Index: linux-2.6.16-rc5/drivers/md/dm-table.c
===================================================================
--- linux-2.6.16-rc5.orig/drivers/md/dm-table.c	2006-03-14 18:30:15.000000000 +0000
+++ linux-2.6.16-rc5/drivers/md/dm-table.c	2006-03-15 23:31:07.000000000 +0000
@@ -591,6 +591,12 @@ int dm_split_args(int *argc, char ***arg
 	char *start, *end = input, *out, **argv = NULL;
 	unsigned array_size = 0;
 
+	if (!input) {
+		*argvp = NULL;
+		*argc = 0;
+		return 0;
+	}
+
 	*argc = 0;
 	argv = realloc_argv(&array_size, argv);
 	if (!argv)