Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+76 -16
+8
Documentation/ABI/testing/sysfs-block-dm
··· 37 37 accounting. This attribute is not applicable to 38 38 bio-based DM devices so it will only ever report 0 for 39 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.
+11
drivers/md/Kconfig
··· 196 196 197 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 210 config DM_DEBUG 200 211 bool "Device mapper debugging support" 201 212 depends on BLK_DEV_DM
+9
drivers/md/dm-sysfs.c
··· 89 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 99 static DM_ATTR_RO(name); 93 100 static DM_ATTR_RO(uuid); 94 101 static DM_ATTR_RO(suspended); 102 + static DM_ATTR_RO(use_blk_mq); 95 103 static DM_ATTR_RW(rq_based_seq_io_merge_deadline); 96 104 97 105 static struct attribute *dm_attrs[] = { 98 106 &dm_attr_name.attr, 99 107 &dm_attr_uuid.attr, 100 108 &dm_attr_suspended.attr, 109 + &dm_attr_use_blk_mq.attr, 101 110 &dm_attr_rq_based_seq_io_merge_deadline.attr, 102 111 NULL, 103 112 };
+3 -3
drivers/md/dm-table.c
··· 940 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 945 unsigned type = dm_table_get_type(t); 946 946 unsigned per_bio_data_size = 0; ··· 958 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 962 if (!t->mempools) 963 963 return -ENOMEM; 964 964 ··· 1128 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 1132 if (r) 1133 1133 DMERR("unable to allocate mempools"); 1134 1134
+41 -12
drivers/md/dm.c
··· 228 228 229 229 /* for blk-mq request-based DM support */ 230 230 struct blk_mq_tag_set tag_set; 231 + bool use_blk_mq; 231 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 + } 232 244 233 245 /* 234 246 * For mempools pre-allocation at the table loading time. ··· 2046 2034 { 2047 2035 unsigned deadline; 2048 2036 2049 - if (!dm_request_based(md)) 2037 + if (!dm_request_based(md) || md->use_blk_mq) 2050 2038 return count; 2051 2039 2052 2040 if (kstrtouint(buf, 10, &deadline)) ··· 2234 2222 2235 2223 static void dm_init_old_md_queue(struct mapped_device *md) 2236 2224 { 2225 + md->use_blk_mq = false; 2237 2226 dm_init_md_queue(md); 2238 2227 2239 2228 /* ··· 2276 2263 if (r < 0) 2277 2264 goto bad_io_barrier; 2278 2265 2266 + md->use_blk_mq = use_blk_mq; 2279 2267 md->type = DM_TYPE_NONE; 2280 2268 mutex_init(&md->suspend_lock); 2281 2269 mutex_init(&md->type_lock); ··· 2363 2349 static void free_dev(struct mapped_device *md) 2364 2350 { 2365 2351 int minor = MINOR(disk_devt(md->disk)); 2366 - bool using_blk_mq = !!md->queue->mq_ops; 2367 2352 2368 2353 unlock_fs(md); 2369 2354 destroy_workqueue(md->wq); ··· 2388 2375 del_gendisk(md->disk); 2389 2376 put_disk(md->disk); 2390 2377 blk_cleanup_queue(md->queue); 2391 - if (using_blk_mq) 2378 + if (md->use_blk_mq) 2392 2379 blk_mq_free_tag_set(&md->tag_set); 2393 2380 bdput(md->bdev); 2394 2381 free_minor(minor); ··· 2401 2388 { 2402 2389 struct dm_md_mempools *p = dm_table_get_md_mempools(t); 2403 2390 2404 - if (md->io_pool && md->bs) { 2391 + if (md->bs) { 2405 2392 /* The md already has necessary mempools. */ 2406 2393 if (dm_table_get_type(t) == DM_TYPE_BIO_BASED) { 2407 2394 /* ··· 2811 2798 return err; 2812 2799 } 2813 2800 2801 + static unsigned filter_md_type(unsigned type, struct mapped_device *md) 2802 + { 2803 + if (type == DM_TYPE_BIO_BASED) 2804 + return type; 2805 + 2806 + return !md->use_blk_mq ? DM_TYPE_REQUEST_BASED : DM_TYPE_MQ_REQUEST_BASED; 2807 + } 2808 + 2814 2809 /* 2815 2810 * Setup the DM device's queue based on md's type 2816 2811 */ 2817 2812 int dm_setup_md_queue(struct mapped_device *md) 2818 2813 { 2819 2814 int r; 2820 - unsigned md_type = dm_get_md_type(md); 2815 + unsigned md_type = filter_md_type(dm_get_md_type(md), md); 2821 2816 2822 2817 switch (md_type) { 2823 2818 case DM_TYPE_REQUEST_BASED: ··· 3530 3509 } 3531 3510 EXPORT_SYMBOL_GPL(dm_noflush_suspending); 3532 3511 3533 - struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size) 3512 + struct dm_md_mempools *dm_alloc_md_mempools(struct mapped_device *md, unsigned type, 3513 + unsigned integrity, unsigned per_bio_data_size) 3534 3514 { 3535 3515 struct dm_md_mempools *pools = kzalloc(sizeof(*pools), GFP_KERNEL); 3536 - struct kmem_cache *cachep; 3516 + struct kmem_cache *cachep = NULL; 3537 3517 unsigned int pool_size = 0; 3538 3518 unsigned int front_pad; 3539 3519 3540 3520 if (!pools) 3541 3521 return NULL; 3522 + 3523 + type = filter_md_type(type, md); 3542 3524 3543 3525 switch (type) { 3544 3526 case DM_TYPE_BIO_BASED: ··· 3550 3526 front_pad = roundup(per_bio_data_size, __alignof__(struct dm_target_io)) + offsetof(struct dm_target_io, clone); 3551 3527 break; 3552 3528 case DM_TYPE_REQUEST_BASED: 3529 + cachep = _rq_tio_cache; 3553 3530 pool_size = dm_get_reserved_rq_based_ios(); 3554 3531 pools->rq_pool = mempool_create_slab_pool(pool_size, _rq_cache); 3555 3532 if (!pools->rq_pool) 3556 3533 goto out; 3557 3534 /* fall through to setup remaining rq-based pools */ 3558 3535 case DM_TYPE_MQ_REQUEST_BASED: 3559 - cachep = _rq_tio_cache; 3560 3536 if (!pool_size) 3561 3537 pool_size = dm_get_reserved_rq_based_ios(); 3562 3538 front_pad = offsetof(struct dm_rq_clone_bio_info, clone); ··· 3564 3540 WARN_ON(per_bio_data_size != 0); 3565 3541 break; 3566 3542 default: 3567 - goto out; 3543 + BUG(); 3568 3544 } 3569 3545 3570 - pools->io_pool = mempool_create_slab_pool(pool_size, cachep); 3571 - if (!pools->io_pool) 3572 - goto out; 3546 + if (cachep) { 3547 + pools->io_pool = mempool_create_slab_pool(pool_size, cachep); 3548 + if (!pools->io_pool) 3549 + goto out; 3550 + } 3573 3551 3574 3552 pools->bs = bioset_create_nobvec(pool_size, front_pad); 3575 3553 if (!pools->bs) ··· 3627 3601 3628 3602 module_param(reserved_rq_based_ios, uint, S_IRUGO | S_IWUSR); 3629 3603 MODULE_PARM_DESC(reserved_rq_based_ios, "Reserved IOs in request-based mempools"); 3604 + 3605 + module_param(use_blk_mq, bool, S_IRUGO | S_IWUSR); 3606 + MODULE_PARM_DESC(use_blk_mq, "Use block multiqueue for request-based DM devices"); 3630 3607 3631 3608 MODULE_DESCRIPTION(DM_NAME " driver"); 3632 3609 MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+4 -1
drivers/md/dm.h
··· 211 211 void dm_internal_suspend(struct mapped_device *md); 212 212 void dm_internal_resume(struct mapped_device *md); 213 213 214 + bool dm_use_blk_mq(struct mapped_device *md); 215 + 214 216 int dm_io_init(void); 215 217 void dm_io_exit(void); 216 218 ··· 222 220 /* 223 221 * Mempool operations 224 222 */ 225 - struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, unsigned per_bio_data_size); 223 + struct dm_md_mempools *dm_alloc_md_mempools(struct mapped_device *md, unsigned type, 224 + unsigned integrity, unsigned per_bio_data_size); 226 225 void dm_free_md_mempools(struct dm_md_mempools *pools); 227 226 228 227 /*