From: Robert Love <robert.w.love@intel.com>
To: James.Bottomley@HansenPartnership.com, linux-scsi@vger.kernel.org
Cc: Joe Eykholt <jeykholt@cisco.com>, Robert Love <robert.w.love@intel.com>
Subject: [PATCH 12/22] libfc: fc_rport_logoff should not drop the lock
Date: Wed, 29 Jul 2009 17:04:49 -0700 [thread overview]
Message-ID: <20090730000449.24658.83683.stgit@localhost.localdomain> (raw)
In-Reply-To: <20090730000345.24658.24830.stgit@localhost.localdomain>
From: Joe Eykholt <jeykholt@cisco.com>
fc_rport_logoff drops the rport lock in order to cancel work
that may be pending. This is undesirable as the state can
completely change, and the caller may not expect that the
lock could've been dropped.
If there is work pending, it will acquire the rdata mutex and
so we're protected and can change the event from READY to DELETE.
Queue the work only if there is no event already pending.
There were a couple other cases where the state was set to
DELETE and work queued, even though the state may have already
been DELETE. Fix these using a common function fc_rport_enter_delete().
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
---
drivers/scsi/libfc/fc_rport.c | 60 ++++++++++++++++++++++++++---------------
1 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index bf7364f..a86df0b 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -230,6 +230,7 @@ static void fc_rport_work(struct work_struct *work)
ids.port_name = rport->port_name;
ids.node_name = rport->node_name;
+ rdata->event = RPORT_EV_NONE;
mutex_unlock(&rdata->rp_mutex);
new_rport = fc_remote_port_add(lport->host, 0, &ids);
@@ -311,6 +312,37 @@ int fc_rport_login(struct fc_rport *rport)
}
/**
+ * fc_rport_enter_delete() - schedule a remote port to be deleted.
+ * @rport: Fibre Channel remote port
+ * @event: event to report as the reason for deletion
+ *
+ * Locking Note: Called with the rport lock held.
+ *
+ * Allow state change into DELETE only once.
+ *
+ * Call queue_work only if there's no event already pending.
+ * Set the new event so that the old pending event will not occur.
+ * Since we have the mutex, even if fc_rport_work() is already started,
+ * it'll see the new event.
+ */
+static void fc_rport_enter_delete(struct fc_rport *rport,
+ enum fc_rport_event event)
+{
+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
+
+ if (rdata->rp_state == RPORT_ST_DELETE)
+ return;
+
+ FC_RPORT_DBG(rport, "Delete port\n");
+
+ fc_rport_state_enter(rport, RPORT_ST_DELETE);
+
+ if (rdata->event == RPORT_EV_NONE)
+ queue_work(rport_event_queue, &rdata->event_work);
+ rdata->event = event;
+}
+
+/**
* fc_rport_logoff() - Logoff and remove an rport
* @rport: Fibre Channel remote port to be removed
*
@@ -338,17 +370,7 @@ int fc_rport_logoff(struct fc_rport *rport)
* Change the state to Delete so that we discard
* the response.
*/
- fc_rport_state_enter(rport, RPORT_ST_DELETE);
-
- mutex_unlock(&rdata->rp_mutex);
-
- cancel_delayed_work_sync(&rdata->retry_work);
-
- mutex_lock(&rdata->rp_mutex);
-
- rdata->event = RPORT_EV_STOP;
- queue_work(rport_event_queue, &rdata->event_work);
-
+ fc_rport_enter_delete(rport, RPORT_EV_STOP);
mutex_unlock(&rdata->rp_mutex);
out:
@@ -370,8 +392,9 @@ static void fc_rport_enter_ready(struct fc_rport *rport)
FC_RPORT_DBG(rport, "Port is Ready\n");
+ if (rdata->event == RPORT_EV_NONE)
+ queue_work(rport_event_queue, &rdata->event_work);
rdata->event = RPORT_EV_CREATED;
- queue_work(rport_event_queue, &rdata->event_work);
}
/**
@@ -432,10 +455,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
case RPORT_ST_PLOGI:
case RPORT_ST_PRLI:
case RPORT_ST_LOGO:
- rdata->event = RPORT_EV_FAILED;
- fc_rport_state_enter(rport, RPORT_ST_DELETE);
- queue_work(rport_event_queue,
- &rdata->event_work);
+ fc_rport_enter_delete(rport, RPORT_EV_FAILED);
break;
case RPORT_ST_RTV:
fc_rport_enter_ready(rport);
@@ -651,9 +671,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
} else {
FC_RPORT_DBG(rport, "Bad ELS response for PRLI command\n");
- rdata->event = RPORT_EV_FAILED;
- fc_rport_state_enter(rport, RPORT_ST_DELETE);
- queue_work(rport_event_queue, &rdata->event_work);
+ fc_rport_enter_delete(rport, RPORT_EV_FAILED);
}
out:
@@ -702,9 +720,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
fc_rport_enter_rtv(rport);
} else {
FC_RPORT_DBG(rport, "Bad ELS response for LOGO command\n");
- rdata->event = RPORT_EV_LOGO;
- fc_rport_state_enter(rport, RPORT_ST_DELETE);
- queue_work(rport_event_queue, &rdata->event_work);
+ fc_rport_enter_delete(rport, RPORT_EV_LOGO);
}
out:
next prev parent reply other threads:[~2009-07-30 0:05 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-07-30 0:03 [PATCH 00/22] Open-FCoE Features for 2.6.32 Robert Love
2009-07-30 0:03 ` [PATCH 01/22] fcoe: Fix validation of mac address when checking for spma support Robert Love
2009-07-30 0:03 ` [PATCH 02/22] libfcoe: Set fip_flags according to fcf and lport's capability of SPMA support Robert Love
2009-07-30 0:04 ` [PATCH 03/22] fcoe: Call dev_ethtool_get_settings() in fcoe_link_ok Robert Love
2009-07-30 0:04 ` [PATCH 04/22] libfc: remove extra semicolons from debug macros Robert Love
2009-07-30 0:04 ` [PATCH 05/22] libfc: change debug messages to give host number Robert Love
2009-07-30 0:04 ` [PATCH 06/22] fcoe: stop delivery of received frames before doing lport_destroy() Robert Love
2009-07-30 0:04 ` [PATCH 07/22] libfc: rename lport NONE state to DISABLED Robert Love
2009-07-30 0:04 ` [PATCH 08/22] libfc: stop login after fabric logoff Robert Love
2009-07-30 0:04 ` [PATCH 09/22] libfc: in fc_lport_destroy, flush rports after turning off link Robert Love
2009-07-30 0:04 ` [PATCH 10/22] libfc: fix WARNING from fc_seq_start_next on closed exchanges Robert Love
2009-07-30 0:04 ` [PATCH 11/22] libfc: rename rport state "NONE" to "DELETE" Robert Love
2009-07-30 0:04 ` Robert Love [this message]
2009-07-30 0:04 ` [PATCH 13/22] libfc: fix: cancel rport retry timer Robert Love
2009-07-30 0:05 ` [PATCH 14/22] fcoe, libfc: adds exchange manager(EM) anchor list per lport and related APIs Robert Love
2009-07-30 0:05 ` [PATCH 15/22] libfc: Remove the FC_EM_DBG macro Robert Love
2009-07-30 0:05 ` [PATCH 16/22] fcoe, fnic, libfc: modifies current code paths to use EM anchor list Robert Love
2009-07-30 0:05 ` [PATCH 17/22] fcoe: modifies fcoe_hostlist_lock uses as prep work to add shared offload EM Robert Love
2009-07-30 0:05 ` [PATCH 18/22] fcoe, libfc: adds offload EM per eth device with only single xid range per EM Robert Love
2009-07-30 0:05 ` [PATCH 19/22] fcoe: Remove ifdef for NETIF_F_FCOE_CRC and NETIF_F_FSO Robert Love
2009-07-30 0:05 ` [PATCH 20/22] libfc: Remove FC_FRAME_SG_LEN in fc_fcp_send_data Robert Love
2009-07-30 0:05 ` [PATCH 21/22] libfc: Remove page flags check for sglist Robert Love
2009-07-30 0:05 ` [PATCH 22/22] fcoe: removes phys_dev and renames real_dev to netdev Robert Love
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=20090730000449.24658.83683.stgit@localhost.localdomain \
--to=robert.w.love@intel.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=jeykholt@cisco.com \
--cc=linux-scsi@vger.kernel.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).