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) | |||
831 | struct dm_target *tgt; | 831 | struct dm_target *tgt; |
832 | struct dm_dev_internal *dd; | 832 | struct dm_dev_internal *dd; |
833 | struct list_head *devices; | 833 | struct list_head *devices; |
834 | unsigned live_md_type; | 834 | unsigned live_md_type = dm_get_md_type(t->md); |
835 | 835 | ||
836 | for (i = 0; i < t->num_targets; i++) { | 836 | for (i = 0; i < t->num_targets; i++) { |
837 | tgt = t->targets + i; | 837 | tgt = t->targets + i; |
@@ -855,8 +855,8 @@ static int dm_table_set_type(struct dm_table *t) | |||
855 | * Determine the type from the live device. | 855 | * Determine the type from the live device. |
856 | * Default to bio-based if device is new. | 856 | * Default to bio-based if device is new. |
857 | */ | 857 | */ |
858 | live_md_type = dm_get_md_type(t->md); | 858 | if (live_md_type == DM_TYPE_REQUEST_BASED || |
859 | if (live_md_type == DM_TYPE_REQUEST_BASED) | 859 | live_md_type == DM_TYPE_MQ_REQUEST_BASED) |
860 | request_based = 1; | 860 | request_based = 1; |
861 | else | 861 | else |
862 | bio_based = 1; | 862 | bio_based = 1; |
@@ -870,6 +870,17 @@ static int dm_table_set_type(struct dm_table *t) | |||
870 | 870 | ||
871 | BUG_ON(!request_based); /* No targets in this table */ | 871 | BUG_ON(!request_based); /* No targets in this table */ |
872 | 872 | ||
873 | /* | ||
874 | * Request-based dm supports only tables that have a single target now. | ||
875 | * To support multiple targets, request splitting support is needed, | ||
876 | * and that needs lots of changes in the block-layer. | ||
877 | * (e.g. request completion process for partial completion.) | ||
878 | */ | ||
879 | if (t->num_targets > 1) { | ||
880 | DMWARN("Request-based dm doesn't support multiple targets yet"); | ||
881 | return -EINVAL; | ||
882 | } | ||
883 | |||
873 | /* Non-request-stackable devices can't be used for request-based dm */ | 884 | /* Non-request-stackable devices can't be used for request-based dm */ |
874 | devices = dm_table_get_devices(t); | 885 | devices = dm_table_get_devices(t); |
875 | list_for_each_entry(dd, devices, list) { | 886 | list_for_each_entry(dd, devices, list) { |
@@ -893,20 +904,14 @@ static int dm_table_set_type(struct dm_table *t) | |||
893 | " are blk-mq request-stackable"); | 904 | " are blk-mq request-stackable"); |
894 | return -EINVAL; | 905 | return -EINVAL; |
895 | } | 906 | } |
896 | } | 907 | t->type = DM_TYPE_MQ_REQUEST_BASED; |
897 | 908 | ||
898 | /* | 909 | } else if (hybrid && list_empty(devices) && live_md_type != DM_TYPE_NONE) { |
899 | * Request-based dm supports only tables that have a single target now. | 910 | /* inherit live MD type */ |
900 | * To support multiple targets, request splitting support is needed, | 911 | t->type = live_md_type; |
901 | * and that needs lots of changes in the block-layer. | ||
902 | * (e.g. request completion process for partial completion.) | ||
903 | */ | ||
904 | if (t->num_targets > 1) { | ||
905 | DMWARN("Request-based dm doesn't support multiple targets yet"); | ||
906 | return -EINVAL; | ||
907 | } | ||
908 | 912 | ||
909 | t->type = !use_blk_mq ? DM_TYPE_REQUEST_BASED : DM_TYPE_MQ_REQUEST_BASED; | 913 | } else |
914 | t->type = DM_TYPE_REQUEST_BASED; | ||
910 | 915 | ||
911 | return 0; | 916 | return 0; |
912 | } | 917 | } |
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); | |||
101 | /* | 101 | /* |
102 | * To check whether the target type is request-based or not (bio-based). | 102 | * To check whether the target type is request-based or not (bio-based). |
103 | */ | 103 | */ |
104 | #define dm_target_request_based(t) ((t)->type->map_rq != NULL) | 104 | #define dm_target_request_based(t) (((t)->type->map_rq != NULL) || \ |
105 | ((t)->type->clone_and_map_rq != NULL)) | ||
105 | 106 | ||
106 | /* | 107 | /* |
107 | * To check whether the target type is a hybrid (capable of being | 108 | * To check whether the target type is a hybrid (capable of being |