Files
bpfire/src/patches/suse-2.6.27.25/patches.drivers/libfc-improve-fc_lport-c-locki.diff
2009-08-05 10:39:24 +02:00

115 lines
5.1 KiB
Diff

From: Robert Love <robert.w.love@intel.com>
Subject: [FcOE] Improve fc_lport.c locking comment block
References: bnc #459142
Signed-off-by: Robert Love <robert.w.love@intel.com>
Acked-by: Bernhard Walle <bwalle@suse.de>
---
drivers/scsi/libfc/fc_lport.c | 76 ++++++++++++++++++++++++------------------
1 file changed, 45 insertions(+), 31 deletions(-)
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -18,34 +18,51 @@
*/
/*
- * General locking notes:
+ * PORT LOCKING NOTES
*
- * The lport and rport blocks both have mutexes that are used to protect
- * the port objects states. The main motivation for this protection is that
- * we don't want to be preparing a request/response in one context while
- * another thread "resets" the port in question. For example, if the lport
- * block is sending a SCR request to the directory server we don't want
- * the lport to be reset before we fill out the frame header's port_id. The
- * problem is that a reset would cause the lport's port_id to reset to 0.
- * If we don't protect the lport we'd spew incorrect frames.
- *
- * At the time of this writing there are two primary mutexes, one for the
- * lport and one for the rport. Since the lport uses the rport and makes
- * calls into that block the rport should never make calls that would cause
- * the lport's mutex to be locked. In other words, the lport's mutex is
- * considered the outer lock and the rport's lock is considered the inner
- * lock. The bottom line is that you can hold a lport's mutex and then
- * hold the rport's mutex, but not the other way around.
- *
- * The only complication to this rule is the callbacks from the rport to
- * the lport's rport_callback function. When rports become READY they make
- * a callback to the lport so that it can track them. In the case of the
- * directory server that callback might cause the lport to change its
- * state, implying that the lport mutex would need to be held. This problem
- * was solved by serializing the rport notifications to the lport and the
- * callback is made without holding the rport's lock.
+ * These comments only apply to the 'port code' which consists of the lport,
+ * disc and rport blocks.
*
- * lport locking notes:
+ * MOTIVATION
+ *
+ * The lport, disc and rport blocks all have mutexes that are used to protect
+ * those objects. The main motivation for these locks is to prevent from
+ * having an lport reset just before we send a frame. In that scenario the
+ * lport's FID would get set to zero and then we'd send a frame with an
+ * invalid SID. We also need to ensure that states don't change unexpectedly
+ * while processing another state.
+ *
+ * HEIRARCHY
+ *
+ * The following heirarchy defines the locking rules. A greater lock
+ * may be held before acquiring a lesser lock, but a lesser lock should never
+ * be held while attempting to acquire a greater lock. Here is the heirarchy-
+ *
+ * lport > disc, lport > rport, disc > rport
+ *
+ * CALLBACKS
+ *
+ * The callbacks cause complications with this scheme. There is a callback
+ * from the rport (to either lport or disc) and a callback from disc
+ * (to the lport).
+ *
+ * As rports exit the rport state machine a callback is made to the owner of
+ * the rport to notify success or failure. Since the callback is likely to
+ * cause the lport or disc to grab its lock we cannot hold the rport lock
+ * while making the callback. To ensure that the rport is not free'd while
+ * processing the callback the rport callbacks are serialized through a
+ * single-threaded workqueue. An rport would never be free'd while in a
+ * callback handler becuase no other rport work in this queue can be executed
+ * at the same time.
+ *
+ * When discovery succeeds or fails a callback is made to the lport as
+ * notification. Currently, succesful discovery causes the lport to take no
+ * action. A failure will cause the lport to reset. There is likely a circular
+ * locking problem with this implementation.
+ */
+
+/*
+ * LPORT LOCKING
*
* The critical sections protected by the lport's mutex are quite broad and
* may be improved upon in the future. The lport code and its locking doesn't
@@ -54,9 +71,9 @@
*
* The strategy is to lock whenever processing a request or response. Note
* that every _enter_* function corresponds to a state change. They generally
- * change the lports state and then sends a request out on the wire. We lock
+ * change the lports state and then send a request out on the wire. We lock
* before calling any of these functions to protect that state change. This
- * means that the entry points into the lport block to manage the locks while
+ * means that the entry points into the lport block manage the locks while
* the state machine can transition between states (i.e. _enter_* functions)
* while always staying protected.
*
@@ -68,9 +85,6 @@
* Retries also have to consider the locking. The retries occur from a work
* context and the work function will lock the lport and then retry the state
* (i.e. _enter_* function).
- *
- * The implication to all of this is that each lport can only process one
- * state at a time.
*/
#include <linux/timer.h>