Index: sys/kern/uipc_sockbuf.c =================================================================== --- sys/kern/uipc_sockbuf.c +++ sys/kern/uipc_sockbuf.c @@ -296,7 +296,7 @@ sbfree(struct sockbuf *sb, struct mbuf *m) { -#if 0 /* XXX: not yet: soclose() call path comes here w/o lock. */ +#if 1 /* XXX: not yet: soclose() call path comes here w/o lock. */ SOCKBUF_LOCK_ASSERT(sb); #endif @@ -366,7 +366,7 @@ sbfree_ktls_rx(struct sockbuf *sb, struct mbuf *m) { -#if 0 /* XXX: not yet: soclose() call path comes here w/o lock. */ +#if 1 /* XXX: not yet: soclose() call path comes here w/o lock. */ SOCKBUF_LOCK_ASSERT(sb); #endif @@ -745,13 +745,15 @@ void sbdestroy(struct sockbuf *sb, struct socket *so) { - + MPASS(so->so_count == 0 || so->so_count == 1); + SOCKBUF_LOCK(sb); // XXX: not needed but silences assertions sbrelease_internal(sb, so); #ifdef KERN_TLS if (sb->sb_tls_info != NULL) ktls_free(sb->sb_tls_info); sb->sb_tls_info = NULL; #endif + SOCKBUF_UNLOCK(sb); // XXX: no needed } /* Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -1450,10 +1450,12 @@ tp->t_srtt != 0 && tp->rfbuf_ts != 0 && TCP_TS_TO_TICKS(tcp_ts_getticks() - tp->rfbuf_ts) > ((tp->t_srtt >> TCP_RTT_SHIFT)/2)) { + SOCKBUF_LOCK(&so->so_rcv); if (tp->rfbuf_cnt > ((so->so_rcv.sb_hiwat / 2)/ 4 * 3) && so->so_rcv.sb_hiwat < V_tcp_autorcvbuf_max) { newsize = min((so->so_rcv.sb_hiwat + (so->so_rcv.sb_hiwat/2)), V_tcp_autorcvbuf_max); } + SOCKBUF_UNLOCK(&so->so_rcv); TCP_PROBE6(receive__autoresize, NULL, tp, m, tp, th, newsize); /* Start over with next RTT. */ @@ -1859,12 +1861,12 @@ tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); tp->t_flags |= TF_WAKESOW; - if (sbavail(&so->so_snd)) + if (sbavail_dolock(&so->so_snd)) (void) tp->t_fb->tfb_tcp_output(tp); goto check_delack; } } else if (th->th_ack == tp->snd_una && - tlen <= sbspace(&so->so_rcv)) { + tlen <= sbspace_dolock(&so->so_rcv)) { int newsize = 0; /* automatic sockbuf scaling */ /* @@ -1941,7 +1943,7 @@ * Receive window is amount of space in rcv queue, * but not less than advertised window. */ - win = sbspace(&so->so_rcv); + win = sbspace_dolock(&so->so_rcv); if (win < 0) win = 0; tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt)); @@ -2986,12 +2988,17 @@ * we should release the tp also, and use a * compressed state. */ + SOCKBUF_UNLOCK_ASSERT(&so->so_rcv); + SOCKBUF_LOCK(&so->so_rcv); if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { + SOCKBUF_UNLOCK(&so->so_rcv); soisdisconnected(so); tcp_timer_activate(tp, TT_2MSL, (tcp_fast_finwait2_recycle ? tcp_finwait2_timeout : TP_MAXIDLE(tp))); + } else { + SOCKBUF_UNLOCK(&so->so_rcv); } tcp_state_change(tp, TCPS_FIN_WAIT_2); } @@ -3219,6 +3226,7 @@ * buffer size. * XXX: Unused. */ + SOCKBUF_LOCK_ASSERT(&so->so_rcv); if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt)) len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt); else Index: sys/netinet/tcp_output.c =================================================================== --- sys/netinet/tcp_output.c +++ sys/netinet/tcp_output.c @@ -572,6 +572,7 @@ flags &= ~TH_FIN; } + SOCKBUF_LOCK(&so->so_rcv); recwin = lmin(lmax(sbspace(&so->so_rcv), 0), (long)TCP_MAXWIN << tp->rcv_scale); @@ -759,10 +760,12 @@ */ just_return: SOCKBUF_UNLOCK(&so->so_snd); + SOCKBUF_UNLOCK(&so->so_rcv); return (0); send: SOCKBUF_LOCK_ASSERT(&so->so_snd); + SOCKBUF_LOCK_ASSERT(&so->so_rcv); if (len > 0) { if (len >= tp->t_maxseg) tp->t_flags2 |= TF2_PLPMTU_MAXSEGSNT; @@ -887,6 +890,7 @@ !(to.to_flags & TOF_FASTOPEN)) len = 0; } + SOCKBUF_UNLOCK(&so->so_rcv); /* * Adjust data length if insertion of options will @@ -1133,6 +1137,7 @@ m->m_len = hdrlen; } SOCKBUF_UNLOCK_ASSERT(&so->so_snd); + SOCKBUF_UNLOCK_ASSERT(&so->so_rcv); m->m_pkthdr.rcvif = (struct ifnet *)0; #ifdef MAC mac_inpcb_create_mbuf(tp->t_inpcb, m); @@ -1212,6 +1217,7 @@ flags |= TH_ECE; } + SOCKBUF_LOCK(&so->so_rcv); /* * If we are doing retransmissions, then snd_nxt will * not reflect the first unsent octet. For ACK only @@ -1250,6 +1256,7 @@ if (flags & TH_RST) { recwin = 0; } else { + SOCKBUF_LOCK_ASSERT(&so->so_rcv); if (recwin < (so->so_rcv.sb_hiwat / 4) && recwin < tp->t_maxseg) recwin = 0; @@ -1270,6 +1277,7 @@ recwin = roundup2(recwin, 1 << tp->rcv_scale); th->th_win = htons((u_short)(recwin >> tp->rcv_scale)); } + SOCKBUF_UNLOCK(&so->so_rcv); /* * Adjust the RXWIN0SENT flag - indicate that we have advertised @@ -1553,7 +1561,7 @@ tp->t_rxtshift = 0; } tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); - } else if (len == 0 && sbavail(&so->so_snd) && + } else if (len == 0 && sbavail_dolock(&so->so_snd) && !tcp_timer_active(tp, TT_REXMT) && !tcp_timer_active(tp, TT_PERSIST)) { /* @@ -1696,6 +1704,8 @@ #endif if (sendalot) goto again; + SOCKBUF_UNLOCK_ASSERT(&so->so_rcv); + SOCKBUF_UNLOCK_ASSERT(&so->so_snd); return (0); } Index: sys/sys/sockbuf.h =================================================================== --- sys/sys/sockbuf.h +++ sys/sys/sockbuf.h @@ -59,10 +59,10 @@ #define SBS_RCVATMARK 0x0040 /* at mark on input */ #if defined(_KERNEL) || defined(_WANT_SOCKET) -#include -#include #include #include +#include +#include #define SB_MAX (2*1024*1024) /* default for max chars in sockbuf */ @@ -199,7 +199,7 @@ sbavail(struct sockbuf *sb) { -#if 0 +#if 1 SOCKBUF_LOCK_ASSERT(sb); #endif return (sb->sb_acc); @@ -213,7 +213,7 @@ sbused(struct sockbuf *sb) { -#if 0 +#if 1 SOCKBUF_LOCK_ASSERT(sb); #endif return (sb->sb_ccc); @@ -229,7 +229,7 @@ { int bleft, mleft; /* size should match sockbuf fields */ -#if 0 +#if 1 SOCKBUF_LOCK_ASSERT(sb); #endif @@ -242,6 +242,22 @@ return ((bleft < mleft) ? bleft : mleft); } +#define sbspace_dolock(sb) \ + ({ \ + SOCKBUF_LOCK(sb); \ + long _space = sbspace(sb); \ + SOCKBUF_UNLOCK(sb); \ + _space; \ + }) + +#define sbavail_dolock(sb) \ + ({ \ + SOCKBUF_LOCK(sb); \ + long _space = sbavail(sb); \ + SOCKBUF_UNLOCK(sb); \ + _space; \ + }) + #define SB_EMPTY_FIXUP(sb) do { \ if ((sb)->sb_mb == NULL) { \ (sb)->sb_mbtail = NULL; \