Index: sys/amd64/conf/GENERIC =================================================================== --- sys/amd64/conf/GENERIC +++ sys/amd64/conf/GENERIC @@ -395,3 +395,9 @@ options HID_DEBUG # enable debug msgs device hid # Generic HID support options IICHID_SAMPLING # Workaround missing GPIO INTR support + + +# More debug +options DEBUG_VFS_LOCKS # enable VFS lock debugging +options SOCKBUF_DEBUG # enable sockbuf last record/mb tail checking +options IFMEDIA_DEBUG # enable debugging in net/if_media.c Index: sys/amd64/conf/GENERIC-KCSAN =================================================================== --- sys/amd64/conf/GENERIC-KCSAN +++ sys/amd64/conf/GENERIC-KCSAN @@ -39,3 +39,8 @@ options NETSMB # Seems to be needed by SMBFS options LIBMCHAIN # Also seems to be needed by SMBFS options LIBICONV # Also seems to be needed by SMBFS + +# More debug +options DEBUG_VFS_LOCKS # enable VFS lock debugging +options SOCKBUF_DEBUG # enable sockbuf last record/mb tail checking +options IFMEDIA_DEBUG # enable debugging in net/if_media.c Index: sys/kern/sys_socket.c =================================================================== --- sys/kern/sys_socket.c +++ sys/kern/sys_socket.c @@ -228,12 +228,14 @@ if (SOLISTENING(so)) { error = EINVAL; } else { + SOCKBUF_LOCK(&so->so_snd); if ((so->so_snd.sb_hiwat < sbused(&so->so_snd)) || (so->so_snd.sb_mbmax < so->so_snd.sb_mbcnt)) { *(int *)data = 0; } else { *(int *)data = sbspace(&so->so_snd); } + SOCKBUF_UNLOCK(&so->so_snd); } break; 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. */ @@ -1864,7 +1866,7 @@ 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 @@ -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/netinet/tcp_timewait.c =================================================================== --- sys/netinet/tcp_timewait.c +++ sys/netinet/tcp_timewait.c @@ -295,11 +295,13 @@ * Recover last window size sent. */ so = inp->inp_socket; + SOCKBUF_LOCK(&so->so_rcv); recwin = lmin(lmax(sbspace(&so->so_rcv), 0), (long)TCP_MAXWIN << tp->rcv_scale); if (recwin < (so->so_rcv.sb_hiwat / 4) && recwin < tp->t_maxseg) recwin = 0; + SOCKBUF_UNLOCK(&so->so_rcv); if (SEQ_GT(tp->rcv_adv, tp->rcv_nxt) && recwin < (tp->rcv_adv - tp->rcv_nxt)) recwin = (tp->rcv_adv - tp->rcv_nxt); 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 */ @@ -202,7 +202,7 @@ #if 0 SOCKBUF_LOCK_ASSERT(sb); #endif - return (sb->sb_acc); + return atomic_load_int(&sb->sb_acc); } /* @@ -216,7 +216,7 @@ #if 0 SOCKBUF_LOCK_ASSERT(sb); #endif - return (sb->sb_ccc); + return atomic_load_int(&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,14 @@ return ((bleft < mleft) ? bleft : mleft); } +#define sbspace_dolock(sb) \ + ({ \ + SOCKBUF_LOCK(sb); \ + long _space = sbspace(sb); \ + SOCKBUF_UNLOCK(sb); \ + _space; \ + }) + #define SB_EMPTY_FIXUP(sb) do { \ if ((sb)->sb_mb == NULL) { \ (sb)->sb_mbtail = NULL; \