1
0
mirror of https://github.com/openbsd/src.git synced 2024-12-21 23:18:00 -08:00

Use per-sockbuf mutex(9) to protect `so_rcv' buffer of tcp(4) sockets.

Only unlock soreceive() path, somove() path still locked exclusively. Also
exclusive  socket lock will be taken in the soreceive() path each time
before pru_rcvd() call.

Note, both socket and `sb_mtx' locks are held while SS_CANTRCVMORE
modified, so socket lock is enough to check it in the protocol input
path.

ok bluhm
This commit is contained in:
mvs 2024-12-19 22:11:35 +00:00
parent 10d5b13ebf
commit f1bf6f4e82
5 changed files with 47 additions and 19 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: uipc_socket.c,v 1.346 2024/12/15 11:00:05 dlg Exp $ */
/* $OpenBSD: uipc_socket.c,v 1.347 2024/12/19 22:11:35 mvs Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@ -160,6 +160,8 @@ soalloc(const struct protosw *prp, int wait)
case SOCK_RAW:
case SOCK_DGRAM:
so->so_snd.sb_flags |= SB_MTXLOCK;
/* FALLTHROUGH */
case SOCK_STREAM:
so->so_rcv.sb_flags |= SB_MTXLOCK;
break;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: uipc_socket2.c,v 1.159 2024/11/06 14:37:45 bluhm Exp $ */
/* $OpenBSD: uipc_socket2.c,v 1.160 2024/12/19 22:11:35 mvs Exp $ */
/* $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $ */
/*
@ -839,8 +839,7 @@ sbappend(struct socket *so, struct sockbuf *sb, struct mbuf *m)
void
sbappendstream(struct socket *so, struct sockbuf *sb, struct mbuf *m)
{
KASSERT(sb == &so->so_rcv || sb == &so->so_snd);
soassertlocked(so);
sbmtxassertlocked(so, sb);
KDASSERT(m->m_nextpkt == NULL);
KASSERT(sb->sb_mb == sb->sb_lastrecord);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_input.c,v 1.408 2024/11/08 21:40:39 bluhm Exp $ */
/* $OpenBSD: tcp_input.c,v 1.409 2024/12/19 22:11:35 mvs Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@ -334,8 +334,11 @@ tcp_flush_queue(struct tcpcb *tp)
ND6_HINT(tp);
if (so->so_rcv.sb_state & SS_CANTRCVMORE)
m_freem(q->tcpqe_m);
else
else {
mtx_enter(&so->so_rcv.sb_mtx);
sbappendstream(so, &so->so_rcv, q->tcpqe_m);
mtx_leave(&so->so_rcv.sb_mtx);
}
pool_put(&tcpqe_pool, q);
q = nq;
} while (q != NULL && q->tcpqe_tcp->th_seq == tp->rcv_nxt);
@ -1051,7 +1054,9 @@ findpcb:
} else
tp->rfbuf_cnt += tlen;
m_adj(m, iphlen + off);
mtx_enter(&so->so_rcv.sb_mtx);
sbappendstream(so, &so->so_rcv, m);
mtx_leave(&so->so_rcv.sb_mtx);
}
tp->t_flags |= TF_BLOCKOUTPUT;
sorwakeup(so);
@ -1869,13 +1874,19 @@ step6:
*/
if ((tiflags & TH_URG) && th->th_urp &&
TCPS_HAVERCVDFIN(tp->t_state) == 0) {
u_long urgent;
/*
* This is a kludge, but if we receive and accept
* random urgent pointers, we'll crash in
* soreceive. It's hard to imagine someone
* actually wanting to send this much urgent data.
*/
if (th->th_urp + so->so_rcv.sb_cc > sb_max) {
mtx_enter(&so->so_rcv.sb_mtx);
urgent = th->th_urp + so->so_rcv.sb_cc;
mtx_leave(&so->so_rcv.sb_mtx);
if (urgent > sb_max) {
th->th_urp = 0; /* XXX */
tiflags &= ~TH_URG; /* XXX */
goto dodata; /* XXX */
@ -1948,7 +1959,9 @@ dodata: /* XXX */
m_freem(m);
else {
m_adj(m, hdroptlen);
mtx_enter(&so->so_rcv.sb_mtx);
sbappendstream(so, &so->so_rcv, m);
mtx_leave(&so->so_rcv.sb_mtx);
}
tp->t_flags |= TF_BLOCKOUTPUT;
sorwakeup(so);
@ -2998,6 +3011,7 @@ tcp_mss_update(struct tcpcb *tp)
(void)sbreserve(so, &so->so_snd, bufsize);
}
mtx_enter(&so->so_rcv.sb_mtx);
bufsize = so->so_rcv.sb_hiwat;
if (bufsize > mss) {
bufsize = roundup(bufsize, mss);
@ -3005,6 +3019,7 @@ tcp_mss_update(struct tcpcb *tp)
bufsize = sb_max;
(void)sbreserve(so, &so->so_rcv, bufsize);
}
mtx_leave(&so->so_rcv.sb_mtx);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_output.c,v 1.145 2024/05/14 09:39:02 bluhm Exp $ */
/* $OpenBSD: tcp_output.c,v 1.146 2024/12/19 22:11:35 mvs Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@ -195,7 +195,7 @@ int
tcp_output(struct tcpcb *tp)
{
struct socket *so = tp->t_inpcb->inp_socket;
long len, win, txmaxseg;
long len, win, rcv_hiwat, txmaxseg;
int off, flags, error;
struct mbuf *m;
struct tcphdr *th;
@ -373,7 +373,10 @@ again:
if (off + len < so->so_snd.sb_cc)
flags &= ~TH_FIN;
win = sbspace(so, &so->so_rcv);
mtx_enter(&so->so_rcv.sb_mtx);
win = sbspace_locked(so, &so->so_rcv);
rcv_hiwat = (long) so->so_rcv.sb_hiwat;
mtx_leave(&so->so_rcv.sb_mtx);
/*
* Sender silly window avoidance. If connection is idle
@ -420,7 +423,7 @@ again:
if (adv >= (long) (2 * tp->t_maxseg))
goto send;
if (2 * adv >= (long) so->so_rcv.sb_hiwat)
if (2 * adv >= rcv_hiwat)
goto send;
}
@ -854,7 +857,7 @@ send:
* Calculate receive window. Don't shrink window,
* but avoid silly window syndrome.
*/
if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg)
if (win < (rcv_hiwat / 4) && win < (long)tp->t_maxseg)
win = 0;
if (win > (long)TCP_MAXWIN << tp->rcv_scale)
win = (long)TCP_MAXWIN << tp->rcv_scale;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: tcp_usrreq.c,v 1.232 2024/11/08 15:46:55 bluhm Exp $ */
/* $OpenBSD: tcp_usrreq.c,v 1.233 2024/12/19 22:11:35 mvs Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@ -296,10 +296,12 @@ tcp_fill_info(struct tcpcb *tp, struct socket *so, struct mbuf *m)
ti->tcpi_rfbuf_cnt = tp->rfbuf_cnt;
ti->tcpi_rfbuf_ts = (now - tp->rfbuf_ts) * t;
mtx_enter(&so->so_rcv.sb_mtx);
ti->tcpi_so_rcv_sb_cc = so->so_rcv.sb_cc;
ti->tcpi_so_rcv_sb_hiwat = so->so_rcv.sb_hiwat;
ti->tcpi_so_rcv_sb_lowat = so->so_rcv.sb_lowat;
ti->tcpi_so_rcv_sb_wat = so->so_rcv.sb_wat;
mtx_leave(&so->so_rcv.sb_mtx);
ti->tcpi_so_snd_sb_cc = so->so_snd.sb_cc;
ti->tcpi_so_snd_sb_hiwat = so->so_snd.sb_hiwat;
ti->tcpi_so_snd_sb_lowat = so->so_snd.sb_lowat;
@ -1044,7 +1046,9 @@ tcp_dodisconnect(struct tcpcb *tp)
tp = tcp_drop(tp, 0);
else {
soisdisconnecting(so);
mtx_enter(&so->so_rcv.sb_mtx);
sbflush(so, &so->so_rcv);
mtx_leave(&so->so_rcv.sb_mtx);
tp = tcp_usrclosed(tp);
if (tp)
(void) tcp_output(tp);
@ -1556,7 +1560,11 @@ void
tcp_update_rcvspace(struct tcpcb *tp)
{
struct socket *so = tp->t_inpcb->inp_socket;
u_long nmax = so->so_rcv.sb_hiwat;
u_long nmax;
mtx_enter(&so->so_rcv.sb_mtx);
nmax = so->so_rcv.sb_hiwat;
if (sbchecklowmem()) {
/* low on memory try to get rid of some */
@ -1577,10 +1585,11 @@ tcp_update_rcvspace(struct tcpcb *tp)
nmax < so->so_snd.sb_lowat)
nmax = so->so_snd.sb_lowat;
if (nmax == so->so_rcv.sb_hiwat)
return;
if (nmax != so->so_rcv.sb_hiwat) {
/* round to MSS boundary */
nmax = roundup(nmax, tp->t_maxseg);
sbreserve(so, &so->so_rcv, nmax);
}
/* round to MSS boundary */
nmax = roundup(nmax, tp->t_maxseg);
sbreserve(so, &so->so_rcv, nmax);
mtx_leave(&so->so_rcv.sb_mtx);
}