aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2010-08-11 23:14:01 -0400
committerAlasdair G Kergon <agk@redhat.com>2010-08-11 23:14:01 -0400
commita5664dad7e1a278d2915c2bf79cf42250e12d7db (patch)
tree3bdbe17f12376c63ea05100c2597757e01dc95e2 /drivers
parent708e929513502fb050c0a3c3ee267cab5b056ded (diff)
dm ioctl: make bio or request based device type immutable
Determine whether a mapped device is bio-based or request-based when loading its first (inactive) table and don't allow that to be changed later. This patch performs different device initialisation in each of the two cases. (We don't think it's necessary to add code to support changing between the two types.) Allowed md->type transitions: DM_TYPE_NONE to DM_TYPE_BIO_BASED DM_TYPE_NONE to DM_TYPE_REQUEST_BASED We now prevent table_load from replacing the inactive table with a conflicting type of table even after an explicit table_clear. Introduce 'type_lock' into the struct mapped_device to protect md->type and to prepare for the next patch that will change the queue initialization and allocate memory while md->type_lock is held. Signed-off-by: Mike Snitzer <snitzer@redhat.com> Acked-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com> drivers/md/dm-ioctl.c | 15 +++++++++++++++ drivers/md/dm.c | 37 ++++++++++++++++++++++++++++++------- drivers/md/dm.h | 5 +++++ include/linux/dm-ioctl.h | 4 ++-- 4 files changed, 52 insertions(+), 9 deletions(-)
Diffstat (limited to 'drivers')
-rw-r--r--drivers/md/dm-ioctl.c15
-rw-r--r--drivers/md/dm.c37
-rw-r--r--drivers/md/dm.h5
3 files changed, 50 insertions, 7 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 */