diff options
author | jhb <jhb@FreeBSD.org> | 2005-07-09 12:26:22 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2005-07-09 12:26:22 +0000 |
commit | 8816876fa9909d3428b22db33b1e6fd8edcdd209 (patch) | |
tree | 95ebffd3322d517c3c43f6c216357b9bb934d16e /sys/compat/linux/linux_socket.c | |
parent | 8c5a4b8551b185d28592d3d03103bfcf97ac4955 (diff) | |
download | FreeBSD-src-8816876fa9909d3428b22db33b1e6fd8edcdd209.zip FreeBSD-src-8816876fa9909d3428b22db33b1e6fd8edcdd209.tar.gz |
Add missing locking to linux_connect() so that it can be marked MP safe:
- Conditionally grab Giant around the EISCONN hack at the end based on
debug.mpsafenet.
- Protect access to so_emuldata via SOCK_LOCK.
Reviewed by: rwatson
Approved by: re (scottl)
Diffstat (limited to 'sys/compat/linux/linux_socket.c')
-rw-r--r-- | sys/compat/linux/linux_socket.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 950e170..f1f26bc 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -44,7 +44,9 @@ __FBSDID("$FreeBSD$"); #include <sys/fcntl.h> #include <sys/file.h> #include <sys/limits.h> +#include <sys/lock.h> #include <sys/malloc.h> +#include <sys/mutex.h> #include <sys/mbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> @@ -614,15 +616,20 @@ linux_connect(struct thread *td, struct linux_connect_args *args) * when on a non-blocking socket. Instead it returns the * error getsockopt(SOL_SOCKET, SO_ERROR) would return on BSD. */ - if ((error = fgetsock(td, linux_args.s, &so, &fflag)) != 0) - return(error); - error = EISCONN; - if (fflag & FNONBLOCK) { - if (so->so_emuldata == 0) - error = so->so_error; - so->so_emuldata = (void *)1; + NET_LOCK_GIANT(); + error = fgetsock(td, linux_args.s, &so, &fflag); + if (error == 0) { + error = EISCONN; + if (fflag & FNONBLOCK) { + SOCK_LOCK(so); + if (so->so_emuldata == 0) + error = so->so_error; + so->so_emuldata = (void *)1; + SOCK_UNLOCK(so); + } + fputsock(so); } - fputsock(so); + NET_UNLOCK_GIANT(); return (error); } |