]> Pileus Git - ~andy/linux/blobdiff - drivers/md/dm-table.c
Merge git://git.infradead.org/mtd-2.6
[~andy/linux] / drivers / md / dm-table.c
index 2ec3482e942a9f0b767f79cb45d5e857e225ec2e..8e91321301424afda07c456a8b6ae53aec524d04 100644 (file)
@@ -54,6 +54,7 @@ struct dm_table {
        sector_t *highs;
        struct dm_target *targets;
 
+       struct target_type *immutable_target_type;
        unsigned integrity_supported:1;
        unsigned singleton:1;
 
@@ -774,6 +775,27 @@ int dm_table_add_target(struct dm_table *t, const char *type,
                t->singleton = 1;
        }
 
+       if (dm_target_always_writeable(tgt->type) && !(t->mode & FMODE_WRITE)) {
+               DMERR("%s: target type %s may not be included in read-only tables",
+                     dm_device_name(t->md), type);
+               return -EINVAL;
+       }
+
+       if (t->immutable_target_type) {
+               if (t->immutable_target_type != tgt->type) {
+                       DMERR("%s: immutable target type %s cannot be mixed with other target types",
+                             dm_device_name(t->md), t->immutable_target_type->name);
+                       return -EINVAL;
+               }
+       } else if (dm_target_is_immutable(tgt->type)) {
+               if (t->num_targets) {
+                       DMERR("%s: immutable target type %s cannot be mixed with other target types",
+                             dm_device_name(t->md), tgt->type->name);
+                       return -EINVAL;
+               }
+               t->immutable_target_type = tgt->type;
+       }
+
        tgt->table = t;
        tgt->begin = start;
        tgt->len = len;
@@ -931,6 +953,11 @@ unsigned dm_table_get_type(struct dm_table *t)
        return t->type;
 }
 
+struct target_type *dm_table_get_immutable_target_type(struct dm_table *t)
+{
+       return t->immutable_target_type;
+}
+
 bool dm_table_request_based(struct dm_table *t)
 {
        return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;