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