Skip to content

Commit 74c4505

Browse files
committed
blk-mq: add a 'list' parameter to ->queue_rq()
Since we have the notion of a 'last' request in a chain, we can use this to have the hardware optimize the issuing of requests. Add a list_head parameter to queue_rq that the driver can use to temporarily store hw commands for issue when 'last' is true. If we are doing a chain of requests, pass in a NULL list for the first request to force issue of that immediately, then batch the remainder for deferred issue until the last request has been sent. Instead of adding yet another argument to the hot ->queue_rq path, encapsulate the passed arguments in a blk_mq_queue_data structure. This is passed as a constant, and has been tested as faster than passing 4 (or even 3) args through ->queue_rq. Update drivers for the new ->queue_rq() prototype. There are no functional changes in this patch for drivers - if they don't use the passed in list, then they will just queue requests individually like before. Signed-off-by: Jens Axboe <[email protected]>
1 parent 34b48db commit 74c4505

File tree

6 files changed

+49
-15
lines changed

6 files changed

+49
-15
lines changed

block/blk-mq.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,8 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
680680
struct request_queue *q = hctx->queue;
681681
struct request *rq;
682682
LIST_HEAD(rq_list);
683+
LIST_HEAD(driver_list);
684+
struct list_head *dptr;
683685
int queued;
684686

685687
WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask));
@@ -705,17 +707,28 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
705707
spin_unlock(&hctx->lock);
706708
}
707709

710+
/*
711+
* Start off with dptr being NULL, so we start the first request
712+
* immediately, even if we have more pending.
713+
*/
714+
dptr = NULL;
715+
708716
/*
709717
* Now process all the entries, sending them to the driver.
710718
*/
711719
queued = 0;
712720
while (!list_empty(&rq_list)) {
721+
struct blk_mq_queue_data bd;
713722
int ret;
714723

715724
rq = list_first_entry(&rq_list, struct request, queuelist);
716725
list_del_init(&rq->queuelist);
717726

718-
ret = q->mq_ops->queue_rq(hctx, rq, list_empty(&rq_list));
727+
bd.rq = rq;
728+
bd.list = dptr;
729+
bd.last = list_empty(&rq_list);
730+
731+
ret = q->mq_ops->queue_rq(hctx, &bd);
719732
switch (ret) {
720733
case BLK_MQ_RQ_QUEUE_OK:
721734
queued++;
@@ -734,6 +747,13 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
734747

735748
if (ret == BLK_MQ_RQ_QUEUE_BUSY)
736749
break;
750+
751+
/*
752+
* We've done the first request. If we have more than 1
753+
* left in the list, set dptr to defer issue.
754+
*/
755+
if (!dptr && rq_list.next != rq_list.prev)
756+
dptr = &driver_list;
737757
}
738758

739759
if (!queued)
@@ -1153,6 +1173,11 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
11531173
}
11541174

11551175
if (is_sync) {
1176+
struct blk_mq_queue_data bd = {
1177+
.rq = rq,
1178+
.list = NULL,
1179+
.last = 1
1180+
};
11561181
int ret;
11571182

11581183
blk_mq_bio_to_request(rq, bio);
@@ -1162,7 +1187,7 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
11621187
* error (busy), just add it to our list as we previously
11631188
* would have done
11641189
*/
1165-
ret = q->mq_ops->queue_rq(data.hctx, rq, true);
1190+
ret = q->mq_ops->queue_rq(data.hctx, &bd);
11661191
if (ret == BLK_MQ_RQ_QUEUE_OK)
11671192
goto done;
11681193
else {

drivers/block/mtip32xx/mtip32xx.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3775,9 +3775,10 @@ static bool mtip_check_unal_depth(struct blk_mq_hw_ctx *hctx,
37753775
return false;
37763776
}
37773777

3778-
static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq,
3779-
bool last)
3778+
static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx,
3779+
const struct blk_mq_queue_data *bd)
37803780
{
3781+
struct request *rq = bd->rq;
37813782
int ret;
37823783

37833784
if (unlikely(mtip_check_unal_depth(hctx, rq)))

drivers/block/null_blk.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,15 +313,15 @@ static void null_request_fn(struct request_queue *q)
313313
}
314314
}
315315

316-
static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq,
317-
bool last)
316+
static int null_queue_rq(struct blk_mq_hw_ctx *hctx,
317+
const struct blk_mq_queue_data *bd)
318318
{
319-
struct nullb_cmd *cmd = blk_mq_rq_to_pdu(rq);
319+
struct nullb_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
320320

321-
cmd->rq = rq;
321+
cmd->rq = bd->rq;
322322
cmd->nq = hctx->driver_data;
323323

324-
blk_mq_start_request(rq);
324+
blk_mq_start_request(bd->rq);
325325

326326
null_handle_cmd(cmd);
327327
return BLK_MQ_RQ_QUEUE_OK;

drivers/block/virtio_blk.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,11 @@ static void virtblk_done(struct virtqueue *vq)
158158
spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
159159
}
160160

161-
static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req,
162-
bool last)
161+
static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx,
162+
const struct blk_mq_queue_data *bd)
163163
{
164164
struct virtio_blk *vblk = hctx->queue->queuedata;
165+
struct request *req = bd->rq;
165166
struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
166167
unsigned long flags;
167168
unsigned int num;
@@ -222,7 +223,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req,
222223
return BLK_MQ_RQ_QUEUE_ERROR;
223224
}
224225

225-
if (last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
226+
if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
226227
notify = true;
227228
spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
228229

drivers/scsi/scsi_lib.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,9 +1858,10 @@ static void scsi_mq_done(struct scsi_cmnd *cmd)
18581858
blk_mq_complete_request(cmd->request);
18591859
}
18601860

1861-
static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req,
1862-
bool last)
1861+
static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx,
1862+
const struct blk_mq_queue_data *bd)
18631863
{
1864+
struct request *req = bd->rq;
18641865
struct request_queue *q = req->q;
18651866
struct scsi_device *sdev = q->queuedata;
18661867
struct Scsi_Host *shost = sdev->host;

include/linux/blk-mq.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ struct blk_mq_tag_set {
7979
struct list_head tag_list;
8080
};
8181

82-
typedef int (queue_rq_fn)(struct blk_mq_hw_ctx *, struct request *, bool);
82+
struct blk_mq_queue_data {
83+
struct request *rq;
84+
struct list_head *list;
85+
bool last;
86+
};
87+
88+
typedef int (queue_rq_fn)(struct blk_mq_hw_ctx *, const struct blk_mq_queue_data *);
8389
typedef struct blk_mq_hw_ctx *(map_queue_fn)(struct request_queue *, const int);
8490
typedef enum blk_eh_timer_return (timeout_fn)(struct request *, bool);
8591
typedef int (init_hctx_fn)(struct blk_mq_hw_ctx *, void *, unsigned int);

0 commit comments

Comments
 (0)