aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-ioctl.c11
-rw-r--r--drivers/md/dm-table.c21
-rw-r--r--drivers/md/dm.c9
-rw-r--r--drivers/md/dm.h2
-rw-r--r--include/linux/device-mapper.h7
-rw-r--r--include/linux/dm-ioctl.h4
6 files changed, 52 insertions, 2 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 2e9a3ca37bdd..31c2dc25886d 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1215,6 +1215,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
1215 struct hash_cell *hc; 1215 struct hash_cell *hc;
1216 struct dm_table *t; 1216 struct dm_table *t;
1217 struct mapped_device *md; 1217 struct mapped_device *md;
1218 struct target_type *immutable_target_type;
1218 1219
1219 md = find_device(param); 1220 md = find_device(param);
1220 if (!md) 1221 if (!md)
@@ -1230,6 +1231,16 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
1230 goto out; 1231 goto out;
1231 } 1232 }
1232 1233
1234 immutable_target_type = dm_get_immutable_target_type(md);
1235 if (immutable_target_type &&
1236 (immutable_target_type != dm_table_get_immutable_target_type(t))) {
1237 DMWARN("can't replace immutable target type %s",
1238 immutable_target_type->name);
1239 dm_table_destroy(t);
1240 r = -EINVAL;
1241 goto out;
1242 }
1243
1233 /* Protect md->type and md->queue against concurrent table loads. */ 1244 /* Protect md->type and md->queue against concurrent table loads. */
1234 dm_lock_md_type(md); 1245 dm_lock_md_type(md);
1235 if (dm_get_md_type(md) == DM_TYPE_NONE) 1246 if (dm_get_md_type(md) == DM_TYPE_NONE)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 9917141729ef..8e9132130142 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -54,6 +54,7 @@ struct dm_table {
54 sector_t *highs; 54 sector_t *highs;
55 struct dm_target *targets; 55 struct dm_target *targets;
56 56
57 struct target_type *immutable_target_type;
57 unsigned integrity_supported:1; 58 unsigned integrity_supported:1;
58 unsigned singleton:1; 59 unsigned singleton:1;
59 60
@@ -780,6 +781,21 @@ int dm_table_add_target(struct dm_table *t, const char *type,
780 return -EINVAL; 781 return -EINVAL;
781 } 782 }
782 783
784 if (t->immutable_target_type) {
785 if (t->immutable_target_type != tgt->type) {
786 DMERR("%s: immutable target type %s cannot be mixed with other target types",
787 dm_device_name(t->md), t->immutable_target_type->name);
788 return -EINVAL;
789 }
790 } else if (dm_target_is_immutable(tgt->type)) {
791 if (t->num_targets) {
792 DMERR("%s: immutable target type %s cannot be mixed with other target types",
793 dm_device_name(t->md), tgt->type->name);
794 return -EINVAL;
795 }
796 t->immutable_target_type = tgt->type;
797 }
798
783 tgt->table = t; 799 tgt->table = t;
784 tgt->begin = start; 800 tgt->begin = start;
785 tgt->len = len; 801 tgt->len = len;
@@ -937,6 +953,11 @@ unsigned dm_table_get_type(struct dm_table *t)
937 return t->type; 953 return t->type;
938} 954}
939 955
956struct target_type *dm_table_get_immutable_target_type(struct dm_table *t)
957{
958 return t->immutable_target_type;
959}
960
940bool dm_table_request_based(struct dm_table *t) 961bool dm_table_request_based(struct dm_table *t)
941{ 962{
942 return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED; 963 return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 2fe3017ba97c..9836324e2118 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -140,6 +140,8 @@ struct mapped_device {
140 /* Protect queue and type against concurrent access. */ 140 /* Protect queue and type against concurrent access. */
141 struct mutex type_lock; 141 struct mutex type_lock;
142 142
143 struct target_type *immutable_target_type;
144
143 struct gendisk *disk; 145 struct gendisk *disk;
144 char name[16]; 146 char name[16];
145 147
@@ -2096,6 +2098,8 @@ static struct dm_table *__bind(struct mapped_device *md, struct dm_table *t,
2096 write_lock_irqsave(&md->map_lock, flags); 2098 write_lock_irqsave(&md->map_lock, flags);
2097 old_map = md->map; 2099 old_map = md->map;
2098 md->map = t; 2100 md->map = t;
2101 md->immutable_target_type = dm_table_get_immutable_target_type(t);
2102
2099 dm_table_set_restrictions(t, q, limits); 2103 dm_table_set_restrictions(t, q, limits);
2100 if (merge_is_optional) 2104 if (merge_is_optional)
2101 set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags); 2105 set_bit(DMF_MERGE_IS_OPTIONAL, &md->flags);
@@ -2166,6 +2170,11 @@ unsigned dm_get_md_type(struct mapped_device *md)
2166 return md->type; 2170 return md->type;
2167} 2171}
2168 2172
2173struct target_type *dm_get_immutable_target_type(struct mapped_device *md)
2174{
2175 return md->immutable_target_type;
2176}
2177
2169/* 2178/*
2170 * Fully initialize a request-based queue (->elevator, ->request_fn, etc). 2179 * Fully initialize a request-based queue (->elevator, ->request_fn, etc).
2171 */ 2180 */
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 6745dbd278a4..b7dacd59d8d7 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -60,6 +60,7 @@ int dm_table_resume_targets(struct dm_table *t);
60int dm_table_any_congested(struct dm_table *t, int bdi_bits); 60int dm_table_any_congested(struct dm_table *t, int bdi_bits);
61int dm_table_any_busy_target(struct dm_table *t); 61int dm_table_any_busy_target(struct dm_table *t);
62unsigned dm_table_get_type(struct dm_table *t); 62unsigned dm_table_get_type(struct dm_table *t);
63struct target_type *dm_table_get_immutable_target_type(struct dm_table *t);
63bool dm_table_request_based(struct dm_table *t); 64bool dm_table_request_based(struct dm_table *t);
64bool dm_table_supports_discards(struct dm_table *t); 65bool dm_table_supports_discards(struct dm_table *t);
65int dm_table_alloc_md_mempools(struct dm_table *t); 66int dm_table_alloc_md_mempools(struct dm_table *t);
@@ -72,6 +73,7 @@ void dm_lock_md_type(struct mapped_device *md);
72void dm_unlock_md_type(struct mapped_device *md); 73void dm_unlock_md_type(struct mapped_device *md);
73void dm_set_md_type(struct mapped_device *md, unsigned type); 74void dm_set_md_type(struct mapped_device *md, unsigned type);
74unsigned dm_get_md_type(struct mapped_device *md); 75unsigned dm_get_md_type(struct mapped_device *md);
76struct target_type *dm_get_immutable_target_type(struct mapped_device *md);
75 77
76int dm_setup_md_queue(struct mapped_device *md); 78int dm_setup_md_queue(struct mapped_device *md);
77 79
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index cc58e2d7c032..98f34b886f95 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -173,6 +173,13 @@ struct target_type {
173#define dm_target_always_writeable(type) \ 173#define dm_target_always_writeable(type) \
174 ((type)->features & DM_TARGET_ALWAYS_WRITEABLE) 174 ((type)->features & DM_TARGET_ALWAYS_WRITEABLE)
175 175
176/*
177 * Any device that contains a table with an instance of this target may never
178 * have tables containing any different target type.
179 */
180#define DM_TARGET_IMMUTABLE 0x00000004
181#define dm_target_is_immutable(type) ((type)->features & DM_TARGET_IMMUTABLE)
182
176struct dm_target { 183struct dm_target {
177 struct dm_table *table; 184 struct dm_table *table;
178 struct target_type *type; 185 struct target_type *type;
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index 0cb8eff76bd6..75fd5573516e 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -267,9 +267,9 @@ enum {
267#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) 267#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
268 268
269#define DM_VERSION_MAJOR 4 269#define DM_VERSION_MAJOR 4
270#define DM_VERSION_MINOR 21 270#define DM_VERSION_MINOR 22
271#define DM_VERSION_PATCHLEVEL 0 271#define DM_VERSION_PATCHLEVEL 0
272#define DM_VERSION_EXTRA "-ioctl (2011-07-06)" 272#define DM_VERSION_EXTRA "-ioctl (2011-10-19)"
273 273
274/* Status bits */ 274/* Status bits */
275#define DM_READONLY_FLAG (1 << 0) /* In/Out */ 275#define DM_READONLY_FLAG (1 << 0) /* In/Out */