diff options
| author | Christoph Hellwig <hch@lst.de> | 2014-09-13 19:40:09 -0400 |
|---|---|---|
| committer | Jens Axboe <axboe@fb.com> | 2014-09-22 14:00:07 -0400 |
| commit | e2490073cd7c3d6f6ef6e029a208edd4d38efac4 (patch) | |
| tree | 48465e67b335f6d696d698641365b4a4d1e89d32 | |
| parent | bf57229745f849e500ba69ff91e35bc8160a7373 (diff) | |
blk-mq: call blk_mq_start_request from ->queue_rq
When we call blk_mq_start_request from the core blk-mq code before calling into
->queue_rq there is a racy window where the timeout handler can hit before we've
fully set up the driver specific part of the command.
Move the call to blk_mq_start_request into the driver so the driver can start
the request only once it is fully set up.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@fb.com>
| -rw-r--r-- | block/blk-mq.c | 13 | ||||
| -rw-r--r-- | drivers/block/mtip32xx/mtip32xx.c | 2 | ||||
| -rw-r--r-- | drivers/block/null_blk.c | 2 | ||||
| -rw-r--r-- | drivers/block/virtio_blk.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 1 | ||||
| -rw-r--r-- | include/linux/blk-mq.h | 1 |
6 files changed, 14 insertions, 7 deletions
diff --git a/block/blk-mq.c b/block/blk-mq.c index 32b4797f4186..141f2e06803a 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c | |||
| @@ -384,7 +384,7 @@ void blk_mq_complete_request(struct request *rq) | |||
| 384 | } | 384 | } |
| 385 | EXPORT_SYMBOL(blk_mq_complete_request); | 385 | EXPORT_SYMBOL(blk_mq_complete_request); |
| 386 | 386 | ||
| 387 | static void blk_mq_start_request(struct request *rq) | 387 | void blk_mq_start_request(struct request *rq) |
| 388 | { | 388 | { |
| 389 | struct request_queue *q = rq->q; | 389 | struct request_queue *q = rq->q; |
| 390 | 390 | ||
| @@ -422,16 +422,18 @@ static void blk_mq_start_request(struct request *rq) | |||
| 422 | rq->nr_phys_segments++; | 422 | rq->nr_phys_segments++; |
| 423 | } | 423 | } |
| 424 | } | 424 | } |
| 425 | EXPORT_SYMBOL(blk_mq_start_request); | ||
| 425 | 426 | ||
| 426 | static void __blk_mq_requeue_request(struct request *rq) | 427 | static void __blk_mq_requeue_request(struct request *rq) |
| 427 | { | 428 | { |
| 428 | struct request_queue *q = rq->q; | 429 | struct request_queue *q = rq->q; |
| 429 | 430 | ||
| 430 | trace_block_rq_requeue(q, rq); | 431 | trace_block_rq_requeue(q, rq); |
| 431 | clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags); | ||
| 432 | 432 | ||
| 433 | if (q->dma_drain_size && blk_rq_bytes(rq)) | 433 | if (test_and_clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags)) { |
| 434 | rq->nr_phys_segments--; | 434 | if (q->dma_drain_size && blk_rq_bytes(rq)) |
| 435 | rq->nr_phys_segments--; | ||
| 436 | } | ||
| 435 | } | 437 | } |
| 436 | 438 | ||
| 437 | void blk_mq_requeue_request(struct request *rq) | 439 | void blk_mq_requeue_request(struct request *rq) |
| @@ -743,8 +745,6 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx) | |||
| 743 | rq = list_first_entry(&rq_list, struct request, queuelist); | 745 | rq = list_first_entry(&rq_list, struct request, queuelist); |
| 744 | list_del_init(&rq->queuelist); | 746 | list_del_init(&rq->queuelist); |
| 745 | 747 | ||
| 746 | blk_mq_start_request(rq); | ||
| 747 | |||
| 748 | ret = q->mq_ops->queue_rq(hctx, rq, list_empty(&rq_list)); | 748 | ret = q->mq_ops->queue_rq(hctx, rq, list_empty(&rq_list)); |
| 749 | switch (ret) { | 749 | switch (ret) { |
| 750 | case BLK_MQ_RQ_QUEUE_OK: | 750 | case BLK_MQ_RQ_QUEUE_OK: |
| @@ -1186,7 +1186,6 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio) | |||
| 1186 | int ret; | 1186 | int ret; |
| 1187 | 1187 | ||
| 1188 | blk_mq_bio_to_request(rq, bio); | 1188 | blk_mq_bio_to_request(rq, bio); |
| 1189 | blk_mq_start_request(rq); | ||
| 1190 | 1189 | ||
| 1191 | /* | 1190 | /* |
| 1192 | * For OK queue, we are done. For error, kill it. Any other | 1191 | * For OK queue, we are done. For error, kill it. Any other |
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 0e2084f37c67..4042440a0470 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
| @@ -3783,6 +3783,8 @@ static int mtip_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq, | |||
| 3783 | if (unlikely(mtip_check_unal_depth(hctx, rq))) | 3783 | if (unlikely(mtip_check_unal_depth(hctx, rq))) |
| 3784 | return BLK_MQ_RQ_QUEUE_BUSY; | 3784 | return BLK_MQ_RQ_QUEUE_BUSY; |
| 3785 | 3785 | ||
| 3786 | blk_mq_start_request(rq); | ||
| 3787 | |||
| 3786 | ret = mtip_submit_request(hctx, rq); | 3788 | ret = mtip_submit_request(hctx, rq); |
| 3787 | if (likely(!ret)) | 3789 | if (likely(!ret)) |
| 3788 | return BLK_MQ_RQ_QUEUE_OK; | 3790 | return BLK_MQ_RQ_QUEUE_OK; |
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index c5b7315c2c13..332ce20d45da 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c | |||
| @@ -321,6 +321,8 @@ static int null_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *rq, | |||
| 321 | cmd->rq = rq; | 321 | cmd->rq = rq; |
| 322 | cmd->nq = hctx->driver_data; | 322 | cmd->nq = hctx->driver_data; |
| 323 | 323 | ||
| 324 | blk_mq_start_request(rq); | ||
| 325 | |||
| 324 | null_handle_cmd(cmd); | 326 | null_handle_cmd(cmd); |
| 325 | return BLK_MQ_RQ_QUEUE_OK; | 327 | return BLK_MQ_RQ_QUEUE_OK; |
| 326 | } | 328 | } |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 13756e016797..83816bf6882f 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
| @@ -205,6 +205,8 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, | |||
| 205 | } | 205 | } |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | blk_mq_start_request(req); | ||
| 209 | |||
| 208 | num = blk_rq_map_sg(hctx->queue, vbr->req, vbr->sg); | 210 | num = blk_rq_map_sg(hctx->queue, vbr->req, vbr->sg); |
| 209 | if (num) { | 211 | if (num) { |
| 210 | if (rq_data_dir(vbr->req) == WRITE) | 212 | if (rq_data_dir(vbr->req) == WRITE) |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f1df41168391..2dcd9078de48 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -1890,6 +1890,7 @@ static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, | |||
| 1890 | scsi_init_cmd_errh(cmd); | 1890 | scsi_init_cmd_errh(cmd); |
| 1891 | cmd->scsi_done = scsi_mq_done; | 1891 | cmd->scsi_done = scsi_mq_done; |
| 1892 | 1892 | ||
| 1893 | blk_mq_start_request(req); | ||
| 1893 | reason = scsi_dispatch_cmd(cmd); | 1894 | reason = scsi_dispatch_cmd(cmd); |
| 1894 | if (reason) { | 1895 | if (reason) { |
| 1895 | scsi_set_blocked(cmd, reason); | 1896 | scsi_set_blocked(cmd, reason); |
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index 9c4e306a9217..878b6f71da48 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h | |||
| @@ -159,6 +159,7 @@ struct request *blk_mq_tag_to_rq(struct blk_mq_tags *tags, unsigned int tag); | |||
| 159 | struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_index); | 159 | struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_index); |
| 160 | struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_tag_set *, unsigned int, int); | 160 | struct blk_mq_hw_ctx *blk_mq_alloc_single_hw_queue(struct blk_mq_tag_set *, unsigned int, int); |
| 161 | 161 | ||
| 162 | void blk_mq_start_request(struct request *rq); | ||
| 162 | void blk_mq_end_io(struct request *rq, int error); | 163 | void blk_mq_end_io(struct request *rq, int error); |
| 163 | void __blk_mq_end_io(struct request *rq, int error); | 164 | void __blk_mq_end_io(struct request *rq, int error); |
| 164 | 165 | ||
