diff options
-rw-r--r-- | drivers/md/dm-ioctl.c | 11 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 21 | ||||
-rw-r--r-- | drivers/md/dm.c | 9 | ||||
-rw-r--r-- | drivers/md/dm.h | 2 | ||||
-rw-r--r-- | include/linux/device-mapper.h | 7 | ||||
-rw-r--r-- | include/linux/dm-ioctl.h | 4 |
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 | ||
956 | struct target_type *dm_table_get_immutable_target_type(struct dm_table *t) | ||
957 | { | ||
958 | return t->immutable_target_type; | ||
959 | } | ||
960 | |||
940 | bool dm_table_request_based(struct dm_table *t) | 961 | bool 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 | ||
2173 | struct 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); | |||
60 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); | 60 | int dm_table_any_congested(struct dm_table *t, int bdi_bits); |
61 | int dm_table_any_busy_target(struct dm_table *t); | 61 | int dm_table_any_busy_target(struct dm_table *t); |
62 | unsigned dm_table_get_type(struct dm_table *t); | 62 | unsigned dm_table_get_type(struct dm_table *t); |
63 | struct target_type *dm_table_get_immutable_target_type(struct dm_table *t); | ||
63 | bool dm_table_request_based(struct dm_table *t); | 64 | bool dm_table_request_based(struct dm_table *t); |
64 | bool dm_table_supports_discards(struct dm_table *t); | 65 | bool dm_table_supports_discards(struct dm_table *t); |
65 | int dm_table_alloc_md_mempools(struct dm_table *t); | 66 | int dm_table_alloc_md_mempools(struct dm_table *t); |
@@ -72,6 +73,7 @@ void dm_lock_md_type(struct mapped_device *md); | |||
72 | void dm_unlock_md_type(struct mapped_device *md); | 73 | void dm_unlock_md_type(struct mapped_device *md); |
73 | void dm_set_md_type(struct mapped_device *md, unsigned type); | 74 | void dm_set_md_type(struct mapped_device *md, unsigned type); |
74 | unsigned dm_get_md_type(struct mapped_device *md); | 75 | unsigned dm_get_md_type(struct mapped_device *md); |
76 | struct target_type *dm_get_immutable_target_type(struct mapped_device *md); | ||
75 | 77 | ||
76 | int dm_setup_md_queue(struct mapped_device *md); | 78 | int 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 | |||
176 | struct dm_target { | 183 | struct 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 */ |