Skip to content

Commit 01e99ae

Browse files
Ming Leiaxboe
authored andcommitted
blk-mq: insert passthrough request into hctx->dispatch directly
For some reason, device may be in one situation which can't handle FS request, so STS_RESOURCE is always returned and the FS request will be added to hctx->dispatch. However passthrough request may be required at that time for fixing the problem. If passthrough request is added to scheduler queue, there isn't any chance for blk-mq to dispatch it given we prioritize requests in hctx->dispatch. Then the FS IO request may never be completed, and IO hang is caused. So passthrough request has to be added to hctx->dispatch directly for fixing the IO hang. Fix this issue by inserting passthrough request into hctx->dispatch directly together withing adding FS request to the tail of hctx->dispatch in blk_mq_dispatch_rq_list(). Actually we add FS request to tail of hctx->dispatch at default, see blk_mq_request_bypass_insert(). Then it becomes consistent with original legacy IO request path, in which passthrough request is always added to q->queue_head. Cc: Dongli Zhang <[email protected]> Cc: Christoph Hellwig <[email protected]> Cc: Ewan D. Milne <[email protected]> Signed-off-by: Ming Lei <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent f8788d8 commit 01e99ae

File tree

4 files changed

+29
-16
lines changed

4 files changed

+29
-16
lines changed

block/blk-flush.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ void blk_insert_flush(struct request *rq)
412412
*/
413413
if ((policy & REQ_FSEQ_DATA) &&
414414
!(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
415-
blk_mq_request_bypass_insert(rq, false);
415+
blk_mq_request_bypass_insert(rq, false, false);
416416
return;
417417
}
418418

block/blk-mq-sched.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -361,13 +361,19 @@ static bool blk_mq_sched_bypass_insert(struct blk_mq_hw_ctx *hctx,
361361
bool has_sched,
362362
struct request *rq)
363363
{
364-
/* dispatch flush rq directly */
365-
if (rq->rq_flags & RQF_FLUSH_SEQ) {
366-
spin_lock(&hctx->lock);
367-
list_add(&rq->queuelist, &hctx->dispatch);
368-
spin_unlock(&hctx->lock);
364+
/*
365+
* dispatch flush and passthrough rq directly
366+
*
367+
* passthrough request has to be added to hctx->dispatch directly.
368+
* For some reason, device may be in one situation which can't
369+
* handle FS request, so STS_RESOURCE is always returned and the
370+
* FS request will be added to hctx->dispatch. However passthrough
371+
* request may be required at that time for fixing the problem. If
372+
* passthrough request is added to scheduler queue, there isn't any
373+
* chance to dispatch it given we prioritize requests in hctx->dispatch.
374+
*/
375+
if ((rq->rq_flags & RQF_FLUSH_SEQ) || blk_rq_is_passthrough(rq))
369376
return true;
370-
}
371377

372378
if (has_sched)
373379
rq->rq_flags |= RQF_SORTED;
@@ -391,8 +397,10 @@ void blk_mq_sched_insert_request(struct request *rq, bool at_head,
391397

392398
WARN_ON(e && (rq->tag != -1));
393399

394-
if (blk_mq_sched_bypass_insert(hctx, !!e, rq))
400+
if (blk_mq_sched_bypass_insert(hctx, !!e, rq)) {
401+
blk_mq_request_bypass_insert(rq, at_head, false);
395402
goto run;
403+
}
396404

397405
if (e && e->type->ops.insert_requests) {
398406
LIST_HEAD(list);

block/blk-mq.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ static void blk_mq_requeue_work(struct work_struct *work)
735735
* merge.
736736
*/
737737
if (rq->rq_flags & RQF_DONTPREP)
738-
blk_mq_request_bypass_insert(rq, false);
738+
blk_mq_request_bypass_insert(rq, false, false);
739739
else
740740
blk_mq_sched_insert_request(rq, true, false, false);
741741
}
@@ -1286,7 +1286,7 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list,
12861286
q->mq_ops->commit_rqs(hctx);
12871287

12881288
spin_lock(&hctx->lock);
1289-
list_splice_init(list, &hctx->dispatch);
1289+
list_splice_tail_init(list, &hctx->dispatch);
12901290
spin_unlock(&hctx->lock);
12911291

12921292
/*
@@ -1677,12 +1677,16 @@ void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
16771677
* Should only be used carefully, when the caller knows we want to
16781678
* bypass a potential IO scheduler on the target device.
16791679
*/
1680-
void blk_mq_request_bypass_insert(struct request *rq, bool run_queue)
1680+
void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
1681+
bool run_queue)
16811682
{
16821683
struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
16831684

16841685
spin_lock(&hctx->lock);
1685-
list_add_tail(&rq->queuelist, &hctx->dispatch);
1686+
if (at_head)
1687+
list_add(&rq->queuelist, &hctx->dispatch);
1688+
else
1689+
list_add_tail(&rq->queuelist, &hctx->dispatch);
16861690
spin_unlock(&hctx->lock);
16871691

16881692
if (run_queue)
@@ -1849,7 +1853,7 @@ static blk_status_t __blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
18491853
if (bypass_insert)
18501854
return BLK_STS_RESOURCE;
18511855

1852-
blk_mq_request_bypass_insert(rq, run_queue);
1856+
blk_mq_request_bypass_insert(rq, false, run_queue);
18531857
return BLK_STS_OK;
18541858
}
18551859

@@ -1876,7 +1880,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
18761880

18771881
ret = __blk_mq_try_issue_directly(hctx, rq, cookie, false, true);
18781882
if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE)
1879-
blk_mq_request_bypass_insert(rq, true);
1883+
blk_mq_request_bypass_insert(rq, false, true);
18801884
else if (ret != BLK_STS_OK)
18811885
blk_mq_end_request(rq, ret);
18821886

@@ -1910,7 +1914,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
19101914
if (ret != BLK_STS_OK) {
19111915
if (ret == BLK_STS_RESOURCE ||
19121916
ret == BLK_STS_DEV_RESOURCE) {
1913-
blk_mq_request_bypass_insert(rq,
1917+
blk_mq_request_bypass_insert(rq, false,
19141918
list_empty(list));
19151919
break;
19161920
}

block/blk-mq.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ int blk_mq_alloc_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags,
6666
*/
6767
void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
6868
bool at_head);
69-
void blk_mq_request_bypass_insert(struct request *rq, bool run_queue);
69+
void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
70+
bool run_queue);
7071
void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
7172
struct list_head *list);
7273

0 commit comments

Comments
 (0)