From patchwork Wed Jan 5 20:35:10 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Dillow X-Patchwork-Id: 454811 X-Patchwork-Delegate: dave@thedillows.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p05KZUCa023977 for ; Wed, 5 Jan 2011 20:35:30 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752357Ab1AEUf1 (ORCPT ); Wed, 5 Jan 2011 15:35:27 -0500 Received: from amavis-outgoing1.knology.net ([24.214.64.230]:56969 "EHLO amavis-outgoing1.knology.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752547Ab1AEUfV (ORCPT ); Wed, 5 Jan 2011 15:35:21 -0500 Received: from localhost (amavis-outbound1 [127.0.0.1]) by amavis-outgoing1.knology.net (Postfix) with ESMTP id 294A66806F; Wed, 5 Jan 2011 15:35:19 -0500 (EST) Received: from smtp5.knology.net ([192.168.200.214]) by localhost (amavis-outgoing1.knology.net [192.168.200.230]) (amavisd-new, port 10024) with LMTP id hKI4MOIdtwwH; Wed, 5 Jan 2011 15:35:15 -0500 (EST) Received: from shed.thedillows.org (unknown [207.98.218.89]) by smtp5.knology.net (Postfix) with ESMTP id 435C2703A9; Wed, 5 Jan 2011 15:35:17 -0500 (EST) Received: from obelisk.thedillows.org (obelisk.thedillows.org [192.168.0.10]) by shed.thedillows.org (8.14.4/8.14.4) with ESMTP id p05KZGg4014196 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 5 Jan 2011 15:35:16 -0500 Received: from obelisk.thedillows.org (localhost [127.0.0.1]) by obelisk.thedillows.org (8.14.4/8.14.3) with ESMTP id p05KZGUY030747; Wed, 5 Jan 2011 15:35:16 -0500 Received: (from dad@localhost) by obelisk.thedillows.org (8.14.4/8.14.4/Submit) id p05KZGNl030746; Wed, 5 Jan 2011 15:35:16 -0500 X-Authentication-Warning: obelisk.thedillows.org: dad set sender to dave@thedillows.org using -f From: David Dillow To: linux-rdma@vger.kernel.org Cc: linux-scsi@vger.kernel.org, bvanassche@acm.org Subject: [PATCH v2 2/8] IB/srp: consolidate state change code Date: Wed, 5 Jan 2011 15:35:10 -0500 Message-Id: <1294259716-30706-3-git-send-email-dillowda@ornl.gov> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1294259716-30706-1-git-send-email-dillowda@ornl.gov> References: <1294259716-30706-1-git-send-email-dillowda@ornl.gov> Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 05 Jan 2011 20:35:30 +0000 (UTC) diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 29429a1..def9e6b 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -441,18 +441,28 @@ static void srp_disconnect_target(struct srp_target_port *target) wait_for_completion(&target->done); } +static bool srp_change_state(struct srp_target_port *target, + enum srp_target_state old, + enum srp_target_state new) +{ + bool changed = false; + + spin_lock_irq(target->scsi_host->host_lock); + if (target->state == old) { + target->state = new; + changed = true; + } + spin_unlock_irq(target->scsi_host->host_lock); + return changed; +} + static void srp_remove_work(struct work_struct *work) { struct srp_target_port *target = container_of(work, struct srp_target_port, work); - spin_lock_irq(target->scsi_host->host_lock); - if (target->state != SRP_TARGET_DEAD) { - spin_unlock_irq(target->scsi_host->host_lock); + if (!srp_change_state(target, SRP_TARGET_DEAD, SRP_TARGET_REMOVED)) return; - } - target->state = SRP_TARGET_REMOVED; - spin_unlock_irq(target->scsi_host->host_lock); spin_lock(&target->srp_host->target_lock); list_del(&target->list); @@ -560,13 +570,8 @@ static int srp_reconnect_target(struct srp_target_port *target) struct ib_wc wc; int ret; - spin_lock_irq(target->scsi_host->host_lock); - if (target->state != SRP_TARGET_LIVE) { - spin_unlock_irq(target->scsi_host->host_lock); + if (!srp_change_state(target, SRP_TARGET_LIVE, SRP_TARGET_CONNECTING)) return -EAGAIN; - } - target->state = SRP_TARGET_CONNECTING; - spin_unlock_irq(target->scsi_host->host_lock); srp_disconnect_target(target); /* @@ -605,13 +610,8 @@ static int srp_reconnect_target(struct srp_target_port *target) if (ret) goto err; - spin_lock_irq(target->scsi_host->host_lock); - if (target->state == SRP_TARGET_CONNECTING) { - ret = 0; - target->state = SRP_TARGET_LIVE; - } else + if (!srp_change_state(target, SRP_TARGET_CONNECTING, SRP_TARGET_LIVE)) ret = -EAGAIN; - spin_unlock_irq(target->scsi_host->host_lock); return ret; @@ -621,9 +621,12 @@ err: /* * We couldn't reconnect, so kill our target port off. - * However, we have to defer the real removal because we might - * be in the context of the SCSI error handler now, which - * would deadlock if we call scsi_remove_host(). + * However, we have to defer the real removal because we + * are in the context of the SCSI error handler now, which + * will deadlock if we call scsi_remove_host(). + * + * Schedule our work inside the lock to avoid a race with + * the flush_scheduled_work() in srp_remove_one(). */ spin_lock_irq(target->scsi_host->host_lock); if (target->state == SRP_TARGET_CONNECTING) {