Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -1497,18 +1497,21 @@ * the TIME_WAIT state before coming here, we need * to check if the socket is still connected. */ + if (tp == NULL) { + log(2, "%s#%d: tp is NULL\n", __func__, __LINE__); + return; + } + if (so == NULL) { + log(2, "%s#%d: so is NULL\n", __func__, __LINE__); + return; + } if ((so->so_state & SS_ISCONNECTED) == 0) return; INP_LOCK_ASSERT(tp->t_inpcb); if (tp->t_flags & TF_WAKESOR) { tp->t_flags &= ~TF_WAKESOR; - SOCKBUF_UNLOCK_ASSERT(&so->so_rcv); - sorwakeup(so); - } - if (tp->t_flags & TF_WAKESOW) { - tp->t_flags &= ~TF_WAKESOW; - SOCKBUF_UNLOCK_ASSERT(&so->so_snd); - sowwakeup(so); + SOCKBUF_LOCK_ASSERT(&so->so_rcv); + sorwakeup_locked(so); } } @@ -1536,6 +1539,10 @@ struct tcphdr tcp_savetcp; short ostate = 0; #endif + + if ((tp != NULL) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s: WAKESOR left over from last invocation\n", __func__); + thflags = th->th_flags; inc = &tp->t_inpcb->inp_inc; tp->sackhint.last_sack_ack = 0; @@ -1886,7 +1893,7 @@ else if (!tcp_timer_active(tp, TT_PERSIST)) tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); - tp->t_flags |= TF_WAKESOW; + sowwakeup(so); if (sbavail(&so->so_snd)) (void) tp->t_fb->tfb_tcp_output(tp); goto check_delack; @@ -1951,8 +1958,8 @@ m_adj(m, drop_hdrlen); /* delayed header drop */ sbappendstream_locked(&so->so_rcv, m, 0); } - SOCKBUF_UNLOCK(&so->so_rcv); - tp->t_flags |= TF_WAKESOR; + /* NB: sorwakeup_locked() does an implicit unlock. */ + sorwakeup_locked(so); if (DELAY_ACK(tp, tlen)) { tp->t_flags |= TF_DELACK; } else { @@ -2490,9 +2497,11 @@ * If segment contains data or ACK, will call tcp_reass() * later; if not, do so now to pass queued data to user. */ - if (tlen == 0 && (thflags & TH_FIN) == 0) + if (tlen == 0 && (thflags & TH_FIN) == 0) { (void) tcp_reass(tp, (struct tcphdr *)0, NULL, 0, (struct mbuf *)0); + tcp_handle_wakeup(tp, so); + } tp->snd_wl1 = th->th_seq - 1; /* FALLTHROUGH */ @@ -2624,6 +2633,7 @@ } } else tp->snd_cwnd += maxseg; +// (void) tp->t_fb->tfb_tcp_output(tp); goto drop; } else if (tp->t_dupacks == tcprexmtthresh || @@ -2685,6 +2695,7 @@ tcps_sack_recovery_episode); tp->snd_recover = tp->snd_nxt; tp->snd_cwnd = maxseg; +// (void) tp->t_fb->tfb_tcp_output(tp); if (SEQ_GT(th->th_ack, tp->snd_una)) goto resume_partialack; @@ -2692,6 +2703,7 @@ } tp->snd_nxt = th->th_ack; tp->snd_cwnd = maxseg; +// (void) tp->t_fb->tfb_tcp_output(tp); KASSERT(tp->snd_limited <= 2, ("%s: tp->snd_limited too big", @@ -2735,6 +2747,7 @@ * is new data available to be sent. * Otherwise we would send pure ACKs. */ +// SOCKBUF_LOCK(&so->so_snd); avail = sbavail(&so->so_snd) - (tp->snd_nxt - tp->snd_una); @@ -2802,6 +2815,7 @@ tp->t_rtttime = 0; tcp_do_prr_ack(tp, th, &to); tp->t_flags |= TF_ACKNOW; +// (void) tcp_output(tp); } else tcp_sack_partialack(tp, th); @@ -2815,6 +2829,7 @@ tp->sackhint.delivered_data = BYTES_THIS_ACK(tp, th); tp->snd_fack = th->th_ack; tcp_do_prr_ack(tp, th, &to); +// (void) tcp_output(tp); } } else @@ -2926,7 +2941,7 @@ * the congestion window. */ cc_ack_received(tp, th, nsegs, CC_ACK); - +// SOCKBUF_LOCK(&so->so_snd); if (acked > sbavail(&so->so_snd)) { if (tp->snd_wnd >= sbavail(&so->so_snd)) @@ -2944,8 +2959,8 @@ tp->snd_wnd = 0; ourfinisacked = 0; } - SOCKBUF_UNLOCK(&so->so_snd); - tp->t_flags |= TF_WAKESOW; + /* NB: sowwakeup_locked() does an implicit unlock. */ + sowwakeup_locked(so); m_freem(mfree); /* Detect una wraparound. */ if (!IN_RECOVERY(tp->t_flags) && @@ -3005,6 +3020,8 @@ if (ourfinisacked) { tcp_twstart(tp); m_freem(m); + if ((tp != NULL) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s#%d: WAKESOR left over\n", __func__,__LINE__); return; } break; @@ -3058,6 +3075,7 @@ * soreceive. It's hard to imagine someone * actually wanting to send this much urgent data. */ +// SOCKBUF_LOCK(&so->so_rcv); if (th->th_urp + sbavail(&so->so_rcv) > sb_max) { th->th_urp = 0; /* XXX */ @@ -3166,7 +3184,6 @@ m_freem(m); else sbappendstream_locked(&so->so_rcv, m, 0); - SOCKBUF_UNLOCK(&so->so_rcv); tp->t_flags |= TF_WAKESOR; } else { /* @@ -3212,6 +3229,7 @@ save_start + tlen); } } + tcp_handle_wakeup(tp, so); #if 0 /* * Note the amount of data that peer has sent into @@ -3235,9 +3253,12 @@ */ if (thflags & TH_FIN) { if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { - socantrcvmore(so); - /* The socket upcall is handled by socantrcvmore. */ - tp->t_flags &= ~TF_WAKESOR; + if (tp->t_flags & TF_WAKESOR) { + /* The socket upcall is handled by socantrcvmore. */ + tp->t_flags &= ~TF_WAKESOR; + socantrcvmore_locked(so); + } else + socantrcvmore(so); /* * If connection is half-synchronized * (ie NEEDSYN flag on) then delay ACK, @@ -3278,6 +3299,8 @@ */ case TCPS_FIN_WAIT_2: tcp_twstart(tp); + if ((tp != NULL) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s#%d: WAKESOR left over\n", __func__,__LINE__); return; } } @@ -3288,6 +3311,10 @@ #endif TCP_PROBE3(debug__input, tp, th, m); + if ((tp != NULL) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s#%d: handling WAKESOR finally\n", __func__,__LINE__); + + tcp_handle_wakeup(tp, so); /* * Return any desired output. */ @@ -3303,6 +3330,8 @@ } tcp_handle_wakeup(tp, so); INP_WUNLOCK(tp->t_inpcb); + if ((tp != NULL) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s#%d: WAKESOR left over\n", __func__,__LINE__); return; dropafterack: @@ -3333,20 +3362,24 @@ &tcp_savetcp, 0); #endif TCP_PROBE3(debug__input, tp, th, m); + tcp_handle_wakeup(tp, so); tp->t_flags |= TF_ACKNOW; (void) tp->t_fb->tfb_tcp_output(tp); - tcp_handle_wakeup(tp, so); INP_WUNLOCK(tp->t_inpcb); m_freem(m); + if ((tp != NULL) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s#%d: WAKESOR left over\n", __func__,__LINE__); return; dropwithreset: if (tp != NULL) { - tcp_dropwithreset(m, th, tp, tlen, rstreason); tcp_handle_wakeup(tp, so); + tcp_dropwithreset(m, th, tp, tlen, rstreason); INP_WUNLOCK(tp->t_inpcb); } else tcp_dropwithreset(m, th, NULL, tlen, rstreason); + if ((tp != NULL) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s#%d: WAKESOR left over\n", __func__,__LINE__); return; drop: @@ -3364,6 +3397,8 @@ INP_WUNLOCK(tp->t_inpcb); } m_freem(m); + if ((tp != NULL ) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s#%d: WAKESOR left over\n", __func__,__LINE__); } /* @@ -3428,9 +3463,13 @@ tcp_respond(tp, mtod(m, void *), th, m, th->th_seq+tlen, (tcp_seq)0, TH_RST|TH_ACK); } + if ((tp != NULL) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s#%d: WAKESOR left over\n", __func__,__LINE__); return; drop: m_freem(m); + if ((tp != NULL) && (tp->t_flags & TF_WAKESOR)) + log(2, "%s#%d: WAKESOR left over\n", __func__,__LINE__); } /* Index: sys/netinet/tcp_reass.c =================================================================== --- sys/netinet/tcp_reass.c +++ sys/netinet/tcp_reass.c @@ -959,7 +959,6 @@ } else { sbappendstream_locked(&so->so_rcv, m, 0); } - SOCKBUF_UNLOCK(&so->so_rcv); tp->t_flags |= TF_WAKESOR; return (flags); } @@ -1108,7 +1107,6 @@ #ifdef TCP_REASS_LOGGING tcp_reass_log_dump(tp); #endif - SOCKBUF_UNLOCK(&so->so_rcv); tp->t_flags |= TF_WAKESOR; return (flags); } Index: sys/netinet/tcp_stacks/bbr.c =================================================================== --- sys/netinet/tcp_stacks/bbr.c +++ sys/netinet/tcp_stacks/bbr.c @@ -7876,8 +7876,8 @@ acked_amount = min(acked, (int)sbavail(&so->so_snd)); tp->snd_wnd -= acked_amount; mfree = sbcut_locked(&so->so_snd, acked_amount); - SOCKBUF_UNLOCK(&so->so_snd); - tp->t_flags |= TF_WAKESOW; + /* NB: sowwakeup_locked() does an implicit unlock. */ + sowwakeup_locked(so); m_freem(mfree); if (SEQ_GT(th->th_ack, tp->snd_una)) { bbr_collapse_rtt(tp, bbr, TCP_REXMTVAL(tp)); @@ -8353,7 +8353,6 @@ appended = #endif sbappendstream_locked(&so->so_rcv, m, 0); - SOCKBUF_UNLOCK(&so->so_rcv); tp->t_flags |= TF_WAKESOR; #ifdef NETFLIX_SB_LIMITS if (so->so_rcv.sb_shlim && appended != mcnt) @@ -8415,9 +8414,12 @@ */ if (thflags & TH_FIN) { if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { - socantrcvmore(so); - /* The socket upcall is handled by socantrcvmore. */ - tp->t_flags &= ~TF_WAKESOR; + if (tp->t_flags & TF_WAKESOR) { + /* The socket upcall is handled by socantrcvmore. */ + tp->t_flags &= ~TF_WAKESOR; + socantrcvmore_locked(so); + } else + socantrcvmore(so); /* * If connection is half-synchronized (ie NEEDSYN * flag on) then delay ACK, so it may be piggybacked @@ -8608,7 +8610,6 @@ sbappendstream_locked(&so->so_rcv, m, 0); ctf_calc_rwin(so, tp); } - SOCKBUF_UNLOCK(&so->so_rcv); tp->t_flags |= TF_WAKESOR; #ifdef NETFLIX_SB_LIMITS if (so->so_rcv.sb_shlim && mcnt != appended) @@ -8800,7 +8801,7 @@ &tcp_savetcp, 0); #endif /* Wake up the socket if we have room to write more */ - tp->t_flags |= TF_WAKESOW; + sowwakeup(so); if (tp->snd_una == tp->snd_max) { /* Nothing left outstanding */ bbr_log_progress_event(bbr, tp, ticks, PROGRESS_CLEAR, __LINE__); Index: sys/netinet/tcp_stacks/rack.c =================================================================== --- sys/netinet/tcp_stacks/rack.c +++ sys/netinet/tcp_stacks/rack.c @@ -8344,8 +8344,8 @@ */ ourfinisacked = 1; } - SOCKBUF_UNLOCK(&so->so_snd); - tp->t_flags |= TF_WAKESOW; + /* NB: sowwakeup_locked() does an implicit unlock. */ + sowwakeup_locked(so); m_freem(mfree); if (rack->r_ctl.rc_early_recovery == 0) { if (IN_RECOVERY(tp->t_flags)) { @@ -8665,7 +8665,6 @@ appended = #endif sbappendstream_locked(&so->so_rcv, m, 0); - SOCKBUF_UNLOCK(&so->so_rcv); tp->t_flags |= TF_WAKESOR; #ifdef NETFLIX_SB_LIMITS if (so->so_rcv.sb_shlim && appended != mcnt) @@ -8732,9 +8731,12 @@ */ if (thflags & TH_FIN) { if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { - socantrcvmore(so); - /* The socket upcall is handled by socantrcvmore. */ - tp->t_flags &= ~TF_WAKESOR; + if (tp->t_flags & TF_WAKESOR) { + /* The socket upcall is handled by socantrcvmore. */ + tp->t_flags &= ~TF_WAKESOR; + socantrcvmore_locked(so); + } else + socantrcvmore(so); /* * If connection is half-synchronized (ie NEEDSYN * flag on) then delay ACK, so it may be piggybacked @@ -8926,7 +8928,6 @@ sbappendstream_locked(&so->so_rcv, m, 0); ctf_calc_rwin(so, tp); } - SOCKBUF_UNLOCK(&so->so_rcv); tp->t_flags |= TF_WAKESOR; #ifdef NETFLIX_SB_LIMITS if (so->so_rcv.sb_shlim && mcnt != appended) @@ -9144,7 +9145,7 @@ rack_timer_cancel(tp, rack, rack->r_ctl.rc_rcvtime, __LINE__); } /* Wake up the socket if we have room to write more */ - tp->t_flags |= TF_WAKESOW; + sowwakeup(so); if (sbavail(&so->so_snd)) { rack->r_wanted_output = 1; } Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h +++ sys/netinet/tcp_var.h @@ -404,7 +404,7 @@ #define TF_FORCEDATA 0x00800000 /* force out a byte */ #define TF_TSO 0x01000000 /* TSO enabled on this connection */ #define TF_TOE 0x02000000 /* this connection is offloaded */ -#define TF_WAKESOW 0x04000000 /* wake up send socket */ +#define TF_UNUSED0 0x04000000 /* unused */ #define TF_UNUSED1 0x08000000 /* unused */ #define TF_UNUSED2 0x10000000 /* unused */ #define TF_CONGRECOVERY 0x20000000 /* congestion recovery mode */