The fc_exch_done() requires calling code path to have extra exch
hold and then last exch release in that path will free the exchange
memory, mostly exch call paths already has this but the fc_exch_recv_req()
path. So added exch release() to fc_exch_recv_req() with making sure
extra exch hold in this code path, this will fix exch ref in code path
of handling exch originated from other side of initiator.

Also fixed fc_seq_lookup_recip() called from fc_exch_recv_req() to
have extra exch hold for caller and releasing exchange in error cases.

This patch has merged changes from Mike Christie sent in attachment
to this email http://www.open-fcoe.org/pipermail/devel/2008-August/000618.html.

Signed-off-by: Vasu Dev <[EMAIL PROTECTED]>
---

 drivers/scsi/libfc/fc_exch.c |   23 +++++++++++++++--------
 1 files changed, 15 insertions(+), 8 deletions(-)


diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index a1d364a..43d824a 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -665,12 +665,14 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr 
*mp, struct fc_frame *fp)
 
 /*
  * Find a sequence for receive where the other end is originating the sequence.
+ * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold
+ * on the ep that should be released by the caller.
  */
 static enum fc_pf_rjt_reason
 fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp)
 {
        struct fc_frame_header *fh = fc_frame_header_get(fp);
-       struct fc_exch *ep = NULL;
+       struct fc_exch *ep = NULL, *new_ep = NULL;
        struct fc_seq *sp = NULL;
        enum fc_pf_rjt_reason reject = FC_RJT_NONE;
        u32 f_ctl;
@@ -693,9 +695,8 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame 
*fp)
                if (ep->rxid == FC_XID_UNKNOWN)
                        ep->rxid = ntohs(fh->fh_rx_id);
                else if (ep->rxid != ntohs(fh->fh_rx_id)) {
-                       fc_exch_release(ep);
                        reject = FC_RJT_OX_ID;
-                       goto out;
+                       goto rel;
                }
        } else {
                xid = ntohs(fh->fh_rx_id);      /* we are the responder */
@@ -717,16 +718,16 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct 
fc_frame *fp)
                ep = fc_exch_find(mp, xid);
                if ((f_ctl & FC_FC_FIRST_SEQ) && fc_sof_is_init(fr_sof(fp))) {
                        if (ep) {
-                               fc_exch_release(ep);
                                atomic_inc(&mp->stats.xid_busy);
                                reject = FC_RJT_RX_ID;
-                               goto out;
+                               goto rel;
                        }
-                       ep = fc_exch_resp(mp, fp);
+                       new_ep = ep = fc_exch_resp(mp, fp);
                        if (!ep) {
                                reject = FC_RJT_EXCH_EST;       /* XXX */
                                goto out;
                        }
+                       fc_exch_hold(ep);       /* Additional hold for caller */
                        xid = ep->xid;  /* get our XID */
                } else if (!ep) {
                        atomic_inc(&mp->stats.xid_not_found);
@@ -743,7 +744,7 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame 
*fp)
                sp = fc_seq_start_next(&ep->seq);
                if (!sp) {
                        reject = FC_RJT_SEQ_XS; /* exchange shortage */
-                       goto out;
+                       goto rel;
                }
                sp->id = fh->fh_seq_id;
                sp->ssb_stat |= SSB_ST_RESP;
@@ -752,7 +753,7 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame 
*fp)
                if (sp->id != fh->fh_seq_id) {
                        atomic_inc(&mp->stats.seq_not_found);
                        reject = FC_RJT_SEQ_ID; /* sequence/exch should exist */
-                       goto out;
+                       goto rel;
                }
        }
        WARN_ON(ep != fc_seq_exch(sp));
@@ -763,6 +764,11 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct 
fc_frame *fp)
        fr_seq(fp) = sp;
 out:
        return reject;
+rel:
+       fc_exch_release(ep);
+       if (new_ep)
+               fc_exch_release(new_ep);
+       return reject;
 }
 
 /*
@@ -1162,6 +1168,7 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct 
fc_exch_mgr *mp,
                        ep->resp(sp, fp, ep->resp_arg);
                else
                        lp->tt.lport_recv(lp, sp, fp);
+               fc_exch_release(ep);    /* release from lookup */
        } else {
                if (fc_exch_debug)
                        FC_DBG("exch/seq lookup failed: reject %x\n", reject);

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

Reply via email to