Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753870AbbKBOwd (ORCPT ); Mon, 2 Nov 2015 09:52:33 -0500 Received: from smtp7.sms.unimo.it ([155.185.44.150]:48515 "EHLO smtp7.sms.unimo.it" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753397AbbKBOwa (ORCPT ); Mon, 2 Nov 2015 09:52:30 -0500 From: Paolo Valente To: Jens Axboe , =?UTF-8?q?Matias=20Bj=C3=B8rling?= , Arianna Avanzini Cc: Paolo Valente , Akinobu Mita , "Luis R. Rodriguez" , Ming Lei , Mike Krinkin , linux-kernel@vger.kernel.org Subject: [PATCH BUGFIX 2/3] null_blk: guarantee device restart in all irq modes Date: Mon, 2 Nov 2015 15:31:12 +0100 Message-Id: <1446474673-2566-3-git-send-email-paolo.valente@unimore.it> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1446474673-2566-1-git-send-email-paolo.valente@unimore.it> References: <1446474673-2566-1-git-send-email-paolo.valente@unimore.it> UNIMORE-X-SA-Score: -2.9 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2566 Lines: 84 From: Arianna Avanzini In single-queue (block layer) mode,the function null_rq_prep_fn stops the device if alloc_cmd fails. Then, once stopped, the device must be restarted on the next command completion, so that the request(s) for which alloc_cmd failed can be requeued. Otherwise the device hangs. Unfortunately, device restart is currently performed only for delayed completions, i.e., in irqmode==2. This fact causes hangs, for the above reasons, with the other irqmodes in combination with single-queue block layer. This commits addresses this issue by making sure that, if stopped, the device is properly restarted for all irqmodes on completions. Signed-off-by: Paolo Valente Signed-off-by: Arianna AVanzini --- drivers/block/null_blk.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index 7db5a77..caaff67 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -210,6 +210,8 @@ static struct nullb_cmd *alloc_cmd(struct nullb_queue *nq, int can_wait) static void end_cmd(struct nullb_cmd *cmd) { + struct request_queue *q = NULL; + switch (queue_mode) { case NULL_Q_MQ: blk_mq_end_request(cmd->rq, 0); @@ -220,27 +222,28 @@ static void end_cmd(struct nullb_cmd *cmd) break; case NULL_Q_BIO: bio_endio(cmd->bio); - break; + goto free_cmd; } - free_cmd(cmd); -} - -static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) -{ - struct nullb_cmd *cmd = container_of(timer, struct nullb_cmd, timer); - struct request_queue *q = NULL; - if (cmd->rq) q = cmd->rq->q; - if (q && !q->mq_ops && blk_queue_stopped(q)) { - spin_lock(q->queue_lock); + /* Restart queue if needed, as we are freeing a tag */ + if (q && blk_queue_stopped(q)) { + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); if (blk_queue_stopped(q)) blk_start_queue(q); - spin_unlock(q->queue_lock); + spin_unlock_irqrestore(q->queue_lock, flags); } - end_cmd(cmd); +free_cmd: + free_cmd(cmd); +} + +static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer) +{ + end_cmd(container_of(timer, struct nullb_cmd, timer)); return HRTIMER_NORESTART; } -- 1.9.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/