linux-rdma.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bart Van Assche <bvanassche-HInyCGIudOg@public.gmane.org>
To: "linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
	<linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Cc: David Dillow <dillowda-1Heg1YXhbW8@public.gmane.org>,
	Roland Dreier <roland-BHEL68pLQRGGvPXPguhicg@public.gmane.org>
Subject: [PATCH 09/20] ib_srp: Eliminate state SRP_TARGET_DEAD
Date: Thu, 09 Aug 2012 15:51:48 +0000	[thread overview]
Message-ID: <5023DC94.5050205@acm.org> (raw)
In-Reply-To: <5023DA39.7020000-HInyCGIudOg@public.gmane.org>

Only queue removal work after having changed the target state
into SRP_TARGET_REMOVED and not if that state was already equal
to SRP_TARGET_REMOVED. That allows to remove the state
SRP_TARGET_DEAD. Add a call to srp_disconnect_target() in
srp_remove_target() - due to previous changes it is now safe to
invoke that last function even if the IB connection has already
been disconnected. This change allows to replace the target
removal code in srp_remove_one() by an (indirect) call to
srp_remove_target(). Rename srp_target_port.work into
srp_target_port.remove_work to reflect its usage.

Signed-off-by: Bart Van Assche <bvanassche-HInyCGIudOg@public.gmane.org>
Cc: David Dillow <dillowda-1Heg1YXhbW8@public.gmane.org>
Cc: Roland Dreier <roland-BHEL68pLQRGGvPXPguhicg@public.gmane.org>
---
 drivers/infiniband/ulp/srp/ib_srp.c |   89 ++++++++++++----------------------
 drivers/infiniband/ulp/srp/ib_srp.h |    5 +-
 2 files changed, 34 insertions(+), 60 deletions(-)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 88557f7..a7f42f3 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -428,6 +428,23 @@ static int srp_send_req(struct srp_target_port *target)
 	return status;
 }
 
+static bool srp_queue_remove_work(struct srp_target_port *target)
+{
+	bool changed = false;
+
+	spin_lock_irq(&target->lock);
+	if (target->state != SRP_TARGET_REMOVED) {
+		target->state = SRP_TARGET_REMOVED;
+		changed = true;
+	}
+	spin_unlock_irq(&target->lock);
+
+	if (changed)
+		queue_work(system_long_wq, &target->remove_work);
+
+	return changed;
+}
+
 static bool srp_change_conn_state(struct srp_target_port *target,
 				  bool connected)
 {
@@ -458,21 +475,6 @@ static void srp_disconnect_target(struct srp_target_port *target)
 	}
 }
 
-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->lock);
-	if (target->state == old) {
-		target->state = new;
-		changed = true;
-	}
-	spin_unlock_irq(&target->lock);
-	return changed;
-}
-
 static void srp_free_req_data(struct srp_target_port *target)
 {
 	struct ib_device *ibdev = target->srp_host->srp_dev->dev;
@@ -508,9 +510,12 @@ static void srp_del_scsi_host_attr(struct Scsi_Host *shost)
 
 static void srp_remove_target(struct srp_target_port *target)
 {
+	WARN_ON(target->state != SRP_TARGET_REMOVED);
+
 	srp_del_scsi_host_attr(target->scsi_host);
 	srp_remove_host(target->scsi_host);
 	scsi_remove_host(target->scsi_host);
+	srp_disconnect_target(target);
 	ib_destroy_cm_id(target->cm_id);
 	srp_free_target_ib(target);
 	srp_free_req_data(target);
@@ -520,10 +525,9 @@ static void srp_remove_target(struct srp_target_port *target)
 static void srp_remove_work(struct work_struct *work)
 {
 	struct srp_target_port *target =
-		container_of(work, struct srp_target_port, work);
+		container_of(work, struct srp_target_port, remove_work);
 
-	if (!srp_change_state(target, SRP_TARGET_DEAD, SRP_TARGET_REMOVED))
-		return;
+	WARN_ON(target->state != SRP_TARGET_REMOVED);
 
 	spin_lock(&target->srp_host->target_lock);
 	list_del(&target->list);
@@ -734,17 +738,8 @@ err:
 	 * 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->lock);
-	if (target->state == SRP_TARGET_LIVE) {
-		target->state = SRP_TARGET_DEAD;
-		INIT_WORK(&target->work, srp_remove_work);
-		queue_work(ib_wq, &target->work);
-	}
-	spin_unlock_irq(&target->lock);
+	srp_queue_remove_work(target);
 
 	return ret;
 }
@@ -1341,8 +1336,7 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd)
 	unsigned long flags;
 	int len;
 
