On 1/26/19 11:37 PM, Florian Stecker wrote: > > > On 1/26/19 2:25 AM, jianchao.wang wrote: ... >>>> >>>> dmesg: https://urldefense.proofpoint.com/v2/url?u=https-3A__florianstecker.de_dmesg-2D2019-2D01-2D25.txt&d=DwIDaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=7WdAxUBeiTUTCy8v-7zXyr4qk7sx26ATvfo6QSTvZyQ&m=t_udGGsH8ivtjXHin4oQ4LxELuPoXbl_ARP7oSxiQ6k&s=DC2fhRw2g4haGhhHxOYyX4zD6FWQQ5YoERdfptVRHM4&e= >>>> Note that no I/O scheduler is in use here, I deactivated them in a udev rule because I still want to be able to use my laptop. When I test this stuff I just reactivate mq-deadline manually. >>>> >>>> Config is the default in Arch Linux: https://urldefense.proofpoint.com/v2/url?u=https-3A__git.archlinux.org_svntogit_packages.git_tree_trunk_config-3Fh-3Dpackages_linux&d=DwIDaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=7WdAxUBeiTUTCy8v-7zXyr4qk7sx26ATvfo6QSTvZyQ&m=t_udGGsH8ivtjXHin4oQ4LxELuPoXbl_ARP7oSxiQ6k&s=GjV_fyXaKZ8za8zdB_gqmKW7yBlbla2OHRaAT0iGZkc&e= >>>> >>>> The problem also appears with BFQ. >>>> >>>> And rq->end_io is set to mq_flush_data_end_io when this happens. The only point I see where this function could invoke blk_mq_end_request is via blk_flush_complete_seq, but it does so only if seq == REQ_FSEQ_DONE. However, seq is REQ_FSEQ_POSTFLUSH for me (i.e. it just transitioned from REQ_FSEQ_DATA to REQ_FSEQ_POSTFLUSH). >>> >>> >>> Could it be this scenario ? >>> >>> data + post flush >>> >>> blk_flush_complete_seq a flush >>> case REQ_FSEQ_DATA >>> blk_flush_queue_rq >>> finally issued to driver blk_mq_dispatch_rq_list >>> try to issue a flush req >>> failed due to NON-NCQ command >>> due to RESTART is set, do nothing >>> req complete >>> req->end_io() // doesn't check RESTART >>> mq_flush_data_end_io >>> blk_flush_complete_seq >>> case REQ_FSEQ_POSTFLUSH >>> blk_kick_flush >>> do nothing because previous flush >>> has not been completed, so >>> flush_pending_idx != flush_running_idx >>> This should be corrected as following, data + post flush blk_flush_complete_seq a flush case REQ_FSEQ_DATA blk_flush_queue_rq finally issued to driver blk_mq_dispatch_rq_list try to issue a flush req failed due to NON-NCQ command return BLK_STS_DEV_RESOURCE req complete req->end_io() // doesn't check RESTART mq_flush_data_end_io case REQ_FSEQ_POSTFLUSH blk_kick_flush do nothing because previous flush has not been completed, so flush_pending_idx != flush_running_idx blk_mq_mq_run_hw_queue insert rq to hctx->dispatch_list due to RESTART is set, do nothing ... > I'm not sure if I understand every detail, but your scenario sounds roughly the same as what I imagine. The patch solves the problem for me (except for the fact that hctx is not defined in that function). > > Actually, it doesn't seem to me as if any of the other users of blk_mq_free_request require or even expect that it calls blk_mq_sched_restart (I could be wrong though). If that is true, how about we just call it from __blk_mq_end_request, like this (also tested successfully on my laptop)? > > diff --git a/block/blk-mq.c b/block/blk-mq.c > index 6a7566244de3..9f3d3456c4af 100644 > --- a/block/blk-mq.c > +++ b/block/blk-mq.c > @@ -481,7 +481,6 @@ static void __blk_mq_free_request(struct request *rq) > blk_mq_put_tag(hctx, hctx->tags, ctx, rq->tag); > if (sched_tag != -1) > blk_mq_put_tag(hctx, hctx->sched_tags, ctx, sched_tag); > - blk_mq_sched_restart(hctx); > blk_queue_exit(q); > } > > @@ -522,6 +521,7 @@ EXPORT_SYMBOL_GPL(blk_mq_free_request); > inline void __blk_mq_end_request(struct request *rq, blk_status_t error) > { > u64 now = ktime_get_ns(); > + struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(rq->q, rq->mq_ctx->cpu); > > if (rq->rq_flags & RQF_STATS) { > blk_mq_poll_stats_start(rq->q); > @@ -541,6 +541,8 @@ inline void __blk_mq_end_request(struct request *rq, blk_status_t error) > blk_mq_free_request(rq->next_rq); > blk_mq_free_request(rq); > } > + > + blk_mq_sched_restart(hctx); > } > EXPORT_SYMBOL(__blk_mq_end_request); We should invoke blk_mq_sched_restart before blk_queue_exit is invoked. How about this one ? diff --git a/block/blk-flush.c b/block/blk-flush.c index a3fc7191..6e0f2d9 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -335,7 +335,7 @@ static void mq_flush_data_end_io(struct request *rq, blk_status_t error) blk_flush_complete_seq(rq, fq, REQ_FSEQ_DATA, error); spin_unlock_irqrestore(&fq->mq_flush_lock, flags); - blk_mq_run_hw_queue(hctx, true); + blk_mq_sched_restart(hctx); } Thanks Jianchao