From patchwork Fri Jun 22 06:25:32 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Williams X-Patchwork-Id: 166511 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id CF7AAB6F77 for ; Fri, 22 Jun 2012 16:08:56 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1761315Ab2FVGIz (ORCPT ); Fri, 22 Jun 2012 02:08:55 -0400 Received: from mga09.intel.com ([134.134.136.24]:4423 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1761300Ab2FVGIy (ORCPT ); Fri, 22 Jun 2012 02:08:54 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 21 Jun 2012 23:08:53 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.67,352,1309762800"; d="scan'208";a="157017203" Received: from dwillia2-linux.jf.intel.com ([10.7.137.146]) by orsmga001.jf.intel.com with ESMTP; 21 Jun 2012 23:08:53 -0700 Received: from dwillia2-linux.jf.intel.com (localhost.localdomain [IPv6:::1]) by dwillia2-linux.jf.intel.com (Postfix) with ESMTP id B58C78003D; Thu, 21 Jun 2012 23:25:32 -0700 (PDT) Subject: [set1 PATCH 2/4] scsi: fix eh wakeup (scsi_schedule_eh vs scsi_restart_operations) To: linux-scsi@vger.kernel.org From: Dan Williams Cc: Tejun Heo , linux-ide@vger.kernel.org, Tom Jackson , stable@vger.kernel.org Date: Thu, 21 Jun 2012 23:25:32 -0700 Message-ID: <20120622062532.21162.59654.stgit@dwillia2-linux.jf.intel.com> In-Reply-To: <20120622062521.21162.31523.stgit@dwillia2-linux.jf.intel.com> References: <20120622062521.21162.31523.stgit@dwillia2-linux.jf.intel.com> User-Agent: StGit/0.16-1-g7004 MIME-Version: 1.0 Sender: linux-ide-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ide@vger.kernel.org Rapid ata hotplug on a libsas controller results in cases where libsas is waiting indefinitely on eh to perform an ata probe. A race exists between scsi_schedule_eh() and scsi_restart_operations() in the case when scsi_restart_operations() issues i/o to other devices in the sas domain. When this happens the host state transitions from SHOST_RECOVERY (set by scsi_schedule_eh) back to SHOST_RUNNING and ->host_busy is non-zero so we put the eh thread to sleep even though ->host_eh_scheduled is active. Before putting the error handler to sleep we need to check if the host_state needs to return to SHOST_RECOVERY for another trip through eh. Since i/o that is released by scsi_restart_operations has been blocked for at least one eh cycle, this implementation allows those i/o's to run before another eh cycle starts to discourage hung task timeouts. Cc: Tejun Heo Cc: Reported-by: Tom Jackson Tested-by: Tom Jackson Signed-off-by: Dan Williams --- drivers/scsi/scsi_error.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index d0f71e5..804f632 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1687,6 +1687,20 @@ static void scsi_restart_operations(struct Scsi_Host *shost) * requests are started. */ scsi_run_host_queues(shost); + + /* + * if eh is active and host_eh_scheduled is pending we need to re-run + * recovery. we do this check after scsi_run_host_queues() to allow + * everything pent up since the last eh run a chance to make forward + * progress before we sync again. Either we'll immediately re-run + * recovery or scsi_device_unbusy() will wake us again when these + * pending commands complete. + */ + spin_lock_irqsave(shost->host_lock, flags); + if (shost->host_eh_scheduled) + if (scsi_host_set_state(shost, SHOST_RECOVERY)) + WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)); + spin_unlock_irqrestore(shost->host_lock, flags); } /**