-	if (target->state == SRP_TARGET_DEAD ||
-	    target->state == SRP_TARGET_REMOVED ||
+	if (target->state == SRP_TARGET_REMOVED ||
 	    !target->connected ||
 	    target->qp_in_error) {
 		scmnd->result = DID_BAD_TARGET << 16;
@@ -1694,8 +1688,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
 	struct srp_iu *iu;
 	struct srp_tsk_mgmt *tsk_mgmt;
 
-	if (target->state == SRP_TARGET_DEAD ||
-	    target->state == SRP_TARGET_REMOVED ||
+	if (target->state == SRP_TARGET_REMOVED ||
 	    !target->connected ||
 	    target->qp_in_error)
 		return -1;
@@ -2262,6 +2255,7 @@ static ssize_t srp_create_target(struct device *dev,
 			     sizeof (struct srp_indirect_buf) +
 			     target->cmd_sg_cnt * sizeof (struct srp_direct_buf);
 
+	INIT_WORK(&target->remove_work, srp_remove_work);
 	spin_lock_init(&target->lock);
 	INIT_LIST_HEAD(&target->free_tx);
 	INIT_LIST_HEAD(&target->free_reqs);
@@ -2495,8 +2489,7 @@ static void srp_remove_one(struct ib_device *device)
 {
 	struct srp_device *srp_dev;
 	struct srp_host *host, *tmp_host;
-	LIST_HEAD(target_list);
-	struct srp_target_port *target, *tmp_target;
+	struct srp_target_port *target;
 
 	srp_dev = ib_get_client_data(device, &srp_client);
 
@@ -2509,35 +2502,17 @@ static void srp_remove_one(struct ib_device *device)
 		wait_for_completion(&host->released);
 
 		/*
-		 * Mark all target ports as removed, so we stop queueing
-		 * commands and don't try to reconnect.
+		 * Remove all target ports.
 		 */
 		spin_lock(&host->target_lock);
-		list_for_each_entry(target, &host->target_list, list) {
-			spin_lock_irq(&target->lock);
-			target->state = SRP_TARGET_REMOVED;
-			spin_unlock_irq(&target->lock);
-		}
+		list_for_each_entry(target, &host->target_list, list)
+			srp_queue_remove_work(target);
 		spin_unlock(&host->target_lock);
 
 		/*
-		 * Wait for any reconnection tasks that may have
-		 * started before we marked our target ports as
-		 * removed, and any target port removal tasks.
+		 * Wait for target port removal tasks.
 		 */
-		flush_workqueue(ib_wq);
-
-		list_for_each_entry_safe(target, tmp_target,
-					 &host->target_list, list) {
-			srp_del_scsi_host_attr(target->scsi_host);
-			srp_remove_host(target->scsi_host);
-			scsi_remove_host(target->scsi_host);
-			srp_disconnect_target(target);
-			ib_destroy_cm_id(target->cm_id);
-			srp_free_target_ib(target);
-			srp_free_req_data(target);
-			scsi_host_put(target->scsi_host);
-		}
+		flush_workqueue(system_long_wq);
 
 		kfree(host);
 	}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index ef95fa4..de2d0b3 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -80,8 +80,7 @@ enum {
 
 enum srp_target_state {
 	SRP_TARGET_LIVE,
-	SRP_TARGET_DEAD,
-	SRP_TARGET_REMOVED
+	SRP_TARGET_REMOVED,
 };
 
 enum srp_iu_type {
@@ -175,7 +174,7 @@ struct srp_target_port {
 	struct srp_iu	       *rx_ring[SRP_RQ_SIZE];
 	struct srp_request	req_ring[SRP_CMD_SQ_SIZE];
 
-	struct work_struct	work;
+	struct work_struct	remove_work;
 
 	struct list_head	list;
 	struct completion	done;
-- 
1.7.7

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2012-08-09 15:51 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-09 15:41 [PATCH 00/20, v4] Make ib_srp better suited for H.A. purposes Bart Van Assche
     [not found] ` <5023DA39.7020000-HInyCGIudOg@public.gmane.org>
2012-08-09 15:43   ` [PATCH 01/20] ib_srp: Fix a race condition Bart Van Assche
     [not found]     ` <5023DAA1.1040507-HInyCGIudOg@public.gmane.org>
2012-08-14  3:19       ` David Dillow
     [not found]         ` <1344914386.31833.45.camel-1q1vX8mYZiGLUyTwlgNVppKKF0rrzTr+@public.gmane.org>
2012-08-14 13:21           ` Bart Van Assche
2012-08-14 13:18       ` [PATCH 01/20 v4b] " Bart Van Assche
     [not found]         ` <502A503D.5030604-HInyCGIudOg@public.gmane.org>
2012-08-15  0:03           ` David Dillow
2012-08-09 15:44   ` [PATCH 02/20] ib_srp: Enlarge block layer timeout Bart Van Assche
2012-08-09 15:45   ` [PATCH 03/20] ib_srp: Move QP state check into srp_send_tsk_mgmt() Bart Van Assche
2012-08-09 15:47   ` [PATCH 04/20] ib_srp: Stop queueing if QP in error Bart Van Assche
2012-08-09 15:48   ` [PATCH 05/20] ib_srp: Eliminate state SRP_TARGET_CONNECTING Bart Van Assche
2012-08-09 15:48   ` [PATCH 06/20] ib_srp: Suppress superfluous error messages Bart Van Assche
2012-08-09 15:49   ` [PATCH 07/20] ib_srp: Avoid that SCSI error handling triggers a crash Bart Van Assche
2012-08-09 15:50   ` [PATCH 08/20] ib_srp: Introduce the helper function, srp_remove_target() Bart Van Assche
2012-08-09 15:51   ` Bart Van Assche [this message]
2012-08-09 15:52   ` [PATCH 10/20] ib_srp: Keep processing commands during scsi_remove_host() Bart Van Assche
2012-08-09 15:53   ` [PATCH 11/20] ib_srp: Make srp_disconnect_target() wait for IB completions Bart Van Assche
     [not found]     ` <5023DCFF.4020709-HInyCGIudOg@public.gmane.org>
2012-08-23 15:59       ` Sebastian Riemer
     [not found]         ` <5036536B.1000003-EIkl63zCoXaH+58JC4qpiA@public.gmane.org>
2012-08-23 16:43           ` Bart Van Assche
     [not found]             ` <50365DC3.1050807-HInyCGIudOg@public.gmane.org>
2012-08-24 10:42               ` Dongsu Park
2012-08-09 15:54   ` [PATCH 12/20] ib_srp: Document sysfs attributes Bart Van Assche
2012-08-09 15:56   ` [PATCH 13/20] srp_transport: Fix atttribute registration Bart Van Assche
2012-08-09 15:58   ` [PATCH 15/20] srp_transport: Document sysfs attributes Bart Van Assche
2012-08-09 15:59   ` [PATCH 16/20] ib_srp: Allow SRP disconnect through sysfs Bart Van Assche
2012-08-09 16:00   ` [PATCH 17/20] ib_srp: Introduce a temporary variable in srp_remove_target() Bart Van Assche
2012-08-09 16:01   ` [PATCH 18/20] ib_srp: Maintain a single connection per I_T nexus Bart Van Assche
2012-08-09 16:02   ` [PATCH 19/20] srp_transport: Add transport layer error handling Bart Van Assche
2012-08-09 16:04   ` [PATCH 20/20] ib_srp: Add dev_loss_tmo support Bart Van Assche
2012-08-27 18:37   ` [PATCH 00/20, v4] Make ib_srp better suited for H.A. purposes Dongsu Park
2012-08-28 10:04     ` Bart Van Assche
2012-08-28 12:25       ` Dongsu Park
2012-08-28 12:58         ` Bart Van Assche
2012-09-25 15:05   ` Bart Van Assche
2012-09-27  0:31     ` David Dillow
     [not found]       ` <1348705896.26028.3.camel-1q1vX8mYZiGLUyTwlgNVppKKF0rrzTr+@public.gmane.org>
2012-11-23 15:07         ` Bart Van Assche
     [not found]           ` <50AF9146.5000405-HInyCGIudOg@public.gmane.org>
2012-11-26  4:47             ` David Dillow
2012-08-09 15:57 ` [PATCH 14/20] srp_transport: Simplify attribute initialization code Bart Van Assche
2012-08-09 16:18 ` [PATCH 00/20, v4] Make ib_srp better suited for H.A. purposes Bart Van Assche
     [not found]   ` <5023E2E3.4030602-HInyCGIudOg@public.gmane.org>
2012-08-11  8:29     ` Joseph Glanville

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5023DC94.5050205@acm.org \
    --to=bvanassche-hinycgiudog@public.gmane.org \
    --cc=dillowda-1Heg1YXhbW8@public.gmane.org \
    --cc=linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=roland-BHEL68pLQRGGvPXPguhicg@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).