PERFORCE change 102887 for review
Kip Macy
kmacy at FreeBSD.org
Tue Aug 1 01:13:07 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=102887
Change 102887 by kmacy at kmacy_storage:sun4v_work_stable on 2006/08/01 01:12:06
integrate latest to get working uipc_usrreq.c
Affected files ...
.. //depot/projects/kmacy_sun4v_stable/src/sys/kern/kern_ktrace.c#3 integrate
.. //depot/projects/kmacy_sun4v_stable/src/sys/kern/uipc_usrreq.c#2 integrate
.. //depot/projects/kmacy_sun4v_stable/src/sys/net/bridgestp.c#3 integrate
.. //depot/projects/kmacy_sun4v_stable/src/sys/net/bridgestp.h#2 integrate
.. //depot/projects/kmacy_sun4v_stable/src/sys/net/if_bridge.c#4 integrate
.. //depot/projects/kmacy_sun4v_stable/src/sys/net/if_bridgevar.h#3 integrate
.. //depot/projects/kmacy_sun4v_stable/src/sys/ufs/ufs/ufs_lookup.c#3 integrate
Differences ...
==== //depot/projects/kmacy_sun4v_stable/src/sys/kern/kern_ktrace.c#3 (text+ko) ====
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/kern_ktrace.c,v 1.109 2006/06/27 11:29:38 pjd Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/kern_ktrace.c,v 1.110 2006/07/31 15:31:43 jhb Exp $");
#include "opt_ktrace.h"
#include "opt_mac.h"
@@ -483,15 +483,6 @@
ktr_submitrequest(curthread, req);
}
-/*
- * Since the uio may not stay valid, we can not hand off this request to
- * the thread and need to process it synchronously. However, we wish to
- * keep the relative order of records in a trace file correct, so we
- * do put this request on the queue (if it isn't empty) and then block.
- * The ktrace thread waks us back up when it is time for this event to
- * be posted and blocks until we have completed writing out the event
- * and woken it back up.
- */
void
ktrgenio(fd, rw, uio, error)
int fd;
==== //depot/projects/kmacy_sun4v_stable/src/sys/kern/uipc_usrreq.c#2 (text+ko) ====
@@ -31,8 +31,26 @@
* From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94
*/
+/*
+ * UNIX Domain (Local) Sockets
+ *
+ * This is an implementation of UNIX (local) domain sockets. Each socket has
+ * an associated struct unpcb (UNIX protocol control block). Stream sockets
+ * may be connected to 0 or 1 other socket. Datagram sockets may be
+ * connected to 0, 1, or many other sockets. Sockets may be created and
+ * connected in pairs (socketpair(2)), or bound/connected to using the file
+ * system name space. For most purposes, only the receive socket buffer is
+ * used, as sending on one socket delivers directly to the receive socket
+ * buffer of a second socket. The implementation is substantially
+ * complicated by the fact that "ancillary data", such as file descriptors or
+ * credentials, may be passed across UNIX domain sockets. The potential for
+ * passing UNIX domain sockets over other UNIX domain sockets requires the
+ * implementation of a simple garbage collector to find and tear down cycles
+ * of disconnected sockets.
+ */
+
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/uipc_usrreq.c,v 1.167 2006/04/24 19:09:33 maxim Exp $");
+__FBSDID("$FreeBSD: src/sys/kern/uipc_usrreq.c,v 1.183 2006/07/31 23:00:05 rwatson Exp $");
#include "opt_mac.h"
@@ -88,6 +106,38 @@
struct mbuf *unp_addsockcred(struct thread *, struct mbuf *);
/*
+ * Both send and receive buffers are allocated PIPSIZ bytes of buffering for
+ * stream sockets, although the total for sender and receiver is actually
+ * only PIPSIZ.
+ *
+ * Datagram sockets really use the sendspace as the maximum datagram size,
+ * and don't really want to reserve the sendspace. Their recvspace should be
+ * large enough for at least one max-size datagram plus address.
+ */
+#ifndef PIPSIZ
+#define PIPSIZ 8192
+#endif
+static u_long unpst_sendspace = PIPSIZ;
+static u_long unpst_recvspace = PIPSIZ;
+static u_long unpdg_sendspace = 2*1024; /* really max datagram size */
+static u_long unpdg_recvspace = 4*1024;
+
+static int unp_rights; /* file descriptors in flight */
+
+SYSCTL_DECL(_net_local_stream);
+SYSCTL_ULONG(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW,
+ &unpst_sendspace, 0, "");
+SYSCTL_ULONG(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW,
+ &unpst_recvspace, 0, "");
+SYSCTL_DECL(_net_local_dgram);
+SYSCTL_ULONG(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW,
+ &unpdg_sendspace, 0, "");
+SYSCTL_ULONG(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW,
+ &unpdg_recvspace, 0, "");
+SYSCTL_DECL(_net_local);
+SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
+
+/*
* Currently, UNIX domain sockets are protected by a single subsystem lock,
* which covers global data structures and variables, the contents of each
* per-socket unpcb structure, and the so_pcb field in sockets attached to
@@ -123,9 +173,6 @@
*/
static struct task unp_gc_task;
-static int unp_attach(struct socket *);
-static void unp_detach(struct unpcb *);
-static int unp_bind(struct unpcb *,struct sockaddr *, struct thread *);
static int unp_connect(struct socket *,struct sockaddr *, struct thread *);
static int unp_connect2(struct socket *so, struct socket *so2, int);
static void unp_disconnect(struct unpcb *);
@@ -149,8 +196,7 @@
KASSERT(unp != NULL, ("uipc_abort: unp == NULL"));
UNP_LOCK();
unp_drop(unp, ECONNABORTED);
- unp_detach(unp);
- UNP_UNLOCK_ASSERT();
+ UNP_UNLOCK();
}
static int
@@ -160,9 +206,8 @@
const struct sockaddr *sa;
/*
- * Pass back name of connected socket,
- * if it was bound and we are still connected
- * (our peer may have closed already!).
+ * Pass back name of connected socket, if it was bound and we are
+ * still connected (our peer may have closed already!).
*/
unp = sotounpcb(so);
KASSERT(unp != NULL, ("uipc_accept: unp == NULL"));
@@ -180,39 +225,181 @@
static int
uipc_attach(struct socket *so, int proto, struct thread *td)
{
+ struct unpcb *unp;
+ int error;
+
+ KASSERT(so->so_pcb == NULL, ("uipc_attach: so_pcb != NULL"));
+ if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
+ switch (so->so_type) {
+
+ case SOCK_STREAM:
+ error = soreserve(so, unpst_sendspace, unpst_recvspace);
+ break;
+
+ case SOCK_DGRAM:
+ error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
+ break;
+
+ default:
+ panic("unp_attach");
+ }
+ if (error)
+ return (error);
+ }
+ unp = uma_zalloc(unp_zone, M_WAITOK | M_ZERO);
+ if (unp == NULL)
+ return (ENOBUFS);
+ LIST_INIT(&unp->unp_refs);
+ unp->unp_socket = so;
+ so->so_pcb = unp;
+
+ UNP_LOCK();
+ unp->unp_gencnt = ++unp_gencnt;
+ unp_count++;
+ LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
+ : &unp_shead, unp, unp_link);
+ UNP_UNLOCK();
- return (unp_attach(so));
+ return (0);
}
static int
uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
{
+ struct sockaddr_un *soun = (struct sockaddr_un *)nam;
+ struct vattr vattr;
+ int error, namelen;
+ struct nameidata nd;
struct unpcb *unp;
- int error;
+ struct vnode *vp;
+ struct mount *mp;
+ char *buf;
unp = sotounpcb(so);
KASSERT(unp != NULL, ("uipc_bind: unp == NULL"));
+
+ namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
+ if (namelen <= 0)
+ return (EINVAL);
+
+ /*
+ * We don't allow simultaneous bind() calls on a single UNIX domain
+ * socket, so flag in-progress operations, and return an error if an
+ * operation is already in progress.
+ *
+ * Historically, we have not allowed a socket to be rebound, so this
+ * also returns an error. Not allowing re-binding certainly
+ * simplifies the implementation and avoids a great many possible
+ * failure modes.
+ */
UNP_LOCK();
- error = unp_bind(unp, nam, td);
+ if (unp->unp_vnode != NULL) {
+ UNP_UNLOCK();
+ return (EINVAL);
+ }
+ if (unp->unp_flags & UNP_BINDING) {
+ UNP_UNLOCK();
+ return (EALREADY);
+ }
+ unp->unp_flags |= UNP_BINDING;
+ UNP_UNLOCK();
+
+ buf = malloc(namelen + 1, M_TEMP, M_WAITOK);
+ strlcpy(buf, soun->sun_path, namelen + 1);
+
+ mtx_lock(&Giant);
+restart:
+ mtx_assert(&Giant, MA_OWNED);
+ NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, UIO_SYSSPACE,
+ buf, td);
+/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
+ error = namei(&nd);
+ if (error)
+ goto error;
+ vp = nd.ni_vp;
+ if (vp != NULL || vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ if (nd.ni_dvp == vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ if (vp != NULL) {
+ vrele(vp);
+ error = EADDRINUSE;
+ goto error;
+ }
+ error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH);
+ if (error)
+ goto error;
+ goto restart;
+ }
+ VATTR_NULL(&vattr);
+ vattr.va_type = VSOCK;
+ vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask);
+#ifdef MAC
+ error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
+ &vattr);
+#endif
+ if (error == 0) {
+ VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
+ error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
+ }
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vput(nd.ni_dvp);
+ if (error) {
+ vn_finished_write(mp);
+ goto error;
+ }
+ vp = nd.ni_vp;
+ ASSERT_VOP_LOCKED(vp, "uipc_bind");
+ soun = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK);
+ UNP_LOCK();
+ vp->v_socket = unp->unp_socket;
+ unp->unp_vnode = vp;
+ unp->unp_addr = soun;
+ unp->unp_flags &= ~UNP_BINDING;
+ UNP_UNLOCK();
+ VOP_UNLOCK(vp, 0, td);
+ vn_finished_write(mp);
+ mtx_unlock(&Giant);
+ free(buf, M_TEMP);
+ return (0);
+error:
+ UNP_LOCK();
+ unp->unp_flags &= ~UNP_BINDING;
UNP_UNLOCK();
+ mtx_unlock(&Giant);
+ free(buf, M_TEMP);
return (error);
}
static int
uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
- struct unpcb *unp;
int error;
KASSERT(td == curthread, ("uipc_connect: td != curthread"));
- unp = sotounpcb(so);
- KASSERT(unp != NULL, ("uipc_connect: unp == NULL"));
UNP_LOCK();
error = unp_connect(so, nam, td);
UNP_UNLOCK();
return (error);
}
+/*
+ * XXXRW: Should also unbind?
+ */
+static void
+uipc_close(struct socket *so)
+{
+ struct unpcb *unp;
+
+ unp = sotounpcb(so);
+ KASSERT(unp != NULL, ("uipc_close: unp == NULL"));
+ UNP_LOCK();
+ unp_disconnect(unp);
+ UNP_UNLOCK();
+}
+
int
uipc_connect2(struct socket *so1, struct socket *so2)
{
@@ -232,13 +419,45 @@
static void
uipc_detach(struct socket *so)
{
+ int local_unp_rights;
struct unpcb *unp;
+ struct vnode *vp;
unp = sotounpcb(so);
KASSERT(unp != NULL, ("uipc_detach: unp == NULL"));
UNP_LOCK();
- unp_detach(unp);
- UNP_UNLOCK_ASSERT();
+ LIST_REMOVE(unp, unp_link);
+ unp->unp_gencnt = ++unp_gencnt;
+ --unp_count;
+ if ((vp = unp->unp_vnode) != NULL) {
+ /*
+ * XXXRW: should v_socket be frobbed only while holding
+ * Giant?
+ */
+ unp->unp_vnode->v_socket = NULL;
+ unp->unp_vnode = NULL;
+ }
+ if (unp->unp_conn != NULL)
+ unp_disconnect(unp);
+ while (!LIST_EMPTY(&unp->unp_refs)) {
+ struct unpcb *ref = LIST_FIRST(&unp->unp_refs);
+ unp_drop(ref, ECONNRESET);
+ }
+ unp->unp_socket->so_pcb = NULL;
+ local_unp_rights = unp_rights;
+ UNP_UNLOCK();
+ if (unp->unp_addr != NULL)
+ FREE(unp->unp_addr, M_SONAME);
+ uma_zfree(unp_zone, unp);
+ if (vp) {
+ int vfslocked;
+
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+ vrele(vp);
+ VFS_UNLOCK_GIANT(vfslocked);
+ }
+ if (local_unp_rights)
+ taskqueue_enqueue(taskqueue_thread, &unp_gc_task);
}
static int
@@ -302,41 +521,45 @@
{
struct unpcb *unp;
struct socket *so2;
+ u_int mbcnt, sbcc;
u_long newhiwat;
unp = sotounpcb(so);
KASSERT(unp != NULL, ("uipc_rcvd: unp == NULL"));
- UNP_LOCK();
switch (so->so_type) {
case SOCK_DGRAM:
panic("uipc_rcvd DGRAM?");
/*NOTREACHED*/
case SOCK_STREAM:
- if (unp->unp_conn == NULL)
+ /*
+ * Adjust backpressure on sender and wakeup any waiting to
+ * write.
+ */
+ SOCKBUF_LOCK(&so->so_rcv);
+ mbcnt = so->so_rcv.sb_mbcnt;
+ sbcc = so->so_rcv.sb_cc;
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ UNP_LOCK();
+ if (unp->unp_conn == NULL) {
+ UNP_UNLOCK();
break;
+ }
so2 = unp->unp_conn->unp_socket;
SOCKBUF_LOCK(&so2->so_snd);
- SOCKBUF_LOCK(&so->so_rcv);
- /*
- * Adjust backpressure on sender
- * and wakeup any waiting to write.
- */
- so2->so_snd.sb_mbmax += unp->unp_mbcnt - so->so_rcv.sb_mbcnt;
- unp->unp_mbcnt = so->so_rcv.sb_mbcnt;
- newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc -
- so->so_rcv.sb_cc;
+ so2->so_snd.sb_mbmax += unp->unp_mbcnt - mbcnt;
+ newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc - sbcc;
(void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat,
newhiwat, RLIM_INFINITY);
- unp->unp_cc = so->so_rcv.sb_cc;
- SOCKBUF_UNLOCK(&so->so_rcv);
sowwakeup_locked(so2);
+ unp->unp_mbcnt = mbcnt;
+ unp->unp_cc = sbcc;
+ UNP_UNLOCK();
break;
default:
panic("uipc_rcvd unknown socktype");
}
- UNP_UNLOCK();
return (0);
}
@@ -346,10 +569,11 @@
uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
struct mbuf *control, struct thread *td)
{
- int error = 0;
- struct unpcb *unp;
+ struct unpcb *unp, *unp2;
struct socket *so2;
+ u_int mbcnt, sbcc;
u_long newhiwat;
+ int error = 0;
unp = sotounpcb(so);
KASSERT(unp != NULL, ("uipc_send: unp == NULL"));
@@ -381,12 +605,24 @@
break;
}
}
- so2 = unp->unp_conn->unp_socket;
+ /*
+ * Because connect() and send() are non-atomic in a sendto()
+ * with a target address, it's possible that the socket will
+ * have disconnected before the send() can run. In that case
+ * return the slightly counter-intuitive but otherwise
+ * correct error that the socket is not connected.
+ */
+ unp2 = unp->unp_conn;
+ if (unp2 == NULL) {
+ error = ENOTCONN;
+ break;
+ }
+ so2 = unp2->unp_socket;
if (unp->unp_addr != NULL)
from = (struct sockaddr *)unp->unp_addr;
else
from = &sun_noname;
- if (unp->unp_conn->unp_flags & UNP_WANTCRED)
+ if (unp2->unp_flags & UNP_WANTCRED)
control = unp_addsockcred(td, control);
SOCKBUF_LOCK(&so2->so_rcv);
if (sbappendaddr_locked(&so2->so_rcv, from, m, control)) {
@@ -403,10 +639,11 @@
}
case SOCK_STREAM:
- /* Connect if not connected yet. */
/*
- * Note: A better implementation would complain
- * if not equal to the peer's address.
+ * Connect if not connected yet.
+ *
+ * Note: A better implementation would complain if not equal
+ * to the peer's address.
*/
if ((so->so_state & SS_ISCONNECTED) == 0) {
if (nam != NULL) {
@@ -419,28 +656,36 @@
}
}
- SOCKBUF_LOCK(&so->so_snd);
+ /* Lockless read. */
if (so->so_snd.sb_state & SBS_CANTSENDMORE) {
- SOCKBUF_UNLOCK(&so->so_snd);
error = EPIPE;
break;
}
- if (unp->unp_conn == NULL)
- panic("uipc_send connected but no connection?");
- so2 = unp->unp_conn->unp_socket;
+ /*
+ * Because connect() and send() are non-atomic in a sendto()
+ * with a target address, it's possible that the socket will
+ * have disconnected before the send() can run. In that case
+ * return the slightly counter-intuitive but otherwise
+ * correct error that the socket is not connected.
+ */
+ unp2 = unp->unp_conn;
+ if (unp2 == NULL) {
+ error = ENOTCONN;
+ break;
+ }
+ so2 = unp2->unp_socket;
SOCKBUF_LOCK(&so2->so_rcv);
- if (unp->unp_conn->unp_flags & UNP_WANTCRED) {
+ if (unp2->unp_flags & UNP_WANTCRED) {
/*
* Credentials are passed only once on
* SOCK_STREAM.
*/
- unp->unp_conn->unp_flags &= ~UNP_WANTCRED;
+ unp2->unp_flags &= ~UNP_WANTCRED;
control = unp_addsockcred(td, control);
}
/*
- * Send to paired receive port, and then reduce
- * send buffer hiwater marks to maintain backpressure.
- * Wake up readers.
+ * Send to paired receive port, and then reduce send buffer
+ * hiwater marks to maintain backpressure. Wake up readers.
*/
if (control != NULL) {
if (sbappendcontrol_locked(&so2->so_rcv, m, control))
@@ -448,16 +693,19 @@
} else {
sbappend_locked(&so2->so_rcv, m);
}
- so->so_snd.sb_mbmax -=
- so2->so_rcv.sb_mbcnt - unp->unp_conn->unp_mbcnt;
- unp->unp_conn->unp_mbcnt = so2->so_rcv.sb_mbcnt;
- newhiwat = so->so_snd.sb_hiwat -
- (so2->so_rcv.sb_cc - unp->unp_conn->unp_cc);
+ mbcnt = so2->so_rcv.sb_mbcnt - unp2->unp_mbcnt;
+ unp2->unp_mbcnt = so2->so_rcv.sb_mbcnt;
+ sbcc = so2->so_rcv.sb_cc;
+ sorwakeup_locked(so2);
+
+ SOCKBUF_LOCK(&so->so_snd);
+ newhiwat = so->so_snd.sb_hiwat - (sbcc - unp2->unp_cc);
(void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat,
newhiwat, RLIM_INFINITY);
+ so->so_snd.sb_mbmax -= mbcnt;
SOCKBUF_UNLOCK(&so->so_snd);
- unp->unp_conn->unp_cc = so2->so_rcv.sb_cc;
- sorwakeup_locked(so2);
+
+ unp2->unp_cc = sbcc;
m = NULL;
break;
@@ -557,9 +805,10 @@
.pru_sense = uipc_sense,
.pru_shutdown = uipc_shutdown,
.pru_sockaddr = uipc_sockaddr,
- .pru_sosend = sosend,
- .pru_soreceive = soreceive,
- .pru_sopoll = sopoll,
+ .pru_sosend = sosend_generic,
+ .pru_soreceive = soreceive_generic,
+ .pru_sopoll = sopoll_generic,
+ .pru_close = uipc_close,
};
int
@@ -644,212 +893,6 @@
return (error);
}
-/*
- * Both send and receive buffers are allocated PIPSIZ bytes of buffering
- * for stream sockets, although the total for sender and receiver is
- * actually only PIPSIZ.
- * Datagram sockets really use the sendspace as the maximum datagram size,
- * and don't really want to reserve the sendspace. Their recvspace should
- * be large enough for at least one max-size datagram plus address.
- */
-#ifndef PIPSIZ
-#define PIPSIZ 8192
-#endif
-static u_long unpst_sendspace = PIPSIZ;
-static u_long unpst_recvspace = PIPSIZ;
-static u_long unpdg_sendspace = 2*1024; /* really max datagram size */
-static u_long unpdg_recvspace = 4*1024;
-
-static int unp_rights; /* file descriptors in flight */
-
-SYSCTL_DECL(_net_local_stream);
-SYSCTL_ULONG(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW,
- &unpst_sendspace, 0, "");
-SYSCTL_ULONG(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW,
- &unpst_recvspace, 0, "");
-SYSCTL_DECL(_net_local_dgram);
-SYSCTL_ULONG(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW,
- &unpdg_sendspace, 0, "");
-SYSCTL_ULONG(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW,
- &unpdg_recvspace, 0, "");
-SYSCTL_DECL(_net_local);
-SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, "");
-
-static int
-unp_attach(struct socket *so)
-{
- struct unpcb *unp;
- int error;
-
- KASSERT(so->so_pcb == NULL, ("unp_attach: so_pcb != NULL"));
- if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
- switch (so->so_type) {
-
- case SOCK_STREAM:
- error = soreserve(so, unpst_sendspace, unpst_recvspace);
- break;
-
- case SOCK_DGRAM:
- error = soreserve(so, unpdg_sendspace, unpdg_recvspace);
- break;
-
- default:
- panic("unp_attach");
- }
- if (error)
- return (error);
- }
- unp = uma_zalloc(unp_zone, M_WAITOK | M_ZERO);
- if (unp == NULL)
- return (ENOBUFS);
- LIST_INIT(&unp->unp_refs);
- unp->unp_socket = so;
- so->so_pcb = unp;
-
- UNP_LOCK();
- unp->unp_gencnt = ++unp_gencnt;
- unp_count++;
- LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead
- : &unp_shead, unp, unp_link);
- UNP_UNLOCK();
-
- return (0);
-}
-
-static void
-unp_detach(struct unpcb *unp)
-{
- struct vnode *vp;
- int local_unp_rights;
-
- UNP_LOCK_ASSERT();
-
- LIST_REMOVE(unp, unp_link);
- unp->unp_gencnt = ++unp_gencnt;
- --unp_count;
- if ((vp = unp->unp_vnode) != NULL) {
- /*
- * XXXRW: should v_socket be frobbed only while holding
- * Giant?
- */
- unp->unp_vnode->v_socket = NULL;
- unp->unp_vnode = NULL;
- }
- if (unp->unp_conn != NULL)
- unp_disconnect(unp);
- while (!LIST_EMPTY(&unp->unp_refs)) {
- struct unpcb *ref = LIST_FIRST(&unp->unp_refs);
- unp_drop(ref, ECONNRESET);
- }
- soisdisconnected(unp->unp_socket);
- unp->unp_socket->so_pcb = NULL;
- local_unp_rights = unp_rights;
- UNP_UNLOCK();
- if (unp->unp_addr != NULL)
- FREE(unp->unp_addr, M_SONAME);
- uma_zfree(unp_zone, unp);
- if (vp) {
- int vfslocked;
-
- vfslocked = VFS_LOCK_GIANT(vp->v_mount);
- vrele(vp);
- VFS_UNLOCK_GIANT(vfslocked);
- }
- if (local_unp_rights)
- taskqueue_enqueue(taskqueue_thread, &unp_gc_task);
-}
-
-static int
-unp_bind(struct unpcb *unp, struct sockaddr *nam, struct thread *td)
-{
- struct sockaddr_un *soun = (struct sockaddr_un *)nam;
- struct vnode *vp;
- struct mount *mp;
- struct vattr vattr;
- int error, namelen;
- struct nameidata nd;
- char *buf;
-
- UNP_LOCK_ASSERT();
-
- /*
- * XXXRW: This test-and-set of unp_vnode is non-atomic; the
- * unlocked read here is fine, but the value of unp_vnode needs
- * to be tested again after we do all the lookups to see if the
- * pcb is still unbound?
- */
- if (unp->unp_vnode != NULL)
- return (EINVAL);
-
- namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path);
- if (namelen <= 0)
- return (EINVAL);
-
- UNP_UNLOCK();
-
- buf = malloc(namelen + 1, M_TEMP, M_WAITOK);
- strlcpy(buf, soun->sun_path, namelen + 1);
-
- mtx_lock(&Giant);
-restart:
- mtx_assert(&Giant, MA_OWNED);
- NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, UIO_SYSSPACE,
- buf, td);
-/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
- error = namei(&nd);
- if (error)
- goto done;
- vp = nd.ni_vp;
- if (vp != NULL || vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
- NDFREE(&nd, NDF_ONLY_PNBUF);
- if (nd.ni_dvp == vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- if (vp != NULL) {
- vrele(vp);
- error = EADDRINUSE;
- goto done;
- }
- error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH);
- if (error)
- goto done;
- goto restart;
- }
- VATTR_NULL(&vattr);
- vattr.va_type = VSOCK;
- vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask);
-#ifdef MAC
- error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
- &vattr);
-#endif
- if (error == 0) {
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
- error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
- }
- NDFREE(&nd, NDF_ONLY_PNBUF);
- vput(nd.ni_dvp);
- if (error) {
- vn_finished_write(mp);
- goto done;
- }
- vp = nd.ni_vp;
- ASSERT_VOP_LOCKED(vp, "unp_bind");
- soun = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK);
- UNP_LOCK();
- vp->v_socket = unp->unp_socket;
- unp->unp_vnode = vp;
- unp->unp_addr = soun;
- UNP_UNLOCK();
- VOP_UNLOCK(vp, 0, td);
- vn_finished_write(mp);
-done:
- mtx_unlock(&Giant);
- free(buf, M_TEMP);
- UNP_LOCK();
- return (error);
-}
-
static int
unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
@@ -870,6 +913,10 @@
if (len <= 0)
return (EINVAL);
strlcpy(buf, soun->sun_path, len + 1);
+ if (unp->unp_flags & UNP_CONNECTING) {
+ UNP_UNLOCK();
+ return (EALREADY);
+ }
UNP_UNLOCK();
sa = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
mtx_lock(&Giant);
@@ -907,10 +954,10 @@
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
if (so2->so_options & SO_ACCEPTCONN) {
/*
- * NB: drop locks here so unp_attach is entered
- * w/o locks; this avoids a recursive lock
- * of the head and holding sleep locks across
- * a (potentially) blocking malloc.
+ * NB: drop locks here so unp_attach is entered w/o
+ * locks; this avoids a recursive lock of the head
+ * and holding sleep locks across a (potentially)
+ * blocking malloc.
*/
UNP_UNLOCK();
so3 = sonewconn(so2, 0);
@@ -932,18 +979,16 @@
/*
* unp_peercred management:
*
- * The connecter's (client's) credentials are copied
- * from its process structure at the time of connect()
- * (which is now).
+ * The connecter's (client's) credentials are copied from its
+ * process structure at the time of connect() (which is now).
*/
cru2x(td->td_ucred, &unp3->unp_peercred);
unp3->unp_flags |= UNP_HAVEPC;
/*
- * The receiver's (server's) credentials are copied
- * from the unp_peercred member of socket on which the
- * former called listen(); unp_listen() cached that
- * process's credentials at that time so we can use
- * them now.
+ * The receiver's (server's) credentials are copied from the
+ * unp_peercred member of socket on which the former called
+ * listen(); unp_listen() cached that process's credentials
+ * at that time so we can use them now.
*/
KASSERT(unp2->unp_flags & UNP_HAVEPCCACHED,
("unp_connect: listener without cached peercred"));
@@ -972,6 +1017,7 @@
mtx_unlock(&Giant);
free(sa, M_SONAME);
UNP_LOCK();
+ unp->unp_flags &= ~UNP_CONNECTING;
return (error);
}
@@ -1039,21 +1085,11 @@
}
}
-#ifdef notdef
-void
-unp_abort(struct unpcb *unp)
-{
-
- unp_detach(unp);
- UNP_UNLOCK_ASSERT();
-}
-#endif
-
/*
- * unp_pcblist() assumes that UNIX domain socket memory is never reclaimed
- * by the zone (UMA_ZONE_NOFREE), and as such potentially stale pointers
- * are safe to reference. It first scans the list of struct unpcb's to
- * generate a pointer list, then it rescans its list one entry at a time to
+ * unp_pcblist() assumes that UNIX domain socket memory is never reclaimed by
+ * the zone (UMA_ZONE_NOFREE), and as such potentially stale pointers are
+ * safe to reference. It first scans the list of struct unpcb's to generate
+ * a pointer list, then it rescans its list one entry at a time to
* externalize and copyout. It checks the generation number to see if a
* struct unpcb has been reused, and will skip it if so.
*/
@@ -1115,7 +1151,7 @@
}
}
UNP_UNLOCK();
- n = i; /* in case we lost some during malloc */
+ n = i; /* In case we lost some during malloc. */
error = 0;
xu = malloc(sizeof(*xu), M_TEMP, M_WAITOK | M_ZERO);
@@ -1144,11 +1180,10 @@
free(xu, M_TEMP);
if (!error) {
/*
- * Give the user an updated idea of our state.
- * If the generation differs from what we told
- * her before, she knows that something happened
- * while we were processing this request, and it
- * might be necessary to retry.
+ * Give the user an updated idea of our state. If the
+ * generation differs from what we told her before, she knows
+ * that something happened while we were processing this
+ * request, and it might be necessary to retry.
*/
xug->xug_gen = unp_gencnt;
xug->xug_sogen = so_gencnt;
@@ -1190,14 +1225,6 @@
unp_disconnect(unp);
}
-#ifdef notdef
-void
-unp_drain(void)
-{
-
-}
-#endif
-
static void
unp_freerights(struct file **rp, int fdcount)
{
@@ -1207,9 +1234,8 @@
for (i = 0; i < fdcount; i++) {
fp = *rp;
/*
- * zero the pointer before calling
- * unp_discard since it may end up
- * in unp_gc()..
+ * Zero the pointer before calling unp_discard since it may
+ * end up in unp_gc()..
*
* XXXRW: This is less true than it used to be.
*/
@@ -1267,10 +1293,10 @@
goto next;
}
/*
- * now change each pointer to an fd in the global
- * table to an integer that is the index to the
- * local fd table entry that we set up to point
- * to the global one we are transferring.
+ * Now change each pointer to an fd in the global
+ * table to an integer that is the index to the local
+ * fd table entry that we set up to point to the
+ * global one we are transferring.
*/
newlen = newfds * sizeof(int);
*controlp = sbcreatecontrol(NULL, newlen,
@@ -1296,7 +1322,8 @@
*fdp++ = f;
}
FILEDESC_UNLOCK(td->td_proc->p_fd);
- } else { /* We can just copy anything else across */
+ } else {
+ /* We can just copy anything else across. */
if (error || controlp == NULL)
goto next;
*controlp = sbcreatecontrol(NULL, datalen,
@@ -1338,6 +1365,7 @@
void
unp_init(void)
{
+
unp_zone = uma_zcreate("unpcb", sizeof(struct unpcb), NULL, NULL,
NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
if (unp_zone == NULL)
@@ -1411,8 +1439,8 @@
case SCM_RIGHTS:
oldfds = datalen / sizeof (int);
/*
- * check that all the FDs passed in refer to legal files
- * If not, reject the entire operation.
+ * Check that all the FDs passed in refer to legal
+ * files. If not, reject the entire operation.
*/
fdp = data;
FILEDESC_LOCK(fdescp);
@@ -1433,8 +1461,8 @@
}
/*
- * Now replace the integer FDs with pointers to
- * the associated global file table entry..
+ * Now replace the integer FDs with pointers to the
+ * associated global file table entry..
*/
newlen = oldfds * sizeof(struct file *);
*controlp = sbcreatecontrol(NULL, newlen,
@@ -1498,8 +1526,9 @@
struct mbuf *
unp_addsockcred(struct thread *td, struct mbuf *control)
{
- struct mbuf *m, *n;
+ struct mbuf *m, *n, *n_prev;
struct sockcred *sc;
+ const struct cmsghdr *cm;
int ngroups;
int i;
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list