Diff below shuffle the socket buffer definition to "properly" memset() all required fields in sorflush(). It also gets rid of the sbrelease() abstraction since zeroing out `sb_hiwat' and `sb_mbmax' is required in only one place.
ok? Index: kern/uipc_socket.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket.c,v retrieving revision 1.210 diff -u -p -r1.210 uipc_socket.c --- kern/uipc_socket.c 10 Dec 2017 11:31:54 -0000 1.210 +++ kern/uipc_socket.c 11 Dec 2017 07:46:02 -0000 @@ -216,7 +216,7 @@ sofree(struct socket *so) so->so_sp = NULL; } #endif /* SOCKET_SPLICE */ - sbrelease(so, &so->so_snd); + sbflush(so, &so->so_snd); sorflush(so); pool_put(&socket_pool, so); } @@ -1052,15 +1052,11 @@ sorflush(struct socket *so) sbunlock(so, sb); aso.so_proto = pr; aso.so_rcv = *sb; - memset(sb, 0, sizeof (*sb)); - /* XXX - the memset stomps all over so_rcv */ - if (aso.so_rcv.sb_flagsintr & SB_KNOTE) { - sb->sb_sel.si_note = aso.so_rcv.sb_sel.si_note; - sb->sb_flagsintr = SB_KNOTE; - } + memset(&sb->sb_startzero, 0, + (caddr_t)&sb->sb_endzero - (caddr_t)&sb->sb_startzero); if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) (*pr->pr_domain->dom_dispose)(aso.so_rcv.sb_mb); - sbrelease(&aso, &aso.so_rcv); + sbflush(&aso, &aso.so_rcv); } #ifdef SOCKET_SPLICE Index: kern/uipc_socket2.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket2.c,v retrieving revision 1.88 diff -u -p -r1.88 uipc_socket2.c --- kern/uipc_socket2.c 10 Dec 2017 11:31:54 -0000 1.88 +++ kern/uipc_socket2.c 11 Dec 2017 07:43:29 -0000 @@ -423,8 +423,7 @@ sowakeup(struct socket *so, struct sockb * Before using a new socket structure it is first necessary to reserve * buffer space to the socket, by calling sbreserve(). This should commit * some of the available buffer space in the system buffer pool for the - * socket (currently, it does nothing but enforce limits). The space - * should be released by calling sbrelease() when the socket is destroyed. + * socket (currently, it does nothing but enforce limits). */ int @@ -446,7 +445,8 @@ soreserve(struct socket *so, u_long sndc so->so_snd.sb_lowat = so->so_snd.sb_hiwat; return (0); bad2: - sbrelease(so, &so->so_snd); + sbflush(so, &so->so_snd); + so->so_snd.sb_hiwat = so->so_snd.sb_mbmax = 0; bad: return (ENOBUFS); } @@ -495,17 +495,6 @@ sbchecklowmem(void) mbpool.pr_nout > mbpool.pr_hardlimit * 80 / 100) sblowmem = 1; return (sblowmem); -} - -/* - * Free mbufs held by a socket, and reserved mbuf space. - */ -void -sbrelease(struct socket *so, struct sockbuf *sb) -{ - - sbflush(so, sb); - sb->sb_hiwat = sb->sb_mbmax = 0; } /* Index: sys/socketvar.h =================================================================== RCS file: /cvs/src/sys/sys/socketvar.h,v retrieving revision 1.79 diff -u -p -r1.79 socketvar.h --- sys/socketvar.h 23 Nov 2017 13:45:46 -0000 1.79 +++ sys/socketvar.h 11 Dec 2017 07:49:06 -0000 @@ -98,6 +98,8 @@ struct socket { * Variables for socket buffering. */ struct sockbuf { +/* The following fields are all zeroed on flush. */ +#define sb_startzero sb_cc u_long sb_cc; /* actual chars in buffer */ u_long sb_datacc; /* data only chars in buffer */ u_long sb_hiwat; /* max actual char count */ @@ -109,10 +111,12 @@ struct socket { struct mbuf *sb_mbtail; /* the last mbuf in the chain */ struct mbuf *sb_lastrecord;/* first mbuf of last record in socket buffer */ - struct selinfo sb_sel; /* process selecting read/write */ - int sb_flagsintr; /* flags, changed during interrupt */ - short sb_flags; /* flags, see below */ u_short sb_timeo; /* timeout for read/write */ + short sb_flags; /* flags, see below */ +/* End area that is zeroed on flush. */ +#define sb_endzero sb_flags + int sb_flagsintr; /* flags, changed atomically */ + struct selinfo sb_sel; /* process selecting read/write */ } so_rcv, so_snd; #define SB_MAX (2*1024*1024) /* default for max chars in sockbuf */ #define SB_LOCK 0x01 /* lock on data queue */