Date: Sat, 8 Dec 2007 05:23:56 GMT From: Kip Macy <kmacy@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 130462 for review Message-ID: <200712080523.lB85NulX047529@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=130462 Change 130462 by kmacy@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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712080523.lB85NulX047529>