diff options
author | Mike Snitzer <snitzer@redhat.com> | 2015-03-11 15:01:09 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2015-04-15 12:10:17 -0400 |
commit | 17e149b8f73ba116e71e25930dd6f2eb3828792d (patch) | |
tree | 6407112dbb113ffeebfd0620df27d4f67cd27ed1 | |
parent | 022333427a8aa4ccb318a9db90cea4e69ca1826b (diff) |
dm: add 'use_blk_mq' module param and expose in per-device ro sysfs attr
Request-based DM's blk-mq support defaults to off; but a user can easily
change the default using the dm_mod.use_blk_mq module/boot option.
Also, you can check what mode a given request-based DM device is using
with: cat /sys/block/dm-X/dm/use_blk_mq
This change enabled further cleanup and reduced work (e.g. the
md->io_pool and md->rq_pool isn't created if using blk-mq).
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-rw-r--r-- | Documentation/ABI/testing/sysfs-block-dm | 8 | ||||
-rw-r--r-- | drivers/md/Kconfig | 11 | ||||
-rw-r--r-- | drivers/md/dm-sysfs.c | 9 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 6 | ||||
-rw-r--r-- | drivers/md/dm.c | 53 | ||||
-rw-r--r-- | drivers/md/dm.h | 5 |
6 files changed, 76 insertions, 16 deletions
diff --git a/Documentation/ABI/testing/sysfs-block-dm b/Documentation/ABI/testing/sysfs-block-dm index ac4b6fe245d9..f9f2339b9a0a 100644 --- a/Documentation/ABI/testing/sysfs-block-dm +++ b/Documentation/ABI/testing/sysfs-block-dm | |||
@@ -37,3 +37,11 @@ Description: Allow control over how long a request that is a | |||
37 | accounting. This attribute is not applicable to | 37 | accounting. This attribute is not applicable to |
38 | bio-based DM devices so it will only ever report 0 for | 38 | bio-based DM devices so it will only ever report 0 for |
39 | them. | 39 | them. |
40 | |||
41 | What: /sys/block/dm-<num>/dm/use_blk_mq | ||
42 | Date: March 2015 | ||
43 | KernelVersion: 4.1 | ||
44 | Contact: dm-devel@redhat.com | ||
45 | Description: Request-based Device-mapper blk-mq I/O path mode. | ||
46 | Contains the value 1 if the device is using blk-mq. | ||
47 | Otherwise it contains 0. Read-only attribute. | ||
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index 63e05e32b462..109f9dcc9cab 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
@@ -196,6 +196,17 @@ config BLK_DEV_DM | |||
196 | 196 | ||
197 | If unsure, say N. | 197 | If unsure, say N. |
198 | 198 | ||
199 | config DM_MQ_DEFAULT | ||
200 | bool "request-based DM: use blk-mq I/O path by default" | ||
201 | depends on BLK_DEV_DM | ||
202 | ---help--- | ||
203 | This option enables the blk-mq based I/O path for request-based | ||
204 | DM devices by default. With the option the dm_mod.use_blk_mq | ||
205 | module/boot option defaults to Y, without it to N, but it can | ||
206 | still be overriden either way. | ||
207 | |||
208 | If unsure say N. | ||
209 | |||
199 | config DM_DEBUG | 210 | config DM_DEBUG |
200 | bool "Device mapper debugging support" | 211 | bool "Device mapper debugging support" |
201 | depends on BLK_DEV_DM | 212 | depends on BLK_DEV_DM |
diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c index f5bb3944f75e..7e818f5f1dc4 100644 --- a/drivers/md/dm-sysfs.c +++ b/drivers/md/dm-sysfs.c | |||
@@ -89,15 +89,24 @@ static ssize_t dm_attr_suspended_show(struct mapped_device *md, char *buf) | |||
89 | return strlen(buf); | 89 | return strlen(buf); |
90 | } | 90 | } |
91 | 91 | ||
92 | static ssize_t dm_attr_use_blk_mq_show(struct mapped_device *md, char *buf) | ||
93 | { | ||
94 | sprintf(buf, "%d\n", dm_use_blk_mq(md)); | ||
95 | |||
96 | return strlen(buf); | ||
97 | } | ||
98 | |||
92 | static DM_ATTR_RO(name); | 99 | static DM_ATTR_RO(name); |
93 | static DM_ATTR_RO(uuid); | 100 | static DM_ATTR_RO(uuid); |
94 | static DM_ATTR_RO(suspended); | 101 | static DM_ATTR_RO(suspended); |
102 | static DM_ATTR_RO(use_blk_mq); | ||
95 | static DM_ATTR_RW(rq_based_seq_io_merge_deadline); | 103 | static DM_ATTR_RW(rq_based_seq_io_merge_deadline); |
96 | 104 | ||
97 | static struct attribute *dm_attrs[] = { | 105 | static struct attribute *dm_attrs[] = { |
98 | &dm_attr_name.attr, | 106 | &dm_attr_name.attr, |
99 | &dm_attr_uuid.attr, | 107 | &dm_attr_uuid.attr, |
100 | &dm_attr_suspended.attr, | 108 | &dm_attr_suspended.attr, |
109 | &dm_attr_use_blk_mq.attr, | ||
101 | &dm_attr_rq_based_seq_io_merge_deadline.attr, | 110 | &dm_attr_rq_based_seq_io_merge_deadline.attr, |
102 | NULL, | 111 | NULL, |
103 | }; | 112 | }; |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 66600cab9fa5..8d025f33de92 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
@@ -940,7 +940,7 @@ bool dm_table_mq_request_based(struct dm_table *t) | |||
940 | return dm_table_get_type(t) == DM_TYPE_MQ_REQUEST_BASED; | 940 | return dm_table_get_type(t) == DM_TYPE_MQ_REQUEST_BASED; |
941 | } | 941 | } |
942 | 942 | ||
943 | static int dm_table_alloc_md_mempools(struct dm_table *t) | 943 | static int dm_table_alloc_md_mempools(struct dm_table *t, struct mapped_device *md) |
944 | { | 944 | { |
945 | unsigned type = dm_table_get_type(t); | 945 | unsigned type = dm_table_get_type(t); |
946 | unsigned per_bio_data_size = 0; | 946 | unsigned per_bio_data_size = 0; |
@@ -958,7 +958,7 @@ static int dm_table_alloc_md_mempools(struct dm_table *t) | |||
958 | per_bio_data_size = max(per_bio_data_size, tgt->per_bio_data_size); | 958 | per_bio_data_size = max(per_bio_data_size, tgt->per_bio_data_size); |
959 | } | 959 | } |
960 | 960 | ||
961 | t->mempools = dm_alloc_md_mempools(type, t->integrity_supported, per_bio_data_size); | 961 | t->mempools = dm_alloc_md_mempools(md, type, t->integrity_supported, per_bio_data_size); |
962 | if (!t->mempools) | 962 | if (!t->mempools) |
963 | return -ENOMEM; | 963 | return -ENOMEM; |
964 | 964 | ||
@@ -1128,7 +1128,7 @@ int dm_table_complete(struct dm_table *t) | |||
1128 | return r; | 1128 | return r; |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | r = dm_table_alloc_md_mempools(t); | 1131 | r = dm_table_alloc_md_mempools(t, t->md); |
1132 | if (r) | 1132 | if (r) |
1133 | DMERR("unable to allocate mempools"); | 1133 | DMERR("unable to allocate mempools"); |
1134 | 1134 | ||
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 55cadb1a2735..944cdb322708 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -228,8 +228,20 @@ struct mapped_device { | |||
228 | 228 | ||
229 | /* for blk-mq request-based DM support */ | 229 | /* for blk-mq request-based DM support */ |
230 | struct blk_mq_tag_set tag_set; | 230 | struct blk_mq_tag_set tag_set; |
231 | bool use_blk_mq; | ||
231 | }; | 232 | }; |
232 | 233 | ||
234 | #ifdef CONFIG_DM_MQ_DEFAULT | ||
235 | static bool use_blk_mq = true; | ||
236 | #else | ||
237 | static bool use_blk_mq = false; | ||
238 | #endif | ||
239 | |||
240 | bool dm_use_blk_mq(struct mapped_device *md) | ||
241 | { | ||
242 | return md->use_blk_mq; | ||
243 | } | ||
244 | |||
233 | /* | 245 | /* |
234 | * For mempools pre-allocation at the table loading time. | 246 | * For mempools pre-allocation at the table loading time. |
235 | */ | 247 | */ |
@@ -2034,7 +2046,7 @@ ssize_t dm_attr_rq_based_seq_io_merge_deadline_store(struct mapped_device *md, | |||
2034 | { | 2046 | { |
2035 | unsigned deadline; | 2047 | unsigned deadline; |
2036 | 2048 | ||
2037 | if (!dm_request_based(md)) | 2049 | if (!dm_request_based(md) || md->use_blk_mq) |
2038 | return count; | 2050 | return count; |
2039 | 2051 | ||
2040 | if (kstrtouint(buf, 10, &deadline)) | 2052 | if (kstrtouint(buf, 10, &deadline)) |
@@ -2222,6 +2234,7 @@ static void dm_init_md_queue(struct mapped_device *md) | |||
2222 | 2234 | ||
2223 | static void dm_init_old_md_queue(struct mapped_device *md) | 2235 | static void dm_init_old_md_queue(struct mapped_device *md) |
2224 | { | 2236 | { |
2237 | md->use_blk_mq = false; | ||
2225 | dm_init_md_queue(md); | 2238 | dm_init_md_queue(md); |
2226 | 2239 | ||
2227 | /* | 2240 | /* |
@@ -2263,6 +2276,7 @@ static struct mapped_device *alloc_dev(int minor) | |||
2263 | if (r < 0) | 2276 | if (r < 0) |
2264 | goto bad_io_barrier; | 2277 | goto bad_io_barrier; |
2265 | 2278 | ||
2279 | md->use_blk_mq = use_blk_mq; | ||
2266 | md->type = DM_TYPE_NONE; | 2280 | md->type = DM_TYPE_NONE; |
2267 | mutex_init(&md->suspend_lock); | 2281 | mutex_init(&md->suspend_lock); |
2268 | mutex_init(&md->type_lock); | 2282 | mutex_init(&md->type_lock); |
@@ -2349,7 +2363,6 @@ static void unlock_fs(struct mapped_device *md); | |||
2349 | static void free_dev(struct mapped_device *md) | 2363 | static void free_dev(struct mapped_device *md) |
2350 | { | 2364 | { |
2351 | int minor = MINOR(disk_devt(md->disk)); | 2365 | int minor = MINOR(disk_devt(md->disk)); |
2352 | bool using_blk_mq = !!md->queue->mq_ops; | ||
2353 | 2366 | ||
2354 | unlock_fs(md); | 2367 | unlock_fs(md); |
2355 | destroy_workqueue(md->wq); | 2368 | destroy_workqueue(md->wq); |
@@ -2375,7 +2388,7 @@ static void free_dev(struct mapped_device *md) | |||
2375 | del_gendisk(md->disk); | 2388 | del_gendisk(md->disk); |
2376 | put_disk(md->disk); | 2389 | put_disk(md->disk); |
2377 | blk_cleanup_queue(md->queue); | 2390 | blk_cleanup_queue(md->queue); |
2378 | if (using_blk_mq) | 2391 | if (md->use_blk_mq) |
2379 | blk_mq_free_tag_set(&md->tag_set); | 2392 | blk_mq_free_tag_set(&md->tag_set); |
2380 | bdput(md->bdev); | 2393 | bdput(md->bdev); |
2381 | free_minor(minor); | 2394 | free_minor(minor); |
@@ -2388,7 +2401,7 @@ static void __bind_mempools(struct mapped_device *md, struct dm_table *t) | |||
2388 | { | 2401 | { |
2389 | struct dm_md_mempools *p = dm_table_get_md_mempools(t); | 2402 | struct dm_md_mempools *p = dm_table_get_md_mempools(t); |
2390 | 2403 | ||
2391 | if (md->io_pool && md->bs) { | 2404 | if (md->bs) { |
2392 | /* The md already has necessary mempools. */ | 2405 | /* The md already has necessary mempools. */ |
2393 | if (dm_table_get_type(t) == DM_TYPE_BIO_BASED) { | 2406 | if (dm_table_get_type(t) == DM_TYPE_BIO_BASED) { |
2394 | /* | 2407 | /* |
@@ -2798,13 +2811,21 @@ out_tag_set: | |||
2798 | return err; | 2811 | return err; |
2799 | } | 2812 | } |
2800 | 2813 | ||
2814 | static unsigned filter_md_type(unsigned type, struct mapped_device *md) | ||
2815 | { | ||
2816 | if (type == DM_TYPE_BIO_BASED) | ||
2817 | return type; | ||
2818 | |||
2819 | return !md->use_blk_mq ? DM_TYPE_REQUEST_BASED : DM_TYPE_MQ_REQUEST_BASED; | ||
2820 | } | ||
2821 | |||
2801 | /* | 2822 | /* |
2802 | * Setup the DM device's queue based on md's type | 2823 | * Setup the DM device's queue based on md's type |
2803 | */ | 2824 | */ |
2804 | int dm_setup_md_queue(struct mapped_device *md) | 2825 | int dm_setup_md_queue(struct mapped_device *md) |
2805 | { | 2826 | { |
2806 | int r; | 2827 | int r; |
2807 | unsigned md_type = dm_get_md_type(md); | 2828 | unsigned md_type = filter_md_type(dm_get_md_type(md), md); |
2808 | 2829 | ||
2809 | switch (md_type) { | 2830 | switch (md_type) { |
2810 | case DM_TYPE_REQUEST_BASED: | 2831 | case DM_TYPE_REQUEST_BASED: |
@@ -3509,16 +3530,19 @@ int dm_noflush_suspending(struct dm_target *ti) | |||
3509 | } | 3530 | } |
3510 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); | 3531 | EXPORT_SYMBOL_GPL(dm_noflush_suspending); |
3511 | 3532 | ||
3512 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size) | 3533 | struct dm_md_mempools *dm_alloc_md_mempools(struct mapped_device *md, unsigned type, |
3534 | unsigned integrity, unsigned per_bio_data_size) | ||
3513 | { | 3535 | { |
3514 | struct dm_md_mempools *pools = kzalloc(sizeof(*pools), GFP_KERNEL); | 3536 | struct dm_md_mempools *pools = kzalloc(sizeof(*pools), GFP_KERNEL); |
3515 | struct kmem_cache *cachep; | 3537 | struct kmem_cache *cachep = NULL; |
3516 | unsigned int pool_size = 0; | 3538 | unsigned int pool_size = 0; |
3517 | unsigned int front_pad; | 3539 | unsigned int front_pad; |
3518 | 3540 | ||
3519 | if (!pools) | 3541 | if (!pools) |
3520 | return NULL; | 3542 | return NULL; |
3521 | 3543 | ||
3544 | type = filter_md_type(type, md); | ||
3545 | |||
3522 | switch (type) { | 3546 | switch (type) { |
3523 | case DM_TYPE_BIO_BASED: | 3547 | case DM_TYPE_BIO_BASED: |
3524 | cachep = _io_cache; | 3548 | cachep = _io_cache; |
@@ -3526,13 +3550,13 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, u | |||
3526 | front_pad = roundup(per_bio_data_size, __alignof__(struct dm_target_io)) + offsetof(struct dm_target_io, clone); | 3550 | front_pad = roundup(per_bio_data_size, __alignof__(struct dm_target_io)) + offsetof(struct dm_target_io, clone); |
3527 | break; | 3551 | break; |
3528 | case DM_TYPE_REQUEST_BASED: | 3552 | case DM_TYPE_REQUEST_BASED: |
3553 | cachep = _rq_tio_cache; | ||
3529 | pool_size = dm_get_reserved_rq_based_ios(); | 3554 | pool_size = dm_get_reserved_rq_based_ios(); |
3530 | pools->rq_pool = mempool_create_slab_pool(pool_size, _rq_cache); | 3555 | pools->rq_pool = mempool_create_slab_pool(pool_size, _rq_cache); |
3531 | if (!pools->rq_pool) | 3556 | if (!pools->rq_pool) |
3532 | goto out; | 3557 | goto out; |
3533 | /* fall through to setup remaining rq-based pools */ | 3558 | /* fall through to setup remaining rq-based pools */ |
3534 | case DM_TYPE_MQ_REQUEST_BASED: | 3559 | case DM_TYPE_MQ_REQUEST_BASED: |
3535 | cachep = _rq_tio_cache; | ||
3536 | if (!pool_size) | 3560 | if (!pool_size) |
3537 | pool_size = dm_get_reserved_rq_based_ios(); | 3561 | pool_size = dm_get_reserved_rq_based_ios(); |
3538 | front_pad = offsetof(struct dm_rq_clone_bio_info, clone); | 3562 | front_pad = offsetof(struct dm_rq_clone_bio_info, clone); |
@@ -3540,12 +3564,14 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, u | |||
3540 | WARN_ON(per_bio_data_size != 0); | 3564 | WARN_ON(per_bio_data_size != 0); |
3541 | break; | 3565 | break; |
3542 | default: | 3566 | default: |
3543 | goto out; | 3567 | BUG(); |
3544 | } | 3568 | } |
3545 | 3569 | ||
3546 | pools->io_pool = mempool_create_slab_pool(pool_size, cachep); | 3570 | if (cachep) { |
3547 | if (!pools->io_pool) | 3571 | pools->io_pool = mempool_create_slab_pool(pool_size, cachep); |
3548 | goto out; | 3572 | if (!pools->io_pool) |
3573 | goto out; | ||
3574 | } | ||
3549 | 3575 | ||
3550 | pools->bs = bioset_create_nobvec(pool_size, front_pad); | 3576 | pools->bs = bioset_create_nobvec(pool_size, front_pad); |
3551 | if (!pools->bs) | 3577 | if (!pools->bs) |
@@ -3602,6 +3628,9 @@ MODULE_PARM_DESC(reserved_bio_based_ios, "Reserved IOs in bio-based mempools"); | |||
3602 | module_param(reserved_rq_based_ios, uint, S_IRUGO | S_IWUSR); | 3628 | module_param(reserved_rq_based_ios, uint, S_IRUGO | S_IWUSR); |
3603 | MODULE_PARM_DESC(reserved_rq_based_ios, "Reserved IOs in request-based mempools"); | 3629 | MODULE_PARM_DESC(reserved_rq_based_ios, "Reserved IOs in request-based mempools"); |
3604 | 3630 | ||
3631 | module_param(use_blk_mq, bool, S_IRUGO | S_IWUSR); | ||
3632 | MODULE_PARM_DESC(use_blk_mq, "Use block multiqueue for request-based DM devices"); | ||
3633 | |||
3605 | MODULE_DESCRIPTION(DM_NAME " driver"); | 3634 | MODULE_DESCRIPTION(DM_NAME " driver"); |
3606 | MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>"); | 3635 | MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>"); |
3607 | MODULE_LICENSE("GPL"); | 3636 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 5522422cc6c4..6123c2bf9150 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
@@ -211,6 +211,8 @@ int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action, | |||
211 | void dm_internal_suspend(struct mapped_device *md); | 211 | void dm_internal_suspend(struct mapped_device *md); |
212 | void dm_internal_resume(struct mapped_device *md); | 212 | void dm_internal_resume(struct mapped_device *md); |
213 | 213 | ||
214 | bool dm_use_blk_mq(struct mapped_device *md); | ||
215 | |||
214 | int dm_io_init(void); | 216 | int dm_io_init(void); |
215 | void dm_io_exit(void); | 217 | void dm_io_exit(void); |
216 | 218 | ||
@@ -220,7 +222,8 @@ void dm_kcopyd_exit(void); | |||
220 | /* | 222 | /* |
221 | * Mempool operations | 223 | * Mempool operations |
222 | */ | 224 | */ |
223 | struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size); | 225 | struct dm_md_mempools *dm_alloc_md_mempools(struct mapped_device *md, unsigned type, |
226 | unsigned integrity, unsigned per_bio_data_size); | ||
224 | void dm_free_md_mempools(struct dm_md_mempools *pools); | 227 | void dm_free_md_mempools(struct dm_md_mempools *pools); |
225 | 228 | ||
226 | /* | 229 | /* |