dm: set DM_TARGET_WILDCARD feature on "error" target
authorMike Snitzer <snitzer@redhat.com>
Sat, 6 Feb 2016 23:38:46 +0000 (18:38 -0500)
committerMike Snitzer <snitzer@redhat.com>
Mon, 22 Feb 2016 16:06:21 +0000 (11:06 -0500)
The DM_TARGET_WILDCARD feature indicates that the "error" target may
replace any target; even immutable targets.  This feature will be useful
to preserve the ability to replace the "multipath" target even once it
is formally converted over to having the DM_TARGET_IMMUTABLE feature.

Also, implicit in the DM_TARGET_WILDCARD feature flag being set is that
.map, .map_rq, .clone_and_map_rq and .release_clone_rq are all defined
in the target_type.

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/dm-ioctl.c
drivers/md/dm-table.c
drivers/md/dm-target.c
drivers/md/dm.h
include/linux/device-mapper.h

index 80a43954325966a872cf8ebc95fb23c92c0b8819..4763c4ae30e434e181b7f91838309c75c2126952 100644 (file)
@@ -1291,7 +1291,8 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
 
        immutable_target_type = dm_get_immutable_target_type(md);
        if (immutable_target_type &&
-           (immutable_target_type != dm_table_get_immutable_target_type(t))) {
+           (immutable_target_type != dm_table_get_immutable_target_type(t)) &&
+           !dm_table_get_wildcard_target(t)) {
                DMWARN("can't replace immutable target type %s",
                       immutable_target_type->name);
                r = -EINVAL;
index 061152a437300bbfacfbbc6e475c3935df7cecb6..a49e62b8611f2ed11bde45153b158d766534531f 100644 (file)
@@ -920,6 +920,20 @@ struct target_type *dm_table_get_immutable_target_type(struct dm_table *t)
        return t->immutable_target_type;
 }
 
+struct dm_target *dm_table_get_wildcard_target(struct dm_table *t)
+{
+       struct dm_target *uninitialized_var(ti);
+       unsigned i = 0;
+
+       while (i < dm_table_get_num_targets(t)) {
+               ti = dm_table_get_target(t, i++);
+               if (dm_target_is_wildcard(ti->type))
+                       return ti;
+       }
+
+       return NULL;
+}
+
 bool dm_table_request_based(struct dm_table *t)
 {
        return __table_type_request_based(dm_table_get_type(t));
index 925ec1b15e75ede24ea91c74667d426950af251e..a317dd884ba6b5aca1b1355e7537b28bfa5c1bd4 100644 (file)
@@ -150,7 +150,8 @@ static void io_err_release_clone_rq(struct request *clone)
 
 static struct target_type error_target = {
        .name = "error",
-       .version = {1, 3, 0},
+       .version = {1, 4, 0},
+       .features = DM_TARGET_WILDCARD,
        .ctr  = io_err_ctr,
        .dtr  = io_err_dtr,
        .map  = io_err_map,
index 7edcf97dfa5a66fc93b964c4f16671d72a17e5a8..53df2585571bac681caaa0c0d7e052db92cb32c3 100644 (file)
@@ -73,6 +73,7 @@ int dm_table_resume_targets(struct dm_table *t);
 int dm_table_any_congested(struct dm_table *t, int bdi_bits);
 unsigned dm_table_get_type(struct dm_table *t);
 struct target_type *dm_table_get_immutable_target_type(struct dm_table *t);
+struct dm_target *dm_table_get_wildcard_target(struct dm_table *t);
 bool dm_table_request_based(struct dm_table *t);
 bool dm_table_mq_request_based(struct dm_table *t);
 void dm_table_free_md_mempools(struct dm_table *t);
index ec1c61c87d8974897af2be54af23588f14746777..87d50ecbc9df1aa317c95cdd12339152d49fc4fe 100644 (file)
@@ -189,6 +189,13 @@ struct target_type {
 #define DM_TARGET_IMMUTABLE            0x00000004
 #define dm_target_is_immutable(type)   ((type)->features & DM_TARGET_IMMUTABLE)
 
+/*
+ * Indicates that a target may replace any target; even immutable targets.
+ * .map, .map_rq, .clone_and_map_rq and .release_clone_rq are all defined.
+ */
+#define DM_TARGET_WILDCARD             0x00000008
+#define dm_target_is_wildcard(type)    ((type)->features & DM_TARGET_WILDCARD)
+
 /*
  * Some targets need to be sent the same WRITE bio severals times so
  * that they can send copies of it to different devices.  This function