From: Mike Christie <[EMAIL PROTECTED]>

I guess the list is not allowing attachments, so here is a resend
inline.

If an abort thread and a normal thread decided to call
exch_done then we end up doing a dec on the refcount too many times.

This patch checks for ESB_ST_COMPLETE before completing it.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libfc/fc_exch.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 7d7a3ef..a4d3901 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -390,7 +390,7 @@ static void fc_exch_timeout(unsigned long ep_arg)
        spin_lock_bh(&ep->ex_lock);
        e_stat = ep->esb_stat;
        if (e_stat & ESB_ST_COMPLETE) {
-               ep->esb_stat = e_stat & ~ESB_ST_REC_QUAL;
+               ep->esb_stat = e_stat & ~(ESB_ST_REC_QUAL | ESB_ST_COMPLETE);
                spin_unlock_bh(&ep->ex_lock);
                if (e_stat & ESB_ST_REC_QUAL)
                        fc_exch_rrq(ep);
@@ -559,8 +559,17 @@ static int fc_exch_done_locked(struct fc_exch *ep)
 {
        int rc = 1;
 
-       ep->esb_stat |= ESB_ST_COMPLETE;
+       /*
+        * We must check for completion in case there are two threads
+        * tyring to complete this. But the rrq code will reuse the
+        * ep, and in that case we only clear the resp and set it as
+        * complete, so it can be reused by the timer to send the rrq.
+        */
        ep->resp = NULL;
+       if (ep->esb_stat & ESB_ST_COMPLETE)
+               return rc;
+       ep->esb_stat |= ESB_ST_COMPLETE;
+
        if (!(ep->esb_stat & ESB_ST_REC_QUAL)) {
                if (del_timer(&ep->ex_timer))
                        atomic_dec(&ep->ex_refcnt); /* drop hold for timer */
-- 
1.5.4.1

_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to