Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751725AbbECAcM (ORCPT ); Sat, 2 May 2015 20:32:12 -0400 Received: from mx0b-00082601.pphosted.com ([67.231.153.30]:55075 "EHLO mx0a-00082601.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750812AbbECAcD (ORCPT ); Sat, 2 May 2015 20:32:03 -0400 From: Shaohua Li To: CC: , Subject: [PATCH] blk-mq: don't lose requests if a stopped queue restarts Date: Sat, 2 May 2015 17:31:58 -0700 Message-ID: <430595847fe98f99e1c8ea79b018003d9315f905.1430613052.git.shli@fb.com> X-Mailer: git-send-email 1.8.1 X-FB-Internal: Safe MIME-Version: 1.0 Content-Type: text/plain X-Proofpoint-Spam-Reason: safe X-FB-Internal: Safe X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.13.68,1.0.33,0.0.0000 definitions=2015-05-02_02:2015-05-02,2015-05-02,1970-01-01 signatures=0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1768 Lines: 57 Normally if driver is busy to dispatch a request the logic is like below: block layer: driver: __blk_mq_run_hw_queue a. blk_mq_stop_hw_queue b. rq add to ctx->dispatch later: 1. blk_mq_start_hw_queue 2. __blk_mq_run_hw_queue But it's possible step 1-2 runs between a and b. And since rq isn't in ctx->dispatch yet, step 2 will not run rq. The rq might get lost if there are no subsequent requests kick in. Signed-off-by: Shaohua Li --- block/blk-mq.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index ade8a2d..e6822a2 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -772,6 +772,7 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx) WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask)); +again: if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state))) return; @@ -853,8 +854,16 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx) */ if (!list_empty(&rq_list)) { spin_lock(&hctx->lock); - list_splice(&rq_list, &hctx->dispatch); + list_splice_init(&rq_list, &hctx->dispatch); spin_unlock(&hctx->lock); + /* + * the queue is expected stopped with BLK_MQ_RQ_QUEUE_BUSY, but + * it's possible the queue is stopped and restarted again + * before this. Queue restart will dispatch requests. And since + * requests in rq_list aren't added into hctx->dispatch yet, + * the requests in rq_list might get lost. + **/ + goto again; } } -- 1.8.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/