> @@ -2208,6 +2208,19 @@ static void blk_mq_plug_issue_direct(struct blk_plug *plug, bool from_schedule) > int queued = 0; > int errors = 0; > > + /* > + * Peek first request and see if we have a ->queue_rqs() hook. If we > + * do, we can dispatch the whole plug list in one go. We already know > + * at this point that all requests belong to the same queue, caller > + * must ensure that's the case. > + */ > + rq = rq_list_peek(&plug->mq_list); > + if (rq->q->mq_ops->queue_rqs) { > + rq->q->mq_ops->queue_rqs(&plug->mq_list); > + if (rq_list_empty(plug->mq_list)) > + return; > + } I'd move this straight into the caller to simplify the follow, something like the patch below. Also I wonder if the slow path might want to be moved from blk_mq_flush_plug_list into a separate helper to keep the fast path as straight as possible? diff --git a/block/blk-mq.c b/block/blk-mq.c index 3ab34c4f20daf..370f4b2ab4511 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -2255,6 +2255,14 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule) plug->rq_count = 0; if (!plug->multiple_queues && !plug->has_elevator && !from_schedule) { + struct request_queue *q = rq_list_peek(&plug->mq_list)->q; + + if (q->mq_ops->queue_rqs) { + q->mq_ops->queue_rqs(&plug->mq_list); + if (rq_list_empty(plug->mq_list)) + return; + } + blk_mq_plug_issue_direct(plug, false); if (rq_list_empty(plug->mq_list)) return;