summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_subr.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2008-05-29 14:28:26 +0000
committerrwatson <rwatson@FreeBSD.org>2008-05-29 14:28:26 +0000
commit4ab736a48e0210d0590c2f490c981f7b6d60a697 (patch)
treee6e1196ef44b7badc4f87fe1fe8687f74651f31f /sys/netinet/tcp_subr.c
parent5de6a45e07a5027a8c6df5a9c354fbfd9c76aec1 (diff)
downloadFreeBSD-src-4ab736a48e0210d0590c2f490c981f7b6d60a697.zip
FreeBSD-src-4ab736a48e0210d0590c2f490c981f7b6d60a697.tar.gz
Read lock rather than write lock TCP inpcbs in monitoring sysctls. In
some cases, add explicit inpcb locking rather than relying on the global lock, as we dereference inp_socket, but also allowing us to drop the global lock more quickly. MFC after: 1 week
Diffstat (limited to 'sys/netinet/tcp_subr.c')
-rw-r--r--sys/netinet/tcp_subr.c66
1 files changed, 31 insertions, 35 deletions
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 36422197..cb2d89a 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -946,7 +946,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_RLOCK(&tcbinfo);
for (inp = LIST_FIRST(tcbinfo.ipi_listhead), i = 0; inp != NULL && i
< n; inp = LIST_NEXT(inp, inp_list)) {
- INP_WLOCK(inp);
+ INP_RLOCK(inp);
if (inp->inp_gencnt <= gencnt) {
/*
* XXX: This use of cr_cansee(), introduced with
@@ -965,7 +965,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
if (error == 0)
inp_list[i++] = inp;
}
- INP_WUNLOCK(inp);
+ INP_RUNLOCK(inp);
}
INP_INFO_RUNLOCK(&tcbinfo);
n = i;
@@ -973,7 +973,7 @@ tcp_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 xtcpcb xt;
void *inp_ppcb;
@@ -997,10 +997,10 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
xt.xt_socket.xso_protocol = IPPROTO_TCP;
}
xt.xt_inp.inp_gencnt = inp->inp_gencnt;
- INP_WUNLOCK(inp);
+ INP_RUNLOCK(inp);
error = SYSCTL_OUT(req, &xt, sizeof xt);
} else
- INP_WUNLOCK(inp);
+ INP_RUNLOCK(inp);
}
if (!error) {
@@ -1042,23 +1042,21 @@ tcp_getcred(SYSCTL_HANDLER_ARGS)
INP_INFO_RLOCK(&tcbinfo);
inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
addrs[0].sin_addr, addrs[0].sin_port, 0, NULL);
- if (inp == NULL) {
- error = ENOENT;
- goto outunlocked;
- }
- INP_WLOCK(inp);
- if (inp->inp_socket == NULL) {
+ if (inp != NULL) {
+ INP_RLOCK(inp);
+ INP_INFO_RUNLOCK(&tcbinfo);
+ if (inp->inp_socket == NULL)
+ error = ENOENT;
+ if (error == 0)
+ error = cr_canseesocket(req->td->td_ucred,
+ inp->inp_socket);
+ if (error == 0)
+ cru2x(inp->inp_socket->so_cred, &xuc);
+ INP_RUNLOCK(inp);
+ } else {
+ INP_INFO_RUNLOCK(&tcbinfo);
error = ENOENT;
- goto out;
}
- error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
- if (error)
- goto out;
- cru2x(inp->inp_socket->so_cred, &xuc);
-out:
- INP_WUNLOCK(inp);
-outunlocked:
- INP_INFO_RUNLOCK(&tcbinfo);
if (error == 0)
error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
return (error);
@@ -1106,23 +1104,21 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS)
inp = in6_pcblookup_hash(&tcbinfo,
&addrs[1].sin6_addr, addrs[1].sin6_port,
&addrs[0].sin6_addr, addrs[0].sin6_port, 0, NULL);
- if (inp == NULL) {
- error = ENOENT;
- goto outunlocked;
- }
- INP_WLOCK(inp);
- if (inp->inp_socket == NULL) {
+ if (inp != NULL) {
+ INP_RLOCK(inp);
+ INP_INFO_RUNLOCK(&tcbinfo);
+ if (inp->inp_socket == NULL)
+ error = ENOENT;
+ if (error == 0)
+ error = cr_canseesocket(req->td->td_ucred,
+ inp->inp_socket);
+ if (error == 0)
+ cru2x(inp->inp_socket->so_cred, &xuc);
+ INP_RUNLOCK(inp);
+ } else {
+ INP_INFO_RUNLOCK(&tcbinfo);
error = ENOENT;
- goto out;
}
- error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
- if (error)
- goto out;
- cru2x(inp->inp_socket->so_cred, &xuc);
-out:
- INP_WUNLOCK(inp);
-outunlocked:
- INP_INFO_RUNLOCK(&tcbinfo);
if (error == 0)
error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
return (error);
OpenPOWER on IntegriCloud