diff options
author | np <np@FreeBSD.org> | 2013-01-26 03:23:28 +0000 |
---|---|---|
committer | np <np@FreeBSD.org> | 2013-01-26 03:23:28 +0000 |
commit | f20c120ed1307b652267aa8015ec6e7486d72297 (patch) | |
tree | dc51e8e1410fb73318b07b33850ab2a29af81fff /sys/dev | |
parent | 7658f66486b3e23df2299b54d18e73d1873c73cd (diff) | |
download | FreeBSD-src-f20c120ed1307b652267aa8015ec6e7486d72297.zip FreeBSD-src-f20c120ed1307b652267aa8015ec6e7486d72297.tar.gz |
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
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/cxgbe/tom/t4_listen.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c index fca9fc7..b80702d 100644 --- a/sys/dev/cxgbe/tom/t4_listen.c +++ b/sys/dev/cxgbe/tom/t4_listen.c @@ -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, const struct rss_header *rss, 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, const struct rss_header *rss, 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, const struct rss_header *rss, * 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, |