From: Alasdair G Kergon <[email-masked]>

Introduce the concept of a singleton table which contains exactly one target.

If a target type sets the DM_TARGET_SINGLETON feature bit device-mapper
will ensure that any table that includes that target contains no others.

The thin provisioning pool target uses this.

Signed-off-by: Alasdair G Kergon <[email-masked]>
---
 drivers/md/dm-table.c         |   16 ++++++++++++++++
 include/linux/device-mapper.h |   14 ++++++++++----
 2 files changed, 26 insertions(+), 4 deletions(-)

Index: linux/drivers/md/dm-table.c
===================================================================
--- linux.orig/drivers/md/dm-table.c
+++ linux/drivers/md/dm-table.c
@@ -55,6 +55,7 @@ struct dm_table {
 	struct dm_target *targets;
 
 	unsigned integrity_supported:1;
+	unsigned singleton:1;
 
 	/*
 	 * Indicates the rw permissions for the new logical
@@ -740,6 +741,12 @@ int dm_table_add_target(struct dm_table 
 	char **argv;
 	struct dm_target *tgt;
 
+	if (t->singleton) {
+		DMERR("%s: target type %s must appear alone in table",
+		      dm_device_name(t->md), t->targets->type->name);
+		return -EINVAL;
+	}
+
 	if ((r = check_space(t)))
 		return r;
 
@@ -758,6 +765,15 @@ int dm_table_add_target(struct dm_table 
 		return -EINVAL;
 	}
 
+	if (dm_target_needs_singleton(tgt->type)) {
+		if (t->num_targets) {
+			DMERR("%s: target type %s must appear alone in table",
+			      dm_device_name(t->md), type);
+			return -EINVAL;
+		}
+		t->singleton = 1;
+	}
+
 	tgt->table = t;
 	tgt->begin = start;
 	tgt->len = len;
Index: linux/include/linux/device-mapper.h
===================================================================
--- linux.orig/include/linux/device-mapper.h
+++ linux/include/linux/device-mapper.h
@@ -128,10 +128,6 @@ void dm_put_device(struct dm_target *ti,
  * Information about a target type
  */
 
-/*
- * Target features
- */
-
 struct target_type {
 	uint64_t features;
 	const char *name;
@@ -160,6 +156,16 @@ struct target_type {
 	struct list_head list;
 };
 
+/*
+ * Target features
+ */
+
+/*
+ * Any table that contains an instance of this target must have only one.
+ */
+#define DM_TARGET_SINGLETON		0x00000001
+#define dm_target_needs_singleton(type)	((type)->features & DM_TARGET_SINGLETON)
+
 struct dm_target {
 	struct dm_table *table;
 	struct target_type *type;