git: 2cfe62664ab7 - main - inpcb: retire the inpcbinfo list lock
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 12 Apr 2026 18:35:31 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=2cfe62664ab74756e40e17f7b8692d7a07531b83
commit 2cfe62664ab74756e40e17f7b8692d7a07531b83
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2026-04-12 18:30:59 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2026-04-12 18:30:59 +0000
inpcb: retire the inpcbinfo list lock
With the SMR locking of inpcbs the use of this lock reduced down to the
global list and generation number. It was used only on an inpcb creation
and destruction. Use the inpcbinfo hash lock for this purpose.
Reviewed by: pouria, rrs, markj
Differential Revision: https://reviews.freebsd.org/D55966
---
sys/netinet/in_pcb.c | 12 +++++-------
sys/netinet/in_pcb.h | 28 +++++-----------------------
sys/netinet/raw_ip.c | 2 +-
sys/netinet/tcp_subr.c | 2 +-
sys/netinet/udp_usrreq.c | 4 ++--
5 files changed, 14 insertions(+), 34 deletions(-)
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 98421a7f2232..d60c75ab45b5 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -558,7 +558,6 @@ in_pcbinfo_init(struct inpcbinfo *pcbinfo, struct inpcbstorage *pcbstor,
.head = HASH_HEAD_CK_LIST,
};
- mtx_init(&pcbinfo->ipi_lock, pcbstor->ips_infolock_name, NULL, MTX_DEF);
mtx_init(&pcbinfo->ipi_hash_lock, pcbstor->ips_hashlock_name,
NULL, MTX_DEF);
#ifdef VIMAGE
@@ -602,7 +601,6 @@ in_pcbinfo_destroy(struct inpcbinfo *pcbinfo)
hashfree(pcbinfo->ipi_porthashbase, &ha);
hashfree(pcbinfo->ipi_lbgrouphashbase, &ha);
mtx_destroy(&pcbinfo->ipi_hash_lock);
- mtx_destroy(&pcbinfo->ipi_lock);
}
/*
@@ -697,11 +695,11 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
inp->inp_route.ro_flags = RT_LLE_CACHE;
refcount_init(&inp->inp_refcount, 1); /* Reference from socket. */
INP_WLOCK(inp);
- INP_INFO_WLOCK(pcbinfo);
+ INP_HASH_WLOCK(pcbinfo);
pcbinfo->ipi_count++;
inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
CK_LIST_INSERT_HEAD(&pcbinfo->ipi_listhead, inp, inp_list);
- INP_INFO_WUNLOCK(pcbinfo);
+ INP_HASH_WUNLOCK(pcbinfo);
so->so_pcb = inp;
return (0);
@@ -1799,13 +1797,13 @@ in_pcbfree(struct inpcb *inp)
* from the hash without acquiring inpcb lock, they rely on the hash
* lock, thus in_pcbremhash() should be the first action.
*/
+ INP_HASH_WLOCK(pcbinfo);
if (inp->inp_flags & INP_INHASHLIST)
- in_pcbremhash(inp);
- INP_INFO_WLOCK(pcbinfo);
+ in_pcbremhash_locked(inp);
inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
pcbinfo->ipi_count--;
CK_LIST_REMOVE(inp, inp_list);
- INP_INFO_WUNLOCK(pcbinfo);
+ INP_HASH_WUNLOCK(pcbinfo);
#ifdef RATELIMIT
if (inp->inp_snd_tag != NULL)
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index a1b547462d53..e76e3fa8e382 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -422,30 +422,23 @@ struct inpcb {
* IPv4 and IPv6.
*
* The pcbs are protected with SMR section and thus all lists in inpcbinfo
- * are CK-lists. Locking is required to insert a pcb into database. Two
- * locks are provided: one for the hash and one for the global list of pcbs,
- * as well as overall count and generation count.
+ * are CK-lists. Locking is required to insert a pcb into database.
*
* Locking key:
*
* (c) Constant or nearly constant after initialisation
* (e) Protected by SMR section
- * (g) Locked by ipi_lock
* (h) Locked by ipi_hash_lock
*/
struct inpcbinfo {
- /*
- * Global lock protecting inpcb list modification
- */
- struct mtx ipi_lock;
- struct inpcbhead ipi_listhead; /* (r:e/w:g) */
- u_int ipi_count; /* (g) */
+ struct inpcbhead ipi_listhead; /* (r:e/w:h) */
+ u_int ipi_count; /* (h) */
/*
* Generation count -- incremented each time a connection is allocated
* or freed.
*/
- u_quad_t ipi_gencnt; /* (g) */
+ u_quad_t ipi_gencnt; /* (h) */
/*
* Fields associated with port lookup and allocation.
@@ -498,11 +491,10 @@ struct inpcbstorage {
uma_init ips_pcbinit;
size_t ips_size;
const char * ips_zone_name;
- const char * ips_infolock_name;
const char * ips_hashlock_name;
};
-#define INPCBSTORAGE_DEFINE(prot, ppcb, lname, zname, iname, hname) \
+#define INPCBSTORAGE_DEFINE(prot, ppcb, lname, zname, hname) \
static int \
prot##_inpcb_init(void *mem, int size __unused, int flags __unused) \
{ \
@@ -515,7 +507,6 @@ static struct inpcbstorage prot = { \
.ips_size = sizeof(struct ppcb), \
.ips_pcbinit = prot##_inpcb_init, \
.ips_zone_name = zname, \
- .ips_infolock_name = iname, \
.ips_hashlock_name = hname, \
}; \
SYSINIT(prot##_inpcbstorage_init, SI_SUB_PROTO_DOMAIN, \
@@ -564,15 +555,6 @@ struct socket *
void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
uint32_t *faddr, uint16_t *fp);
-#define INP_INFO_WLOCK(ipi) mtx_lock(&(ipi)->ipi_lock)
-#define INP_INFO_WLOCKED(ipi) mtx_owned(&(ipi)->ipi_lock)
-#define INP_INFO_WUNLOCK(ipi) mtx_unlock(&(ipi)->ipi_lock)
-#define INP_INFO_LOCK_ASSERT(ipi) MPASS(SMR_ENTERED((ipi)->ipi_smr) || \
- mtx_owned(&(ipi)->ipi_lock))
-#define INP_INFO_WLOCK_ASSERT(ipi) mtx_assert(&(ipi)->ipi_lock, MA_OWNED)
-#define INP_INFO_WUNLOCK_ASSERT(ipi) \
- mtx_assert(&(ipi)->ipi_lock, MA_NOTOWNED)
-
#define INP_HASH_WLOCK(ipi) mtx_lock(&(ipi)->ipi_hash_lock)
#define INP_HASH_WUNLOCK(ipi) mtx_unlock(&(ipi)->ipi_hash_lock)
#define INP_HASH_LOCK_ASSERT(ipi) MPASS(SMR_ENTERED((ipi)->ipi_smr) || \
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index a8a4fc1df9e2..f2fec876d077 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -181,7 +181,7 @@ rip_delhash(struct inpcb *inp)
}
#endif /* INET */
-INPCBSTORAGE_DEFINE(ripcbstor, inpcb, "rawinp", "ripcb", "rip", "riphash");
+INPCBSTORAGE_DEFINE(ripcbstor, inpcb, "rawinp", "ripcb", "riphash");
static void
rip_init(void *arg __unused)
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index b6bb0221e872..43c430708926 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1140,7 +1140,7 @@ static struct mtx isn_mtx;
#define ISN_LOCK() mtx_lock(&isn_mtx)
#define ISN_UNLOCK() mtx_unlock(&isn_mtx)
-INPCBSTORAGE_DEFINE(tcpcbstor, tcpcb, "tcpinp", "tcp_inpcb", "tcp", "tcphash");
+INPCBSTORAGE_DEFINE(tcpcbstor, tcpcb, "tcpinp", "tcp_inpcb", "tcphash");
/*
* Take a value and get the next power of 2 that doesn't overflow.
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index e8847ea12f1e..eb37ceddace0 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -165,9 +165,9 @@ VNET_PCPUSTAT_SYSUNINIT(udpstat);
static void udp_detach(struct socket *so);
#endif
-INPCBSTORAGE_DEFINE(udpcbstor, udpcb, "udpinp", "udp_inpcb", "udp", "udphash");
+INPCBSTORAGE_DEFINE(udpcbstor, udpcb, "udpinp", "udp_inpcb", "udphash");
INPCBSTORAGE_DEFINE(udplitecbstor, udpcb, "udpliteinp", "udplite_inpcb",
- "udplite", "udplitehash");
+ "udplitehash");
static void
udp_vnet_init(void *arg __unused)