Skip to content

Commit

Permalink
blk-mq-sched: allow setting of default IO scheduler
Browse files Browse the repository at this point in the history
Add Kconfig entries to manage what devices get assigned an MQ
scheduler, and add a blk-mq flag for drivers to opt out of scheduling.
The latter is useful for admin type queues that still allocate a blk-mq
queue and tag set, but aren't use for normal IO.

Signed-off-by: Jens Axboe <axboe@fb.com>
Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com>
Reviewed-by: Omar Sandoval <osandov@fb.com>
  • Loading branch information
axboe committed Jan 17, 2017
1 parent 945ffb6 commit d348499
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 7 deletions.
56 changes: 50 additions & 6 deletions block/Kconfig.iosched
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,6 @@ config IOSCHED_CFQ

This is the default I/O scheduler.

config MQ_IOSCHED_DEADLINE
tristate "MQ deadline I/O scheduler"
default y
---help---
MQ version of the deadline IO scheduler.

config CFQ_GROUP_IOSCHED
bool "CFQ Group Scheduling support"
depends on IOSCHED_CFQ && BLK_CGROUP
Expand Down Expand Up @@ -69,6 +63,56 @@ config DEFAULT_IOSCHED
default "cfq" if DEFAULT_CFQ
default "noop" if DEFAULT_NOOP

config MQ_IOSCHED_DEADLINE
tristate "MQ deadline I/O scheduler"
default y
---help---
MQ version of the deadline IO scheduler.

config MQ_IOSCHED_NONE
bool
default y

choice
prompt "Default single-queue blk-mq I/O scheduler"
default DEFAULT_SQ_NONE
help
Select the I/O scheduler which will be used by default for blk-mq
managed block devices with a single queue.

config DEFAULT_SQ_DEADLINE
bool "MQ Deadline" if MQ_IOSCHED_DEADLINE=y

config DEFAULT_SQ_NONE
bool "None"

endchoice

config DEFAULT_SQ_IOSCHED
string
default "mq-deadline" if DEFAULT_SQ_DEADLINE
default "none" if DEFAULT_SQ_NONE

choice
prompt "Default multi-queue blk-mq I/O scheduler"
default DEFAULT_MQ_NONE
help
Select the I/O scheduler which will be used by default for blk-mq
managed block devices with multiple queues.

config DEFAULT_MQ_DEADLINE
bool "MQ Deadline" if MQ_IOSCHED_DEADLINE=y

config DEFAULT_MQ_NONE
bool "None"

endchoice

config DEFAULT_MQ_IOSCHED
string
default "mq-deadline" if DEFAULT_MQ_DEADLINE
default "none" if DEFAULT_MQ_NONE

endmenu

endif
20 changes: 20 additions & 0 deletions block/blk-mq-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,23 @@ void blk_mq_sched_teardown(struct request_queue *q)
queue_for_each_hw_ctx(q, hctx, i)
blk_mq_sched_free_tags(set, hctx, i);
}

int blk_mq_sched_init(struct request_queue *q)
{
int ret;

#if defined(CONFIG_DEFAULT_SQ_NONE)
if (q->nr_hw_queues == 1)
return 0;
#endif
#if defined(CONFIG_DEFAULT_MQ_NONE)
if (q->nr_hw_queues > 1)
return 0;
#endif

mutex_lock(&q->sysfs_lock);
ret = elevator_init(q, NULL);
mutex_unlock(&q->sysfs_lock);

return ret;
}
2 changes: 2 additions & 0 deletions block/blk-mq-sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ void blk_mq_sched_move_to_dispatch(struct blk_mq_hw_ctx *hctx,
int blk_mq_sched_setup(struct request_queue *q);
void blk_mq_sched_teardown(struct request_queue *q);

int blk_mq_sched_init(struct request_queue *q);

static inline bool
blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio)
{
Expand Down
8 changes: 8 additions & 0 deletions block/blk-mq.c
Original file line number Diff line number Diff line change
Expand Up @@ -2285,6 +2285,14 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
mutex_unlock(&all_q_mutex);
put_online_cpus();

if (!(set->flags & BLK_MQ_F_NO_SCHED)) {
int ret;

ret = blk_mq_sched_init(q);
if (ret)
return ERR_PTR(ret);
}

return q;

err_hctxs:
Expand Down
8 changes: 7 additions & 1 deletion block/elevator.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,13 @@ int elevator_init(struct request_queue *q, char *name)
}

if (!e) {
e = elevator_get(CONFIG_DEFAULT_IOSCHED, false);
if (q->mq_ops && q->nr_hw_queues == 1)
e = elevator_get(CONFIG_DEFAULT_SQ_IOSCHED, false);
else if (q->mq_ops)
e = elevator_get(CONFIG_DEFAULT_MQ_IOSCHED, false);
else
e = elevator_get(CONFIG_DEFAULT_IOSCHED, false);

if (!e) {
printk(KERN_ERR
"Default I/O scheduler not found. " \
Expand Down
1 change: 1 addition & 0 deletions drivers/nvme/host/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,7 @@ static int nvme_alloc_admin_tags(struct nvme_dev *dev)
dev->admin_tagset.timeout = ADMIN_TIMEOUT;
dev->admin_tagset.numa_node = dev_to_node(dev->dev);
dev->admin_tagset.cmd_size = nvme_cmd_size(dev);
dev->admin_tagset.flags = BLK_MQ_F_NO_SCHED;
dev->admin_tagset.driver_data = dev;

if (blk_mq_alloc_tag_set(&dev->admin_tagset))
Expand Down
1 change: 1 addition & 0 deletions include/linux/blk-mq.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ enum {
BLK_MQ_F_SG_MERGE = 1 << 2,
BLK_MQ_F_DEFER_ISSUE = 1 << 4,
BLK_MQ_F_BLOCKING = 1 << 5,
BLK_MQ_F_NO_SCHED = 1 << 6,
BLK_MQ_F_ALLOC_POLICY_START_BIT = 8,
BLK_MQ_F_ALLOC_POLICY_BITS = 1,

Expand Down

0 comments on commit d348499

Please sign in to comment.