summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_syscalls.c
diff options
context:
space:
mode:
authortanimura <tanimura@FreeBSD.org>2002-05-20 05:41:09 +0000
committertanimura <tanimura@FreeBSD.org>2002-05-20 05:41:09 +0000
commit92d8381dd544a8237b3fd68c4e7fce9bd0903fb2 (patch)
tree2465ddbcecac65f96c5c6d5cef1a4fe3f1ac03f8 /sys/kern/uipc_syscalls.c
parent969293170b27461145f69a538d5abd15fea34ba1 (diff)
downloadFreeBSD-src-92d8381dd544a8237b3fd68c4e7fce9bd0903fb2.zip
FreeBSD-src-92d8381dd544a8237b3fd68c4e7fce9bd0903fb2.tar.gz
Lock down a socket, milestone 1.
o Add a mutex (sb_mtx) to struct sockbuf. This protects the data in a socket buffer. The mutex in the receive buffer also protects the data in struct socket. o Determine the lock strategy for each members in struct socket. o Lock down the following members: - so_count - so_options - so_linger - so_state o Remove *_locked() socket APIs. Make the following socket APIs touching the members above now require a locked socket: - sodisconnect() - soisconnected() - soisconnecting() - soisdisconnected() - soisdisconnecting() - sofree() - soref() - sorele() - sorwakeup() - sotryfree() - sowakeup() - sowwakeup() Reviewed by: alfred
Diffstat (limited to 'sys/kern/uipc_syscalls.c')
-rw-r--r--sys/kern/uipc_syscalls.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index f80dcc9..0c00fe5 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -245,12 +245,15 @@ accept1(td, uap, compat)
if (error)
goto done2;
s = splnet();
+ SOCK_LOCK(head);
if ((head->so_options & SO_ACCEPTCONN) == 0) {
+ SOCK_UNLOCK(head);
splx(s);
error = EINVAL;
goto done;
}
if ((head->so_state & SS_NBIO) && TAILQ_EMPTY(&head->so_comp)) {
+ SOCK_UNLOCK(head);
splx(s);
error = EWOULDBLOCK;
goto done;
@@ -260,13 +263,16 @@ accept1(td, uap, compat)
head->so_error = ECONNABORTED;
break;
}
- error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
+ error = msleep((caddr_t)&head->so_timeo,
+ SOCK_MTX(head), PSOCK | PCATCH,
"accept", 0);
if (error) {
+ SOCK_UNLOCK(head);
splx(s);
goto done;
}
}
+ SOCK_UNLOCK(head);
if (head->so_error) {
error = head->so_error;
head->so_error = 0;
@@ -305,13 +311,17 @@ accept1(td, uap, compat)
/* connection has been removed from the listen queue */
KNOTE(&head->so_rcv.sb_sel.si_note, 0);
+ SOCK_LOCK(so);
so->so_state &= ~SS_COMP;
+ SOCK_UNLOCK(so);
so->so_head = NULL;
if (head->so_sigio != NULL)
fsetown(fgetown(head->so_sigio), &so->so_sigio);
FILE_LOCK(nfp);
+ SOCK_LOCK(so);
soref(so); /* file descriptor reference */
+ SOCK_UNLOCK(so);
nfp->f_data = (caddr_t)so; /* nfp has ref count from falloc */
nfp->f_flag = fflag;
nfp->f_ops = &socketops;
@@ -432,24 +442,30 @@ connect(td, uap)
mtx_lock(&Giant);
if ((error = fgetsock(td, uap->s, &so, NULL)) != 0)
goto done2;
+ SOCK_LOCK(so);
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
+ SOCK_UNLOCK(so);
error = EALREADY;
goto done1;
}
+ SOCK_UNLOCK(so);
error = getsockaddr(&sa, uap->name, uap->namelen);
if (error)
goto done1;
error = soconnect(so, sa, td);
if (error)
goto bad;
+ SOCK_LOCK(so);
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
+ SOCK_UNLOCK(so);
FREE(sa, M_SONAME);
error = EINPROGRESS;
goto done1;
}
s = splnet();
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
- error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH, "connec", 0);
+ error = msleep((caddr_t)&so->so_timeo,
+ SOCK_MTX(so), PSOCK | PCATCH, "connec", 0);
if (error)
break;
}
@@ -457,9 +473,12 @@ connect(td, uap)
error = so->so_error;
so->so_error = 0;
}
+ SOCK_UNLOCK(so);
splx(s);
bad:
+ SOCK_LOCK(so);
so->so_state &= ~SS_ISCONNECTING;
+ SOCK_UNLOCK(so);
FREE(sa, M_SONAME);
if (error == ERESTART)
error = EINTR;
@@ -1412,10 +1431,13 @@ getpeername1(td, uap, compat)
mtx_lock(&Giant);
if ((error = fgetsock(td, uap->fdes, &so, NULL)) != 0)
goto done2;
+ SOCK_LOCK(so);
if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
+ SOCK_UNLOCK(so);
error = ENOTCONN;
goto done1;
}
+ SOCK_UNLOCK(so);
error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
if (error)
goto done1;
@@ -1673,10 +1695,13 @@ sendfile(struct thread *td, struct sendfile_args *uap)
error = EINVAL;
goto done;
}
+ SOCK_LOCK(so);
if ((so->so_state & SS_ISCONNECTED) == 0) {
+ SOCK_UNLOCK(so);
error = ENOTCONN;
goto done;
}
+ SOCK_UNLOCK(so);
if (uap->offset < 0) {
error = EINVAL;
goto done;
@@ -1739,14 +1764,17 @@ retry_lookup:
* Optimize the non-blocking case by looking at the socket space
* before going to the extra work of constituting the sf_buf.
*/
+ SOCK_LOCK(so);
if ((so->so_state & SS_NBIO) && sbspace(&so->so_snd) <= 0) {
if (so->so_state & SS_CANTSENDMORE)
error = EPIPE;
else
error = EAGAIN;
+ SOCK_UNLOCK(so);
sbunlock(&so->so_snd);
goto done;
}
+ SOCK_UNLOCK(so);
/*
* Attempt to look up the page.
*
@@ -1869,6 +1897,7 @@ retry_space:
* blocks before the pru_send (or more accurately, any blocking
* results in a loop back to here to re-check).
*/
+ SOCK_LOCK(so);
if ((so->so_state & SS_CANTSENDMORE) || so->so_error) {
if (so->so_state & SS_CANTSENDMORE) {
error = EPIPE;
@@ -1876,6 +1905,7 @@ retry_space:
error = so->so_error;
so->so_error = 0;
}
+ SOCK_UNLOCK(so);
m_freem(m);
sbunlock(&so->so_snd);
splx(s);
@@ -1888,12 +1918,14 @@ retry_space:
*/
if (sbspace(&so->so_snd) < so->so_snd.sb_lowat) {
if (so->so_state & SS_NBIO) {
+ SOCK_UNLOCK(so);
m_freem(m);
sbunlock(&so->so_snd);
splx(s);
error = EAGAIN;
goto done;
}
+ SOCK_UNLOCK(so);
error = sbwait(&so->so_snd);
/*
* An error from sbwait usually indicates that we've
@@ -1908,6 +1940,7 @@ retry_space:
}
goto retry_space;
}
+ SOCK_UNLOCK(so);
error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, 0, 0, td);
splx(s);
if (error) {
OpenPOWER on IntegriCloud