summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in_pcb.c
diff options
context:
space:
mode:
authorups <ups@FreeBSD.org>2006-07-18 22:34:27 +0000
committerups <ups@FreeBSD.org>2006-07-18 22:34:27 +0000
commitee0a5eb928ae5ccdf1a0e619b4ba6e93d19db5fb (patch)
tree2e39fd9d815a6efa63bdabd6bfed00c38e05310a /sys/netinet/in_pcb.c
parent9adb8df4815a901cfc690d567d4ba0b6c63b1d5d (diff)
downloadFreeBSD-src-ee0a5eb928ae5ccdf1a0e619b4ba6e93d19db5fb.zip
FreeBSD-src-ee0a5eb928ae5ccdf1a0e619b4ba6e93d19db5fb.tar.gz
Fix race conditions on enumerating pcb lists by moving the initialization
( and where appropriate the destruction) of the pcb mutex to the init/finit functions of the pcb zones. This allows locking of the pcb entries and race condition free comparison of the generation count. Rearrange locking a bit to avoid extra locking operation to update the generation count in in_pcballoc(). (in_pcballoc now returns the pcb locked) I am planning to convert pcb list handling from a type safe to a reference count model soon. ( As this allows really freeing the PCBs) Reviewed by: rwatson@, mohans@ MFC after: 1 week
Diffstat (limited to 'sys/netinet/in_pcb.c')
-rw-r--r--sys/netinet/in_pcb.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 37386d7..ddb9e3c 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -167,19 +167,20 @@ SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomtime, CTLFLAG_RW,
/*
* Allocate a PCB and associate it with the socket.
+ * On success return with the PCB locked.
*/
int
-in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo, const char *type)
+in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
{
struct inpcb *inp;
int error;
INP_INFO_WLOCK_ASSERT(pcbinfo);
error = 0;
- inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT | M_ZERO);
+ inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT);
if (inp == NULL)
return (ENOBUFS);
- inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
+ bzero(inp,inp_zero_size);
inp->inp_pcbinfo = pcbinfo;
inp->inp_socket = so;
#ifdef MAC
@@ -209,11 +210,13 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo, const char *type)
LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list);
pcbinfo->ipi_count++;
so->so_pcb = (caddr_t)inp;
- INP_LOCK_INIT(inp, "inp", type);
#ifdef INET6
if (ip6_auto_flowlabel)
inp->inp_flags |= IN6P_AUTOFLOWLABEL;
#endif
+ INP_LOCK(inp);
+ inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
+
#if defined(IPSEC) || defined(FAST_IPSEC) || defined(MAC)
out:
if (error != 0)
@@ -721,10 +724,11 @@ in_pcbfree(struct inpcb *inp)
(void)m_free(inp->inp_options);
ip_freemoptions(inp->inp_moptions);
inp->inp_vflag = 0;
- INP_LOCK_DESTROY(inp);
+
#ifdef MAC
mac_destroy_inpcb(inp);
#endif
+ INP_UNLOCK(inp);
uma_zfree(ipi->ipi_zone, inp);
}
OpenPOWER on IntegriCloud