diff options
| author | Mike Snitzer <snitzer@redhat.com> | 2014-12-18 16:26:47 -0500 | 
|---|---|---|
| committer | Mike Snitzer <snitzer@redhat.com> | 2015-02-09 13:06:47 -0500 | 
| commit | 65803c2059832fb99b992728157f7924c2e42d4b (patch) | |
| tree | 02ba090a7ff05070a3bb999708ceee67dadd0a10 | |
| parent | e5863d9ad754926e7d3f38b43ac8bd48ef73b097 (diff) | |
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 <snitzer@redhat.com>
| -rw-r--r-- | drivers/md/dm-table.c | 35 | ||||
| -rw-r--r-- | 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  | 
