Author: np
Date: Sat Jan 26 03:23:28 2013
New Revision: 245937
URL: http://svnweb.freebsd.org/changeset/base/245937

Log:
  Install an extra hold on the newly allocated synq entry so that it
  cannot be freed while do_pass_accept_req is running.  This closes a race
  where do_pass_establish on another CPU (the driver chose a different
  queue for the new tid) expands the synq entry into a full PCB and then
  releases the only hold on it, all while do_pass_accept_req is still
  running.
  
  MFC after:    3 days

Modified:
  head/sys/dev/cxgbe/tom/t4_listen.c

Modified: head/sys/dev/cxgbe/tom/t4_listen.c
==============================================================================
--- head/sys/dev/cxgbe/tom/t4_listen.c  Sat Jan 26 03:10:28 2013        
(r245936)
+++ head/sys/dev/cxgbe/tom/t4_listen.c  Sat Jan 26 03:23:28 2013        
(r245937)
@@ -954,7 +954,7 @@ mbuf_to_synqe(struct mbuf *m)
                        return (NULL);
                synqe->flags = TPF_SYNQE | TPF_SYNQE_NEEDFREE;
        } else {
-               synqe = (void *)(m->m_data + m->m_len + tspace - 
sizeof(*synqe));
+               synqe = (void *)(m->m_data + m->m_len + tspace - len);
                synqe->flags = TPF_SYNQE;
        }
 
@@ -1335,7 +1335,7 @@ do_pass_accept_req(struct sge_iq *iq, co
        synqe->lctx = lctx;
        synqe->syn = m;
        m = NULL;
-       refcount_init(&synqe->refcnt, 0);
+       refcount_init(&synqe->refcnt, 1);       /* 1 means extra hold */
        synqe->l2e_idx = e->idx;
        synqe->rcv_bufsize = rx_credits;
        atomic_store_rel_ptr(&synqe->wr, (uintptr_t)wr);
@@ -1381,6 +1381,7 @@ do_pass_accept_req(struct sge_iq *iq, co
                if (inp)
                        INP_WUNLOCK(inp);
 
+               release_synqe(synqe);   /* extra hold */
                REJECT_PASS_ACCEPT();
        }
 
@@ -1395,15 +1396,19 @@ do_pass_accept_req(struct sge_iq *iq, co
                 * this tid because there was no L2T entry for the tid at that
                 * time.  Abort it now.  The reply to the abort will clean up.
                 */
-               CTR5(KTR_CXGBE, "%s: stid %u, tid %u, lctx %p, synqe %p, ABORT",
-                   __func__, stid, tid, lctx, synqe);
-               send_reset_synqe(tod, synqe);
+               CTR6(KTR_CXGBE,
+                   "%s: stid %u, tid %u, lctx %p, synqe %p (0x%x), ABORT",
+                   __func__, stid, tid, lctx, synqe, synqe->flags);
+               if (!(synqe->flags & TPF_SYNQE_EXPANDED))
+                       send_reset_synqe(tod, synqe);
                INP_WUNLOCK(inp);
 
+               release_synqe(synqe);   /* extra hold */
                return (__LINE__);
        }
        INP_WUNLOCK(inp);
 
+       release_synqe(synqe);   /* extra hold */
        return (0);
 reject:
        CTR4(KTR_CXGBE, "%s: stid %u, tid %u, REJECT (%d)", __func__, stid, tid,
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to