Date: Sun, 12 Apr 2026 18:35:36 +0000 From: Gleb Smirnoff <glebius@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 8b4d0bec4311 - main - inpcb: make in_pcbbind() acquire the hash lock internally Message-ID: <69dbe5f8.3a90c.181a2a8d@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=8b4d0bec43116f5d4d1fba89d1b81f1d05805147 commit 8b4d0bec43116f5d4d1fba89d1b81f1d05805147 Author: Gleb Smirnoff <glebius@FreeBSD.org> AuthorDate: 2026-04-12 18:33:20 +0000 Commit: Gleb Smirnoff <glebius@FreeBSD.org> CommitDate: 2026-04-12 18:33:20 +0000 inpcb: make in_pcbbind() acquire the hash lock internally Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D55970 --- sys/netinet/in_pcb.c | 9 +++++++-- sys/netinet/tcp_usrreq.c | 10 ---------- sys/netinet/udp_usrreq.c | 6 ------ sys/netinet6/in6_pcb.c | 15 +++++++++++---- sys/netinet6/udp6_usrreq.c | 4 ---- 5 files changed, 18 insertions(+), 26 deletions(-) diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index f1053f6abe03..6c5b7869d945 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -727,22 +727,27 @@ in_pcbbind(struct inpcb *inp, struct sockaddr_in *sin, int flags, KASSERT(sin == NULL || sin->sin_len == sizeof(struct sockaddr_in), ("%s: invalid address length for %p", __func__, sin)); INP_WLOCK_ASSERT(inp); - INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY) return (EINVAL); anonport = sin == NULL || sin->sin_port == 0; + + INP_HASH_WLOCK(inp->inp_pcbinfo); error = in_pcbbind_setup(inp, sin, &inp->inp_laddr.s_addr, &inp->inp_lport, flags, cred); - if (error) + if (error) { + INP_HASH_WUNLOCK(inp->inp_pcbinfo); return (error); + } if (__predict_false((error = in_pcbinshash(inp)) != 0)) { + INP_HASH_WUNLOCK(inp->inp_pcbinfo); MPASS(inp->inp_socket->so_options & SO_REUSEPORT_LB); inp->inp_laddr.s_addr = INADDR_ANY; inp->inp_lport = 0; inp->inp_flags &= ~INP_BOUNDFIB; return (error); } + INP_HASH_WUNLOCK(inp->inp_pcbinfo); if (anonport) inp->inp_flags |= INP_ANONPORT; return (0); diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index ce13f1a9cefe..72100a0fb9d9 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -256,10 +256,8 @@ tcp_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td) error = EAFNOSUPPORT; goto out; } - INP_HASH_WLOCK(&V_tcbinfo); error = in_pcbbind(inp, sinp, V_tcp_bind_all_fibs ? 0 : INPBIND_FIB, td->td_ucred); - INP_HASH_WUNLOCK(&V_tcbinfo); out: tcp_bblog_pru(tp, PRU_BIND, error); TCP_PROBE2(debug__user, tp, PRU_BIND); @@ -305,7 +303,6 @@ tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td) goto out; } - INP_HASH_WLOCK(&V_tcbinfo); inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; #ifdef INET @@ -318,20 +315,17 @@ tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td) in6_sin6_2_sin(&sin, sin6); if (IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) { error = EAFNOSUPPORT; - INP_HASH_WUNLOCK(&V_tcbinfo); goto out; } inp->inp_vflag |= INP_IPV4; inp->inp_vflag &= ~INP_IPV6; error = in_pcbbind(inp, &sin, 0, td->td_ucred); - INP_HASH_WUNLOCK(&V_tcbinfo); goto out; } } #endif error = in6_pcbbind(inp, sin6, V_tcp_bind_all_fibs ? 0 : INPBIND_FIB, td->td_ucred); - INP_HASH_WUNLOCK(&V_tcbinfo); out: if (error != 0) inp->inp_vflag = vflagsav; @@ -368,10 +362,8 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td) goto out; } if (inp->inp_lport == 0) { - INP_HASH_WLOCK(&V_tcbinfo); error = in_pcbbind(inp, NULL, V_tcp_bind_all_fibs ? 0 : INPBIND_FIB, td->td_ucred); - INP_HASH_WUNLOCK(&V_tcbinfo); } if (error == 0) { tcp_state_change(tp, TCPS_LISTEN); @@ -426,7 +418,6 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td) SOCK_UNLOCK(so); goto out; } - INP_HASH_WLOCK(&V_tcbinfo); if (inp->inp_lport == 0) { inp->inp_vflag &= ~INP_IPV4; if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) @@ -434,7 +425,6 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td) error = in6_pcbbind(inp, NULL, V_tcp_bind_all_fibs ? 0 : INPBIND_FIB, td->td_ucred); } - INP_HASH_WUNLOCK(&V_tcbinfo); if (error == 0) { tcp_state_change(tp, TCPS_LISTEN); solisten_proto(so, backlog); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index e425af92048d..3e8011542753 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1356,10 +1356,8 @@ udp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr, .sin_len = sizeof(struct sockaddr_in), }; - INP_HASH_WLOCK(pcbinfo); error = in_pcbbind(inp, &wild, V_udp_bind_all_fibs ? 0 : INPBIND_FIB, td->td_ucred); - INP_HASH_WUNLOCK(pcbinfo); if (error) goto release; lport = inp->inp_lport; @@ -1599,11 +1597,9 @@ static int udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { struct inpcb *inp; - struct inpcbinfo *pcbinfo; struct sockaddr_in *sinp; int error; - pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_bind: inp == NULL")); @@ -1622,10 +1618,8 @@ udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td) return (EINVAL); INP_WLOCK(inp); - INP_HASH_WLOCK(pcbinfo); error = in_pcbbind(inp, sinp, V_udp_bind_all_fibs ? 0 : INPBIND_FIB, td->td_ucred); - INP_HASH_WUNLOCK(pcbinfo); INP_WUNLOCK(inp); return (error); } diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 09a62a53e054..c4469136fc90 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -297,7 +297,6 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, int flags, int error, fib, lookupflags, sooptions; INP_WLOCK_ASSERT(inp); - INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) return (EINVAL); @@ -310,6 +309,7 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, int flags, if ((error = prison_local_ip6(cred, &inp->in6p_laddr, ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) return (error); + INP_HASH_WLOCK(inp->inp_pcbinfo); } else { KASSERT(sin6->sin6_family == AF_INET6, ("%s: invalid address family for %p", __func__, sin6)); @@ -326,11 +326,14 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, int flags, fib = (flags & INPBIND_FIB) != 0 ? inp->inp_inc.inc_fibnum : RT_ALL_FIBS; + INP_HASH_WLOCK(inp->inp_pcbinfo); /* See if this address/port combo is available. */ - error = in6_pcbbind_avail(inp, sin6, fib, sooptions, lookupflags, - cred); - if (error != 0) + error = in6_pcbbind_avail(inp, sin6, fib, sooptions, + lookupflags, cred); + if (error != 0) { + INP_HASH_WUNLOCK(inp->inp_pcbinfo); return (error); + } lport = sin6->sin6_port; inp->in6p_laddr = sin6->sin6_addr; @@ -339,6 +342,7 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, int flags, inp->inp_flags |= INP_BOUNDFIB; if (lport == 0) { if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0) { + INP_HASH_WUNLOCK(inp->inp_pcbinfo); /* Undo an address bind that may have occurred. */ inp->inp_flags &= ~INP_BOUNDFIB; inp->in6p_laddr = in6addr_any; @@ -347,12 +351,15 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, int flags, } else { inp->inp_lport = lport; if (in_pcbinshash(inp) != 0) { + INP_HASH_WUNLOCK(inp->inp_pcbinfo); inp->inp_flags &= ~INP_BOUNDFIB; inp->in6p_laddr = in6addr_any; inp->inp_lport = 0; return (EAGAIN); } } + INP_HASH_WUNLOCK(inp->inp_pcbinfo); + return (0); } diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index 715f43f0d47c..6e37586f16e4 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -1046,11 +1046,9 @@ udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) { struct sockaddr_in6 *sin6_p; struct inpcb *inp; - struct inpcbinfo *pcbinfo; int error; u_char vflagsav; - pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_bind: inp == NULL")); @@ -1062,7 +1060,6 @@ udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) sin6_p = (struct sockaddr_in6 *)nam; INP_WLOCK(inp); - INP_HASH_WLOCK(pcbinfo); vflagsav = inp->inp_vflag; inp->inp_vflag &= ~INP_IPV4; inp->inp_vflag |= INP_IPV6; @@ -1091,7 +1088,6 @@ out: #endif if (error != 0) inp->inp_vflag = vflagsav; - INP_HASH_WUNLOCK(pcbinfo); INP_WUNLOCK(inp); return (error); }home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69dbe5f8.3a90c.181a2a8d>
