From a5664dad7e1a278d2915c2bf79cf42250e12d7db Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 12 Aug 2010 04:14:01 +0100 Subject: 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 Acked-by: Kiyoshi Ueda Signed-off-by: Alasdair G Kergon 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(-) --- drivers/md/dm-ioctl.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/md/dm-ioctl.c') 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) goto out; } + /* Protect md->type against concurrent table loads. */ + dm_lock_md_type(md); + if (dm_get_md_type(md) == DM_TYPE_NONE) + /* Initial table load: acquire type of table. */ + dm_set_md_type(md, dm_table_get_type(t)); + else if (dm_get_md_type(md) != dm_table_get_type(t)) { + DMWARN("can't change device type after initial table load."); + dm_table_destroy(t); + dm_unlock_md_type(md); + r = -EINVAL; + goto out; + } + dm_unlock_md_type(md); + + /* stage inactive table */ down_write(&_hash_lock); hc = dm_get_mdptr(md); if (!hc || hc->md != md) { -- cgit v1.2.3