From 65803c2059832fb99b992728157f7924c2e42d4b Mon Sep 17 00:00:00 2001 From: Mike Snitzer Date: Thu, 18 Dec 2014 16:26:47 -0500 Subject: dm table: train hybrid target type detection to select blk-mq if appropriate Otherwise replacing the multipath target with the error target fails: device-mapper: ioctl: can't change device type after initial table load. The error target was mistakenly considered to be target type DM_TYPE_REQUEST_BASED rather than DM_TYPE_MQ_REQUEST_BASED even if the target it was to replace was of type DM_TYPE_MQ_REQUEST_BASED. Signed-off-by: Mike Snitzer --- drivers/md/dm-table.c | 35 ++++++++++++++++++++--------------- drivers/md/dm.h | 3 ++- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 2d7e373955f3..14954d844668 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -831,7 +831,7 @@ static int dm_table_set_type(struct dm_table *t) struct dm_target *tgt; struct dm_dev_internal *dd; struct list_head *devices; - unsigned live_md_type; + unsigned live_md_type = dm_get_md_type(t->md); for (i = 0; i < t->num_targets; i++) { tgt = t->targets + i; @@ -855,8 +855,8 @@ static int dm_table_set_type(struct dm_table *t) * Determine the type from the live device. * Default to bio-based if device is new. */ - live_md_type = dm_get_md_type(t->md); - if (live_md_type == DM_TYPE_REQUEST_BASED) + if (live_md_type == DM_TYPE_REQUEST_BASED || + live_md_type == DM_TYPE_MQ_REQUEST_BASED) request_based = 1; else bio_based = 1; @@ -870,6 +870,17 @@ static int dm_table_set_type(struct dm_table *t) BUG_ON(!request_based); /* No targets in this table */ + /* + * Request-based dm supports only tables that have a single target now. + * To support multiple targets, request splitting support is needed, + * and that needs lots of changes in the block-layer. + * (e.g. request completion process for partial completion.) + */ + if (t->num_targets > 1) { + DMWARN("Request-based dm doesn't support multiple targets yet"); + return -EINVAL; + } + /* Non-request-stackable devices can't be used for request-based dm */ devices = dm_table_get_devices(t); list_for_each_entry(dd, devices, list) { @@ -893,20 +904,14 @@ static int dm_table_set_type(struct dm_table *t) " are blk-mq request-stackable"); return -EINVAL; } - } + t->type = DM_TYPE_MQ_REQUEST_BASED; - /* - * Request-based dm supports only tables that have a single target now. - * To support multiple targets, request splitting support is needed, - * and that needs lots of changes in the block-layer. - * (e.g. request completion process for partial completion.) - */ - if (t->num_targets > 1) { - DMWARN("Request-based dm doesn't support multiple targets yet"); - return -EINVAL; - } + } else if (hybrid && list_empty(devices) && live_md_type != DM_TYPE_NONE) { + /* inherit live MD type */ + t->type = live_md_type; - t->type = !use_blk_mq ? DM_TYPE_REQUEST_BASED : DM_TYPE_MQ_REQUEST_BASED; + } else + t->type = DM_TYPE_REQUEST_BASED; return 0; } diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 84d79784b866..59f53e79db82 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h @@ -101,7 +101,8 @@ int dm_setup_md_queue(struct mapped_device *md); /* * To check whether the target type is request-based or not (bio-based). */ -#define dm_target_request_based(t) ((t)->type->map_rq != NULL) +#define dm_target_request_based(t) (((t)->type->map_rq != NULL) || \ + ((t)->type->clone_and_map_rq != NULL)) /* * To check whether the target type is a hybrid (capable of being -- cgit v1.2.3