From patchwork Mon Apr 27 21:47:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Krivenok X-Patchwork-Id: 6283481 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 9BE089F1C2 for ; Mon, 27 Apr 2015 21:47:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D28DA20328 for ; Mon, 27 Apr 2015 21:47:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AA68220306 for ; Mon, 27 Apr 2015 21:47:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965251AbbD0Vrw (ORCPT ); Mon, 27 Apr 2015 17:47:52 -0400 Received: from mail-yk0-f175.google.com ([209.85.160.175]:34904 "EHLO mail-yk0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965070AbbD0Vru (ORCPT ); Mon, 27 Apr 2015 17:47:50 -0400 Received: by ykec202 with SMTP id c202so22299064yke.2 for ; Mon, 27 Apr 2015 14:47:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=vrDowixwL2Ew1JOSnp97PG4TdZWaVb5F7abAAV8UJV8=; b=N06c1dKjJN6vV8yKZK0KSg2P5iZHUfR/b9cN5+KzdJAxmjNViYnZYYsHQIK1B08a8j jY7IfPJSUj8BrcTKhMw1hk3+dq2c+hsFQumiavvYbBQ0xPFyxd01C1HHSg+pUPT4AUfz cVlhZw3BH1/vO4Y3FnuJml7nIzxoSyWD0y2sKyffyW6gOlbv3n91S2YYUTU38dRp4PeD pUa7en/GRX2oXfP5oeqjATc3dFcRMTFXtF+CXL5q0urYoSOkQG63/EFh3JUxwUiph9ww DIdPXscB5n3cZyH8vUCX0y1wSiyfyWjQ8kWGSFSYI6SOOIw+PKZK0lLrJ4WkM0Kpavbf p0DA== MIME-Version: 1.0 X-Received: by 10.236.4.129 with SMTP id 1mr12929503yhj.179.1430171269476; Mon, 27 Apr 2015 14:47:49 -0700 (PDT) Received: by 10.129.98.137 with HTTP; Mon, 27 Apr 2015 14:47:49 -0700 (PDT) In-Reply-To: <553E7397.2010208@kernel.dk> References: <553E70FA.1080302@kernel.dk> <553E7397.2010208@kernel.dk> Date: Tue, 28 Apr 2015 00:47:49 +0300 Message-ID: Subject: Re: [PATCH 1/1] null_blk: fix handling of BLKPREP_DEFER case From: Dmitry Krivenok To: Jens Axboe Cc: linux-fsdevel@vger.kernel.org Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, T_TVD_MIME_EPI,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP I think we need to surround blk_start_queue() call with queue lock/unlock as it expects that lock should be held. Slightly modified patch is attached. I've tested it using the same commands as before. Thanks, Dmitry On Mon, Apr 27, 2015 at 8:36 PM, Jens Axboe wrote: > On 04/27/2015 11:25 AM, Jens Axboe wrote: >> >> On 04/19/2015 12:19 PM, Dmitry Krivenok wrote: >>> >>> When we fail to allocate new cmd in null_rq_prep_fn we return >>> BLKPREP_DEFER >>> which is not handled properly. In single-queue mode of null_blk the >>> following >>> command hangs forever in io_schedule(): >>> $ dd if=/dev/nullb0 of=/dev/null bs=8M count=5000 iflag=direct >>> >>> The reason is that when 64 commands have been allocated, the 65th command >>> allocation will fail due to missing free tag. The request, however, >>> will be >>> kept in the queue which will never be started again (unless you run >>> another >>> command that does I/O to /dev/nullb0). >>> >>> This small patch tries to solve the issue by stopping the queue when we >>> detect that all tags were exhausted and starting it again when we free >>> the tag. >>> >>> I've verified that the command mentioned above doesn't hang anymore >>> and also >>> made sure that null_blk with my change survives fio-based stress tests. >> >> >> You are right, legacy request_fn mode has a bug there. I'd get rid of >> the no_cmds bool, though. If we fail allocating a command in alloc_cmd() >> and we're in NULL_Q_RQ mode, stop the queue. In free_cmd(), again if >> we're in NULL_Q_RQ_MODE, check the stopped flag and start the queue if >> it is set. > > > Something like the attached, totally untested. > > -- > Jens Axboe > From c5dfcc7f3d3f79688dbf06aeb099f1a036f42bb9 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Krivenok" Date: Tue, 28 Apr 2015 00:39:21 +0300 Subject: [PATCH 1/1] null_blk: fix handling of BLKPREP_DEFER case This is a fix for BLKPREP_DEFER case in single queue mode. It's rework of original implementation based on feedback from Jens (basically his version plus locking fix). Signed-off-by: Dmitry V. Krivenok --- drivers/block/null_blk.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index 65cd61a..a26b57f 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -24,6 +24,7 @@ struct nullb_queue { wait_queue_head_t wait; unsigned int queue_depth; + struct nullb *dev; struct nullb_cmd *cmds; }; @@ -153,6 +154,16 @@ static void put_tag(struct nullb_queue *nq, unsigned int tag) if (waitqueue_active(&nq->wait)) wake_up(&nq->wait); + + if (queue_mode == NULL_Q_RQ) { + struct nullb *nullb = nq->dev; + + if (blk_queue_stopped(nullb->q)) { + spin_lock_irq(nullb->q->queue_lock); + blk_start_queue(nullb->q); + spin_unlock_irq(nullb->q->queue_lock); + } + } } static unsigned int get_tag(struct nullb_queue *nq) @@ -196,7 +207,7 @@ static struct nullb_cmd *alloc_cmd(struct nullb_queue *nq, int can_wait) cmd = __alloc_cmd(nq); if (cmd || !can_wait) - return cmd; + goto out; do { prepare_to_wait(&nq->wait, &wait, TASK_UNINTERRUPTIBLE); @@ -208,6 +219,11 @@ static struct nullb_cmd *alloc_cmd(struct nullb_queue *nq, int can_wait) } while (1); finish_wait(&nq->wait, &wait); +out: + if (!cmd) { + BUG_ON(queue_mode != NULL_Q_RQ); + blk_stop_queue(nq->dev->q); + } return cmd; } @@ -372,6 +388,7 @@ static void null_init_queue(struct nullb *nullb, struct nullb_queue *nq) init_waitqueue_head(&nq->wait); nq->queue_depth = nullb->queue_depth; + nq->dev = nullb; } static int null_init_hctx(struct blk_mq_hw_ctx *hctx, void *data, -- 2.3.6