From: Mike Christie <[EMAIL PROTECTED]>

If fc_exch_recv is completing the ep while fc_fcp.c is calling
fc_seq_exch_abort then we could hit the WARN_ON for the completion
check. Instead of warning we just want to fail the fc_seq_exch_abort
call.

This also adds a check in fc_seq_exch_abort for if we are
sending an abort. There is no point in sending another one.

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

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 377d165..66b1c0d 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -138,6 +138,7 @@ static void fc_seq_ls_rjt(struct fc_seq *, enum 
fc_els_rjt_reason,
                  enum fc_els_rjt_explan);
 static void fc_exch_els_rec(struct fc_seq *, struct fc_frame *);
 static void fc_exch_els_rrq(struct fc_seq *, struct fc_frame *);
+static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp);
 
 /*
  * Internal implementation notes.
@@ -352,35 +353,43 @@ int fc_seq_exch_abort(const struct fc_seq *req_sp)
 
        ep = fc_seq_exch(req_sp);
 
+       spin_lock_bh(&ep->ex_lock);
+       if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL)) {
+               spin_unlock_bh(&ep->ex_lock);
+               return -ENXIO;
+       }
+
        /*
         * Send the abort on a new sequence if possible.
         */
-       error = -ENOMEM;
-       sp = fc_seq_start_next(&ep->seq);
-       if (sp) {
-               spin_lock_bh(&ep->ex_lock);
-               sp->f_ctl |= FC_FC_SEQ_INIT;
-               ep->esb_stat |= ESB_ST_SEQ_INIT | ESB_ST_ABNORMAL;
-               fc_exch_timer_set_locked(ep, ep->r_a_tov);
+       sp = fc_seq_start_next_locked(&ep->seq);
+       if (!sp) {
                spin_unlock_bh(&ep->ex_lock);
+               return -ENOMEM;
+       }
 
-               /*
-                * If not logged into the fabric, don't send ABTS but leave
-                * sequence active until next timeout.
-                */
-               if (!ep->sid)
-                       return 0;
+       sp->f_ctl |= FC_FC_SEQ_INIT;
+       ep->esb_stat |= ESB_ST_SEQ_INIT | ESB_ST_ABNORMAL;
+       fc_exch_timer_set_locked(ep, ep->r_a_tov);
+       spin_unlock_bh(&ep->ex_lock);
+
+       /*
+        * If not logged into the fabric, don't send ABTS but leave
+        * sequence active until next timeout.
+        */
+       if (!ep->sid)
+               return 0;
+
+       /*
+        * Send an abort for the sequence that timed out.
+        */
+       fp = fc_frame_alloc(ep->lp, 0);
+       if (fp) {
+               fc_frame_setup(fp, FC_RCTL_BA_ABTS, FC_TYPE_BLS);
+               error = fc_seq_send(ep->lp, sp, fp, FC_FC_END_SEQ);
+       } else
+               error = -ENOBUFS;
 
-               /*
-                * Send an abort for the sequence that timed out.
-                */
-               fp = fc_frame_alloc(ep->lp, 0);
-               if (fp) {
-                       fc_frame_setup(fp, FC_RCTL_BA_ABTS, FC_TYPE_BLS);
-                       error = fc_seq_send(ep->lp, sp, fp, FC_FC_END_SEQ);
-               } else
-                       error = -ENOBUFS;
-       }
        return error;
 }
 EXPORT_SYMBOL(fc_seq_exch_abort);
@@ -717,11 +726,11 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct 
fc_frame *fp)
         */
        if (fc_sof_is_init(fr_sof(fp))) {
                sp = fc_seq_start_next(&ep->seq);
-               sp->id = fh->fh_seq_id;
                if (!sp) {
                        reject = FC_RJT_SEQ_XS; /* exchange shortage */
                        goto out;
                }
+               sp->id = fh->fh_seq_id;
                sp->ssb_stat |= SSB_ST_RESP;
        } else {
                sp = &ep->seq;
@@ -793,6 +802,16 @@ static void fc_exch_set_addr(struct fc_exch *ep,
        }
 }
 
+static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp)
+{
+       struct fc_exch *ep = fc_seq_exch(sp);
+
+       sp = fc_seq_alloc(ep, ep->seq_id++);
+       if (fc_exch_debug)
+               FC_DBG("exch %4x f_ctl %6x seq %2x f_ctl %6x\n",
+                      ep->xid, ep->f_ctl, sp->id, sp->f_ctl);
+       return sp;
+}
 /*
  * Allocate a new sequence on the same exchange as the supplied sequence.
  * This will never return NULL.
@@ -803,13 +822,9 @@ struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
 
        spin_lock_bh(&ep->ex_lock);
        WARN_ON((ep->esb_stat & ESB_ST_COMPLETE) != 0);
-
-       sp = fc_seq_alloc(ep, ep->seq_id++);
-
-       if (fc_exch_debug)
-               FC_DBG("exch %4x f_ctl %6x seq %2x f_ctl %6x\n",
-                      ep->xid, ep->f_ctl, sp->id, sp->f_ctl);
+       sp = fc_seq_start_next_locked(sp);
        spin_unlock_bh(&ep->ex_lock);
+
        return sp;
 }
 EXPORT_SYMBOL(fc_seq_start_next);
-- 
1.5.4.1

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

Reply via email to