diff options
author | rwatson <rwatson@FreeBSD.org> | 2008-04-21 12:03:59 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2008-04-21 12:03:59 +0000 |
commit | c6e37355a2f7b8c97a9e27321b849448a8a909a8 (patch) | |
tree | d2887788e31642325153044566e6d9bc1a937680 /sys | |
parent | ca37ae1f066b064769052aa4e9035b4a22f0703e (diff) | |
download | FreeBSD-src-c6e37355a2f7b8c97a9e27321b849448a8a909a8.zip FreeBSD-src-c6e37355a2f7b8c97a9e27321b849448a8a909a8.tar.gz |
Read lock, rather than write lock, the inpcb when transmitting with or
delivering to an IP divert socket.
MFC after: 3 months
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip_divert.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index b2ec79f..158a9e7 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -268,7 +268,7 @@ divert_packet(struct mbuf *m, int incoming) nport = htons((u_int16_t)divert_info(mtag)); INP_INFO_RLOCK(&divcbinfo); LIST_FOREACH(inp, &divcb, inp_list) { - INP_WLOCK(inp); + INP_RLOCK(inp); /* XXX why does only one socket match? */ if (inp->inp_lport == nport) { sa = inp->inp_socket; @@ -280,10 +280,10 @@ divert_packet(struct mbuf *m, int incoming) sa = NULL; /* force mbuf reclaim below */ } else sorwakeup_locked(sa); - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); break; } - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); } INP_INFO_RUNLOCK(&divcbinfo); if (sa == NULL) { @@ -356,7 +356,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, dt->info |= IP_FW_DIVERT_OUTPUT_FLAG; INP_INFO_WLOCK(&divcbinfo); inp = sotoinpcb(so); - INP_WLOCK(inp); + INP_RLOCK(inp); /* * Don't allow both user specified and setsockopt options, * and don't allow packet length sizes that will crash @@ -364,7 +364,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options) || ((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) { error = EINVAL; - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); INP_INFO_WUNLOCK(&divcbinfo); m_freem(m); } else { @@ -405,7 +405,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, if (options == NULL) error = ENOBUFS; } - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); INP_INFO_WUNLOCK(&divcbinfo); if (error == ENOBUFS) { m_freem(m); @@ -615,11 +615,11 @@ div_pcblist(SYSCTL_HANDLER_ARGS) INP_INFO_RLOCK(&divcbinfo); for (inp = LIST_FIRST(divcbinfo.ipi_listhead), i = 0; inp && i < n; inp = LIST_NEXT(inp, inp_list)) { - INP_WLOCK(inp); + INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt && cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0) inp_list[i++] = inp; - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); } INP_INFO_RUNLOCK(&divcbinfo); n = i; @@ -627,7 +627,7 @@ div_pcblist(SYSCTL_HANDLER_ARGS) error = 0; for (i = 0; i < n; i++) { inp = inp_list[i]; - INP_WLOCK(inp); + INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt) { struct xinpcb xi; bzero(&xi, sizeof(xi)); @@ -636,10 +636,10 @@ div_pcblist(SYSCTL_HANDLER_ARGS) bcopy(inp, &xi.xi_inp, sizeof *inp); if (inp->inp_socket) sotoxsocket(inp->inp_socket, &xi.xi_socket); - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); error = SYSCTL_OUT(req, &xi, sizeof xi); } else - INP_WUNLOCK(inp); + INP_RUNLOCK(inp); } if (!error) { /* |