summaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorJens Axboe <axboe@fb.com>2017-02-17 11:39:26 -0700
committerJens Axboe <axboe@fb.com>2017-02-17 12:35:47 -0700
commit64765a75ef258c802f795558d00a5a1864c531fc (patch)
treef748a608e3489cc582a3788fe7dc776c5722ec97 /block
parent0c2a6fe4dc3e8c24bc67cd5d0a36092834027cf0 (diff)
downloadlinux-0-day-64765a75ef258c802f795558d00a5a1864c531fc.tar.gz
linux-0-day-64765a75ef258c802f795558d00a5a1864c531fc.tar.xz
blk-mq-sched: ask scheduler for work, if we failed dispatching leftovers
Usually we don't ask the scheduler for work, if we already have leftovers on the dispatch list. This is done to leave work on the scheduler side for as long as possible, for proper merging. But if we do have work leftover but didn't dispatch anything, then we should ask the scheduler since we could potentially issue requests from that. Signed-off-by: Jens Axboe <axboe@fb.com> Reviewed-by: Omar Sandoval <osandov@fb.com>
Diffstat (limited to 'block')
-rw-r--r--block/blk-mq-sched.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c
index 4ee7cb0438125..9e8d6795a8c1b 100644
--- a/block/blk-mq-sched.c
+++ b/block/blk-mq-sched.c
@@ -175,6 +175,8 @@ void blk_mq_sched_put_request(struct request *rq)
void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
{
struct elevator_queue *e = hctx->queue->elevator;
+ const bool has_sched_dispatch = e && e->type->ops.mq.dispatch_request;
+ bool did_work = false;
LIST_HEAD(rq_list);
if (unlikely(blk_mq_hctx_stopped(hctx)))
@@ -204,11 +206,18 @@ void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
*/
if (!list_empty(&rq_list)) {
blk_mq_sched_mark_restart(hctx);
- blk_mq_dispatch_rq_list(hctx, &rq_list);
- } else if (!e || !e->type->ops.mq.dispatch_request) {
+ did_work = blk_mq_dispatch_rq_list(hctx, &rq_list);
+ } else if (!has_sched_dispatch) {
blk_mq_flush_busy_ctxs(hctx, &rq_list);
blk_mq_dispatch_rq_list(hctx, &rq_list);
- } else {
+ }
+
+ /*
+ * We want to dispatch from the scheduler if we had no work left
+ * on the dispatch list, OR if we did have work but weren't able
+ * to make progress.
+ */
+ if (!did_work && has_sched_dispatch) {
do {
struct request *rq;