PERFORCE change 130462 for review
Kip Macy
kmacy at FreeBSD.org
Fri Dec 7 21:23:58 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=130462
Change 130462 by kmacy at kmacy:storage:toestack on 2007/12/08 05:23:03
various locking fixes
handle abort in SYN_RCVD state
Affected files ...
.. //depot/projects/toestack/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c#29 edit
Differences ...
==== //depot/projects/toestack/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c#29 (text+ko) ====
@@ -488,9 +488,11 @@
toep->tp_copied_seq += read;
toep->tp_enqueued_bytes -= read;
credits = toep->tp_copied_seq - toep->tp_rcv_wup;
- DPRINTF("copied_seq=%u rcv_wup=%u credits=%u\n",
- toep->tp_copied_seq, toep->tp_rcv_wup, credits);
- SOCKBUF_UNLOCK(&so->so_rcv);
+ SOCKBUF_UNLOCK(&so->so_rcv);
+
+ if (credits > so->so_rcv.sb_mbmax)
+ printf("copied_seq=%u rcv_wup=%u credits=%u\n",
+ toep->tp_copied_seq, toep->tp_rcv_wup, credits);
/*
* XXX this won't accurately reflect credit return - we need
* to look at the difference between the amount that has been
@@ -534,7 +536,7 @@
{
struct socket *so;
- printf("cxgb_toe_disconnect\n");
+ DPRINTF("cxgb_toe_disconnect\n");
so = tp->t_inpcb->inp_socket;
close_conn(so);
@@ -879,7 +881,7 @@
__skb_queue_purge(&tp->out_of_order_queue);
#endif
} else { // we have TID
- cxgb_remove_tid(cdev, (void *)so, tid);
+ cxgb_remove_tid(cdev, toep, tid);
toepcb_release(toep);
}
#if 0
@@ -975,7 +977,10 @@
toep->tp_delack_mode = 0;
toep->tp_mtu_idx = select_mss(td, tp, dst->rt_ifp->if_mtu);
-
+ /*
+ * XXX broken
+ *
+ */
tp->rcv_wnd = select_rcv_wnd(so);
toep->tp_ulp_mode = TOM_TUNABLE(dev, ddp) && !(so->so_options & SO_NO_DDP) &&
tp->rcv_wnd >= MIN_DDP_RCV_WIN ? ULP_MODE_TCPDDP : 0;
@@ -1161,6 +1166,7 @@
* check SOCK_DEAD or sk->sk_sock. Or maybe generate the error here but don't
* free the atid. Hmm.
*/
+#ifdef notyet
static void
act_open_req_arp_failure(struct t3cdev *dev, struct mbuf *m)
{
@@ -1178,7 +1184,7 @@
}
INP_UNLOCK(inp);
}
-
+#endif
/*
* Send an active open request.
*/
@@ -1460,10 +1466,17 @@
SOCKBUF_LOCK(&so->so_rcv);
if (sb_notify(&so->so_rcv))
DPRINTF("rx_data so=%p flags=0x%x len=%d\n", so, so->so_rcv.sb_flags, m->m_pkthdr.len);
+
+ sbappend_locked(&so->so_rcv, m);
+ KASSERT(so->so_rcv.sb_cc < so->so_rcv.sb_mbmax,
+
+ ("so=%p, data contents exceed mbmax, sb_cc=%d sb_mbmax=%d",
+ so, so->so_rcv.sb_cc, so->so_rcv.sb_mbmax));
- sbappendstream_locked(&so->so_rcv, m);
INP_UNLOCK(tp->t_inpcb);
-
+ DPRINTF("sb_cc=%d sb_mbcnt=%d\n",
+ so->so_rcv.sb_cc, so->so_rcv.sb_mbcnt);
+
if (__predict_true((so->so_state & SS_NOFDREF) == 0))
sorwakeup_locked(so);
else
@@ -1725,7 +1738,7 @@
struct toepcb *toep = tp->t_toe;
int keep = 0, dead = (so->so_state & SS_NOFDREF);
- printf("do_peer_fin state=%d dead=%d\n", tp->t_state, !!dead);
+ DPRINTF("do_peer_fin state=%d dead=%d\n", tp->t_state, !!dead);
#ifdef T3_TRACE
T3_TRACE0(TIDTB(sk),"do_peer_fin:");
@@ -1772,7 +1785,7 @@
*/
t3_release_offload_resources(so);
if (toep->tp_flags & TP_ABORT_RPL_PENDING) {
- tcp_close(tp);
+ tp = tcp_close(tp);
} else
enter_timewait(so);
break;
@@ -1782,10 +1795,11 @@
TOE_DEV(so)->name, toep->tp_tid, tp->t_state);
}
INP_INFO_WUNLOCK(&tcbinfo);
- INP_UNLOCK(tp->t_inpcb);
+ if (tp)
+ INP_UNLOCK(tp->t_inpcb);
if (!dead) {
- printf("waking up waiters on %p rcv_notify=%d flags=0x%x\n", so, sb_notify(&so->so_rcv), so->so_rcv.sb_flags);
+ DPRINTF("waking up waiters on %p rcv_notify=%d flags=0x%x\n", so, sb_notify(&so->so_rcv), so->so_rcv.sb_flags);
sorwakeup(so);
sowwakeup(so);
@@ -1825,19 +1839,18 @@
process_close_con_rpl(struct socket *so, struct mbuf *m)
{
struct tcpcb *tp = sototcpcb(so);
- struct inpcb *inp = tp->t_inpcb;
struct cpl_close_con_rpl *rpl = cplhdr(m);
struct toepcb *toep = tp->t_toe;
tp->snd_una = ntohl(rpl->snd_nxt) - 1; /* exclude FIN */
- printf("process_close_con_rpl(%p) state=%d dead=%d\n", so, tp->t_state,
+ DPRINTF("process_close_con_rpl(%p) state=%d dead=%d\n", so, tp->t_state,
!!(so->so_state & SS_NOFDREF));
if (!is_t3a(TOE_DEV(so)) && (toep->tp_flags & TP_ABORT_RPL_PENDING))
goto out;
INP_INFO_WLOCK(&tcbinfo);
- INP_LOCK(inp);
+ INP_LOCK(tp->t_inpcb);
switch (tp->t_state) {
case TCPS_CLOSING: /* see FIN_WAIT2 case in do_peer_fin */
t3_release_offload_resources(so);
@@ -1884,7 +1897,7 @@
}
INP_INFO_WUNLOCK(&tcbinfo);
if (tp)
- INP_UNLOCK(inp);
+ INP_UNLOCK(tp->t_inpcb);
out:
m_free(m);
}
@@ -1922,14 +1935,13 @@
"process_abort_rpl: GTS rpl pending %d",
sock_flag(sk, ABORT_RPL_PENDING));
#endif
- INP_LOCK_ASSERT(tp->t_inpcb);
+ INP_LOCK(tp->t_inpcb);
if (toep->tp_flags & TP_ABORT_RPL_PENDING) {
if (!(toep->tp_flags & TP_ABORT_RPL_RCVD) && !is_t3a(TOE_DEV(so)))
toep->tp_flags |= TP_ABORT_RPL_RCVD;
else {
toep->tp_flags &= ~(TP_ABORT_RPL_RCVD|TP_ABORT_RPL_PENDING);
-
if (!(toep->tp_flags & TP_ABORT_REQ_RCVD) ||
!is_t3a(TOE_DEV(so))) {
if (toep->tp_flags & TP_ABORT_REQ_RCVD)
@@ -1937,12 +1949,14 @@
INP_INFO_WLOCK(&tcbinfo);
INP_LOCK(tp->t_inpcb);
t3_release_offload_resources(so);
- tcp_close(tp);
+ tp = tcp_close(tp);
INP_INFO_WUNLOCK(&tcbinfo);
- INP_UNLOCK(tp->t_inpcb);
}
}
}
+ if (tp)
+ INP_UNLOCK(tp->t_inpcb);
+
m_free(m);
}
@@ -1979,7 +1993,7 @@
*/
if (!toep)
goto discard;
-
+
so = toeptoso(toep);
toepcb_hold(toep);
process_abort_rpl(so, m);
@@ -2024,6 +2038,8 @@
rpl->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_HOST_ABORT_CON_RPL));
rpl->wr.wr_lo = htonl(V_WR_TID(tid));
+ m->m_len = m->m_pkthdr.len = sizeof(*rpl);
+
OPCODE_TID(rpl) = htonl(MK_OPCODE_TID(CPL_ABORT_RPL, tid));
rpl->cmd = cmd;
}
@@ -2079,6 +2095,7 @@
cxgb_ofld_send(TOM_DATA(tdev)->cdev, reply_mbuf);
}
+#ifdef notyet
static void
cleanup_syn_rcv_conn(struct socket *child, struct socket *parent)
{
@@ -2093,6 +2110,7 @@
#endif
}
+
/*
* Performs the actual work to abort a SYN_RECV connection.
*/
@@ -2101,8 +2119,7 @@
{
struct tcpcb *parenttp = sototcpcb(parent);
struct tcpcb *childtp = sototcpcb(child);
- struct inpcb *inp = sotoinpcb(child);
-
+
/*
* If the server is still open we clean up the child connection,
* otherwise the server already did the clean up as it was purging
@@ -2111,15 +2128,16 @@
if (__predict_false(parenttp->t_state == TCPS_LISTEN)) {
cleanup_syn_rcv_conn(child, parent);
INP_INFO_WLOCK(&tcbinfo);
- INP_LOCK(inp);
+ INP_LOCK(childtp->t_inpcb);
t3_release_offload_resources(child);
- tcp_close(childtp);
+ childtp = tcp_close(childtp);
INP_INFO_WUNLOCK(&tcbinfo);
- INP_UNLOCK(inp);
+ if (childtp)
+ INP_UNLOCK(childtp->t_inpcb);
}
}
+#endif
-
/*
* Handle abort requests for a SYN_RECV connection. These need extra work
* because the socket is on its parent's SYN queue.
@@ -2163,11 +2181,11 @@
struct tcpcb *tp = sototcpcb(so);
struct toepcb *toep = tp->t_toe;
- INP_LOCK_ASSERT(tp->t_inpcb);
+ INP_LOCK(tp->t_inpcb);
if ((toep->tp_flags & TP_ABORT_REQ_RCVD) == 0) {
toep->tp_flags |= (TP_ABORT_REQ_RCVD|TP_ABORT_SHUTDOWN);
m_free(m);
- return;
+ goto skip;
}
toep->tp_flags &= ~TP_ABORT_REQ_RCVD;
@@ -2193,15 +2211,18 @@
* returns 0 is has taken care of the abort.
*/
if ((tp->t_state == TCPS_SYN_RECEIVED) && !abort_syn_rcv(so, m))
- return;
+ goto skip;
- INP_LOCK(tp->t_inpcb);
t3_release_offload_resources(so);
- tcp_close(tp);
- INP_UNLOCK(tp->t_inpcb);
+ tp = tcp_close(tp);
}
+ if (tp)
+ INP_UNLOCK(tp->t_inpcb);
+ send_abort_rpl(m, tdev, rst_status);
+ return;
- send_abort_rpl(m, tdev, rst_status);
+skip:
+ INP_UNLOCK(tp->t_inpcb);
}
/*
@@ -2213,15 +2234,30 @@
const struct cpl_abort_req_rss *req = cplhdr(m);
struct toepcb *toep = (struct toepcb *)ctx;
struct socket *so;
+ struct inpcb *inp;
if (is_neg_adv_abort(req->status)) {
m_free(m);
return (0);
}
+
printf("aborting tid=%d\n", toep->tp_tid);
- INP_INFO_WLOCK(&tcbinfo);
if (toep->tp_flags & TP_SYN_RCVD) {
+ cxgb_remove_tid(cdev, toep, toep->tp_tid);
+ printf("sending abort rpl\n");
+
+ send_abort_rpl(m, toep->tp_toedev, CPL_ABORT_NO_RST);
+ printf("sent\n");
+ if (toep->tp_l2t)
+ l2t_release(L2DATA(cdev), toep->tp_l2t);
+
+ /*
+ * XXX need to call syncache_chkrst - but we don't
+ * have a way of doing that yet
+ */
+ toepcb_release(toep);
+
printf("abort for unestablished connection :-(\n");
return (0);
}
@@ -2232,14 +2268,17 @@
}
so = toeptoso(toep);
+ inp = sotoinpcb(so);
+
VALIDATE_SOCK(so);
toepcb_hold(toep);
+ INP_INFO_WLOCK(&tcbinfo);
process_abort_req(so, m, TOE_DEV(so));
INP_INFO_WUNLOCK(&tcbinfo);
toepcb_release(toep);
return (0);
}
-
+#ifdef notyet
static void
pass_open_abort(struct socket *child, struct socket *parent, struct mbuf *m)
{
@@ -2255,7 +2294,7 @@
} else
m_free(m);
}
-
+#endif
static void
handle_pass_open_arp_failure(struct socket *so, struct mbuf *m)
{
@@ -2616,7 +2655,7 @@
newtoep->tp_tid = tid;
newtoep->tp_toedev = tdev;
- DPRINTF("inserting tid=%d\n", tid);
+ printf("inserting tid=%d\n", tid);
cxgb_insert_tid(cdev, d->client, newtoep, tid);
if (lctx->ulp_mode) {
@@ -2631,7 +2670,11 @@
set_arp_failure_handler(reply_mbuf, pass_accept_rpl_arp_failure);
DPRINTF("adding request to syn cache\n");
-
+
+ /*
+ * XXX workaround for lack of syncache drop
+ */
+ toepcb_hold(newtoep);
syncache_add_accept_req(req, so, newtoep);
rpl = cplhdr(reply_mbuf);
@@ -2850,7 +2893,7 @@
to.to_wscale = G_TCPOPT_SND_WSCALE(opt);
to.to_flags = (mss ? TOF_MSS : 0) | (wsf ? TOF_SCALE : 0) | (ts ? TOF_TS : 0) | (sack ? TOF_SACKPERM : 0);
- printf("syncache expand of %d:%d %d:%d mss:%d wsf:%d ts:%d sack:%d\n",
+ DPRINTF("syncache expand of %d:%d %d:%d mss:%d wsf:%d ts:%d sack:%d\n",
ntohl(req->local_ip), ntohs(req->local_port),
ntohl(req->peer_ip), ntohs(req->peer_port),
mss, wsf, ts, sack);
@@ -2891,6 +2934,11 @@
*/
UNIMPLEMENTED();
}
+
+ /*
+ * XXX workaround for lack of syncache drop
+ */
+ toepcb_release(toep);
tp = sototcpcb(so);
INP_LOCK(tp->t_inpcb);
@@ -2900,6 +2948,7 @@
tp->t_toe = toep;
reset_wr_list(tp);
tp->rcv_wnd = select_rcv_wnd(so);
+ DPRINTF("rcv_wnd=%ld\n", tp->rcv_wnd);
install_offload_ops(so);
toep->tp_wr_max = toep->tp_wr_avail = TOM_TUNABLE(tdev, max_wrs);
More information about the p4-projects
mailing list