aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-ioctl.c15
-rw-r--r--drivers/md/dm.c37
-rw-r--r--drivers/md/dm.h5
-rw-r--r--include/linux/dm-ioctl.h4
4 files changed, 52 insertions, 9 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 3fd8f0e169e7..4702f380cb45 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1189,6 +1189,21 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
1189 goto out; 1189 goto out;
1190 } 1190 }
1191 1191
1192 /* Protect md->type against concurrent table loads. */
1193 dm_lock_md_type(md);
1194 if (dm_get_md_type(md) == DM_TYPE_NONE)
1195 /* Initial table load: acquire type of table. */
1196 dm_set_md_type(md, dm_table_get_type(t));
1197 else if (dm_get_md_type(md) != dm_table_get_type(t)) {
1198 DMWARN("can't change device type after initial table load.");
1199 dm_table_destroy(t);
1200 dm_unlock_md_type(md);
1201 r = -EINVAL;
1202 goto out;
1203 }
1204 dm_unlock_md_type(md);
1205
1206 /* stage inactive table */
1192 down_write(&_hash_lock); 1207 down_write(&_hash_lock);
1193 hc = dm_get_mdptr(md); 1208 hc = dm_get_mdptr(md);
1194 if (!hc || hc->md != md) { 1209 if (!hc || hc->md != md) {
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index f3cc5d99fe8d..345e94c10c65 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -125,6 +125,10 @@ struct mapped_device {
125 unsigned long flags; 125 unsigned long flags;
126 126
127 struct request_queue *queue; 127 struct request_queue *queue;
128 unsigned type;
129 /* Protect type against concurrent access. */
130 struct mutex type_lock;
131
128 struct gendisk *disk; 132 struct gendisk *disk;
129 char name[16]; 133 char name[16];
130 134
@@ -1877,8 +1881,10 @@ static struct mapped_device *alloc_dev(int minor)
1877 if (r < 0) 1881 if (r < 0)
1878 goto bad_minor; 1882 goto bad_minor;
1879 1883
1884 md->type = DM_TYPE_NONE;
1880 init_rwsem(&md->io_lock); 1885 init_rwsem(&md->io_lock);
1881 mutex_init(&md->suspend_lock); 1886 mutex_init(&md->suspend_lock);
1887 mutex_init(&md->type_lock);
1882 spin_lock_init(&md->deferred_lock); 1888 spin_lock_init(&md->deferred_lock);
1883 spin_lock_init(&md->barrier_error_lock); 1889 spin_lock_init(&md->barrier_error_lock);
1884 rwlock_init(&md->map_lock); 1890 rwlock_init(&md->map_lock);
@@ -2130,6 +2136,30 @@ int dm_create(int minor, struct mapped_device **result)
2130 return 0; 2136 return 0;
2131} 2137}
2132 2138
2139/*
2140 * Functions to manage md->type.
2141 * All are required to hold md->type_lock.
2142 */
2143void dm_lock_md_type(struct mapped_device *md)
2144{
2145 mutex_lock(&md->type_lock);
2146}
2147
2148void dm_unlock_md_type(struct mapped_device *md)
2149{
2150 mutex_unlock(&md->type_lock);
2151}
2152
2153void dm_set_md_type(struct mapped_device *md, unsigned type)
2154{
2155 md->type = type;
2156}
2157
2158unsigned dm_get_md_type(struct mapped_device *md)
2159{
2160 return md->type;
2161}
2162
2133static struct mapped_device *dm_find_md(dev_t dev) 2163static struct mapped_device *dm_find_md(dev_t dev)
2134{ 2164{
2135 struct mapped_device *md; 2165 struct mapped_device *md;
@@ -2440,13 +2470,6 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
2440 goto out; 2470 goto out;
2441 } 2471 }
2442 2472
2443 /* cannot change the device type, once a table is bound */
2444 if (md->map &&
2445 (dm_table_get_type(md->map) != dm_table_get_type(table))) {
2446 DMWARN("can't change the device type after a table is bound");
2447 goto out;
2448 }
2449
2450 map = __bind(md, table, &limits); 2473 map = __bind(md, table, &limits);
2451 2474
2452out: 2475out:
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 8223671e4901..1db782530ce6 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -66,6 +66,11 @@ int dm_table_alloc_md_mempools(struct dm_table *t);
66void dm_table_free_md_mempools(struct dm_table *t); 66void dm_table_free_md_mempools(struct dm_table *t);
67struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); 67struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t);
68 68
69void dm_lock_md_type(struct mapped_device *md);
70void dm_unlock_md_type(struct mapped_device *md);
71void dm_set_md_type(struct mapped_device *md, unsigned type);
72unsigned dm_get_md_type(struct mapped_device *md);
73
69/* 74/*
70 * To check the return value from dm_table_find_target(). 75 * To check the return value from dm_table_find_target().
71 */ 76 */
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index 2c445e113790..43b2de17449b 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -266,9 +266,9 @@ enum {
266#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) 266#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
267 267
268#define DM_VERSION_MAJOR 4 268#define DM_VERSION_MAJOR 4
269#define DM_VERSION_MINOR 17 269#define DM_VERSION_MINOR 18
270#define DM_VERSION_PATCHLEVEL 0 270#define DM_VERSION_PATCHLEVEL 0
271#define DM_VERSION_EXTRA "-ioctl (2010-03-05)" 271#define DM_VERSION_EXTRA "-ioctl (2010-06-29)"
272 272
273/* Status bits */ 273/* Status bits */
274#define DM_READONLY_FLAG (1 << 0) /* In/Out */ 274#define DM_READONLY_FLAG (1 << 0) /* In/Out */