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
This commit is contained in:
Gleb Smirnoff
2026-04-12 11:30:59 -07:00
parent 202370905f
commit 2cfe62664a
5 changed files with 14 additions and 34 deletions
+5 -7
View File
@@ -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)
+5 -23
View File
@@ -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) || \
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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.
+2 -2
View File
@@ -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)