Skip to content

Commit 65fac0d

Browse files
YuKuai-huaweiaxboe
authored andcommitted
blk-mq: fix io hung due to missing commit_rqs
Currently, in virtio_scsi, if 'bd->last' is not set to true while dispatching request, such io will stay in driver's queue, and driver will wait for block layer to dispatch more rqs. However, if block layer failed to dispatch more rq, it should trigger commit_rqs to inform driver. There is a problem in blk_mq_try_issue_list_directly() that commit_rqs won't be called: // assume that queue_depth is set to 1, list contains two rq blk_mq_try_issue_list_directly blk_mq_request_issue_directly // dispatch first rq // last is false __blk_mq_try_issue_directly blk_mq_get_dispatch_budget // succeed to get first budget __blk_mq_issue_directly scsi_queue_rq cmd->flags |= SCMD_LAST virtscsi_queuecommand kick = (sc->flags & SCMD_LAST) != 0 // kick is false, first rq won't issue to disk queued++ blk_mq_request_issue_directly // dispatch second rq __blk_mq_try_issue_directly blk_mq_get_dispatch_budget // failed to get second budget ret == BLK_STS_RESOURCE blk_mq_request_bypass_insert // errors is still 0 if (!list_empty(list) || errors && ...) // won't pass, commit_rqs won't be called In this situation, first rq relied on second rq to dispatch, while second rq relied on first rq to complete, thus they will both hung. Fix the problem by also treat 'BLK_STS_*RESOURCE' as 'errors' since it means that request is not queued successfully. Same problem exists in blk_mq_dispatch_rq_list(), 'BLK_STS_*RESOURCE' can't be treated as 'errors' here, fix the problem by calling commit_rqs if queue_rq return 'BLK_STS_*RESOURCE'. Fixes: d666ba9 ("blk-mq: add mq_ops->commit_rqs()") Signed-off-by: Yu Kuai <[email protected]> Reviewed-by: Ming Lei <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent d3b3859 commit 65fac0d

File tree

1 file changed

+3
-2
lines changed

1 file changed

+3
-2
lines changed

block/blk-mq.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,7 +1931,8 @@ bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list,
19311931
/* If we didn't flush the entire list, we could have told the driver
19321932
* there was more coming, but that turned out to be a lie.
19331933
*/
1934-
if ((!list_empty(list) || errors) && q->mq_ops->commit_rqs && queued)
1934+
if ((!list_empty(list) || errors || needs_resource ||
1935+
ret == BLK_STS_DEV_RESOURCE) && q->mq_ops->commit_rqs && queued)
19351936
q->mq_ops->commit_rqs(hctx);
19361937
/*
19371938
* Any items that need requeuing? Stuff them into hctx->dispatch,
@@ -2660,14 +2661,14 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
26602661
list_del_init(&rq->queuelist);
26612662
ret = blk_mq_request_issue_directly(rq, list_empty(list));
26622663
if (ret != BLK_STS_OK) {
2664+
errors++;
26632665
if (ret == BLK_STS_RESOURCE ||
26642666
ret == BLK_STS_DEV_RESOURCE) {
26652667
blk_mq_request_bypass_insert(rq, false,
26662668
list_empty(list));
26672669
break;
26682670
}
26692671
blk_mq_end_request(rq, ret);
2670-
errors++;
26712672
} else
26722673
queued++;
26732674
}

0 commit comments

Comments
 (0)