diff options
| -rw-r--r-- | drivers/md/dm-ioctl.c | 15 | ||||
| -rw-r--r-- | drivers/md/dm.c | 37 | ||||
| -rw-r--r-- | drivers/md/dm.h | 5 | ||||
| -rw-r--r-- | include/linux/dm-ioctl.h | 4 |
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 | */ | ||
| 2143 | void dm_lock_md_type(struct mapped_device *md) | ||
| 2144 | { | ||
| 2145 | mutex_lock(&md->type_lock); | ||
| 2146 | } | ||
| 2147 | |||
| 2148 | void dm_unlock_md_type(struct mapped_device *md) | ||
| 2149 | { | ||
| 2150 | mutex_unlock(&md->type_lock); | ||
| 2151 | } | ||
| 2152 | |||
| 2153 | void dm_set_md_type(struct mapped_device *md, unsigned type) | ||
| 2154 | { | ||
| 2155 | md->type = type; | ||
| 2156 | } | ||
| 2157 | |||
| 2158 | unsigned dm_get_md_type(struct mapped_device *md) | ||
| 2159 | { | ||
| 2160 | return md->type; | ||
| 2161 | } | ||
| 2162 | |||
| 2133 | static struct mapped_device *dm_find_md(dev_t dev) | 2163 | static 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 | ||
| 2452 | out: | 2475 | out: |
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); | |||
| 66 | void dm_table_free_md_mempools(struct dm_table *t); | 66 | void dm_table_free_md_mempools(struct dm_table *t); |
| 67 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); | 67 | struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t); |
| 68 | 68 | ||
| 69 | void dm_lock_md_type(struct mapped_device *md); | ||
| 70 | void dm_unlock_md_type(struct mapped_device *md); | ||
| 71 | void dm_set_md_type(struct mapped_device *md, unsigned type); | ||
| 72 | unsigned 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 */ |
