From patchwork Wed May 25 07:55:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Christie X-Patchwork-Id: 9134927 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 961BE6075C for ; Wed, 25 May 2016 07:55:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8860A28091 for ; Wed, 25 May 2016 07:55:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7D15D282BE; Wed, 25 May 2016 07:55:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0F6EA28091 for ; Wed, 25 May 2016 07:55:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753312AbcEYHzN (ORCPT ); Wed, 25 May 2016 03:55:13 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38651 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753229AbcEYHzL (ORCPT ); Wed, 25 May 2016 03:55:11 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 65EBE50F5F; Wed, 25 May 2016 07:55:10 +0000 (UTC) Received: from rh2.redhat.com (vpn-61-39.rdu2.redhat.com [10.10.61.39]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u4P7t4FG009788; Wed, 25 May 2016 03:55:09 -0400 From: mchristi@redhat.com To: linux-scsi@vger.kernel.org, linux-block@vger.kernel.org, target-devel@vger.kernel.org Cc: Mike Christie Subject: [PATCH 4/5] scsi: add new async device reset support Date: Wed, 25 May 2016 02:55:02 -0500 Message-Id: <1464162903-14735-5-git-send-email-mchristi@redhat.com> In-Reply-To: <1464162903-14735-1-git-send-email-mchristi@redhat.com> References: <1464162903-14735-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 25 May 2016 07:55:10 +0000 (UTC) Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Mike Christie Currently, if the SCSI eh runs then before we do a LUN_RESET we stop the host. This patch and the block layer one before it begin to add infrastructure to be able to do a LUN_RESET and eventually do a transport level recovery without having to stop the host. For LUn-reset, this patch adds a new callout, eh_async_device_reset_handler, which works similar to how LLDs handle SG_SCSI_RESET_DEVICE where the LLD manages the commands that are affected. eh_async_device_reset_handler: The LLD should perform a LUN RESET that affects all commands that have been accepted by its queuecommand callout for the device passed in to the callout. While the reset handler is running, queuecommand will not be running or called for the device. Unlike eh_device_reset_handler, queuecommand may still be called for other devices, and the LLD must call scsi_done for the commands that have been affected by the reset. If SUCCESS or FAST_IO_FAIL is returned, the scsi_cmnds cleaned up must be failed with DID_ABORT. Signed-off-by: Mike Christie --- drivers/scsi/scsi_error.c | 31 ++++++++++++++++++++++++++++--- drivers/scsi/scsi_lib.c | 6 ++++++ drivers/scsi/scsi_priv.h | 1 + include/scsi/scsi_host.h | 17 +++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 984ddcb..cec2dfb 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -853,16 +853,41 @@ static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd) { int rtn; struct scsi_host_template *hostt = scmd->device->host->hostt; + struct scsi_device *sdev = scmd->device; - if (!hostt->eh_device_reset_handler) + if (!hostt->eh_device_reset_handler && + !hostt->eh_async_device_reset_handler) return FAILED; - rtn = hostt->eh_device_reset_handler(scmd); + if (hostt->eh_device_reset_handler) { + rtn = hostt->eh_device_reset_handler(scmd); + } else { + if (!blk_reset_queue(sdev->request_queue)) + rtn = SUCCESS; + else + rtn = FAILED; + } if (rtn == SUCCESS) - __scsi_report_device_reset(scmd->device, NULL); + __scsi_report_device_reset(sdev, NULL); return rtn; } +enum blk_eh_timer_return scsi_reset_queue(struct request_queue *q) +{ + struct scsi_device *sdev = q->queuedata; + struct scsi_host_template *hostt = sdev->host->hostt; + int rtn; + + if (!hostt->eh_async_device_reset_handler) + return -EOPNOTSUPP; + + rtn = hostt->eh_async_device_reset_handler(sdev); + if (rtn == SUCCESS || rtn == FAST_IO_FAIL) + return BLK_EH_HANDLED; + + return BLK_EH_NOT_HANDLED; +} + /** * scsi_try_to_abort_cmd - Ask host to abort a SCSI command * @hostt: SCSI driver host template diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 8106515..11374dd 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -779,6 +779,10 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result) set_host_byte(cmd, DID_OK); error = -ENODATA; break; + case DID_ABORT: + set_host_byte(cmd, DID_OK); + error = -EINTR; + break; default: error = -EIO; break; @@ -2159,6 +2163,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) blk_queue_softirq_done(q, scsi_softirq_done); blk_queue_rq_timed_out(q, scsi_times_out); blk_queue_lld_busy(q, scsi_lld_busy); + blk_queue_reset(q, scsi_reset_queue); return q; } @@ -2167,6 +2172,7 @@ static struct blk_mq_ops scsi_mq_ops = { .queue_rq = scsi_queue_rq, .complete = scsi_softirq_done, .timeout = scsi_timeout, + .reset = scsi_reset_queue, .init_request = scsi_init_request, .exit_request = scsi_exit_request, }; diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 27b4d0a..2e03168 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -67,6 +67,7 @@ extern void scsi_exit_devinfo(void); /* scsi_error.c */ extern void scmd_eh_abort_handler(struct work_struct *work); +extern enum blk_eh_timer_return scsi_reset_queue(struct request_queue *q); extern enum blk_eh_timer_return scsi_times_out(struct request *req); extern int scsi_error_handler(void *host); extern int scsi_decide_disposition(struct scsi_cmnd *cmd); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index fcfa3d7..532deb5 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -146,6 +146,23 @@ struct scsi_host_template { */ int (* eh_abort_handler)(struct scsi_cmnd *); int (* eh_device_reset_handler)(struct scsi_cmnd *); + /* + * eh_async_device_reset_handler - Perform LUN RESET + * @scsi_device: scsi device to reset + * + * The LLD should perform a LUN RESET that affects all commands + * that have been accepted by its queuecommand callout for the + * device passed in. While the reset handler is running, queuecommand + * will not be called for the device. + * + * Unlike eh_device_reset_handler, queuecommand may still be called + * for other devices, and the LLD must call scsi_done for the commands + * that have been affected by the reset. + * + * If SUCCESS or FAST_IO_FAIL is returned, the scsi_cmnds for + * scsi_device must be failed with DID_ABORT. + */ + int (* eh_async_device_reset_handler)(struct scsi_device *); int (* eh_target_reset_handler)(struct scsi_cmnd *); int (* eh_bus_reset_handler)(struct scsi_cmnd *); int (* eh_host_reset_handler)(struct scsi_cmnd *);