Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 31 Mar 2003 22:48:44 +0100
From:      David Malone <dwmalone@maths.tcd.ie>
To:        arch@freebsd.org
Cc:        iedowse@freebsd.org
Subject:   Splitting up sendit
Message-ID:  <200303312248.aa21293@salmon.maths.tcd.ie>

next in thread | raw e-mail | index | archive | help
I wonder if anyone has any comments on this patch. It splits
sendit into a part which just does the copyin of arguments and then
calls a new function, kern_sendit which does the real work. The
point of this is to allow the linux emulation code to avoid using
the stackgap for send, sendto and sendmsg.

The patch also moves the grabbing of giant into kern_sendit 'cos,
as I understand it, neither copyin or the allocation of mbufs
requires giant.

	David.



Index: sys/kern/uipc_syscalls.c
===================================================================
RCS file: /cvs/FreeBSD-CVS/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.145
diff -u -r1.145 uipc_syscalls.c
--- sys/kern/uipc_syscalls.c	31 Mar 2003 06:25:42 -0000	1.145
+++ sys/kern/uipc_syscalls.c	31 Mar 2003 20:38:45 -0000
@@ -619,47 +619,18 @@
 	register struct msghdr *mp;
 	int flags;
 {
-	struct uio auio;
-	register struct iovec *iov;
-	register int i;
 	struct mbuf *control;
-	struct sockaddr *to = NULL;
-	int len, error;
-	struct socket *so;
-#ifdef KTRACE
-	struct iovec *ktriov = NULL;
-	struct uio ktruio;
-	int iovlen;
-#endif
-
-	if ((error = fgetsock(td, s, &so, NULL)) != 0)
-		return (error);
-
-#ifdef MAC
-	error = mac_check_socket_send(td->td_ucred, so);
-	if (error)
-		goto bad;
-#endif
+	struct sockaddr *to;
+	int error;
 
-	auio.uio_iov = mp->msg_iov;
-	auio.uio_iovcnt = mp->msg_iovlen;
-	auio.uio_segflg = UIO_USERSPACE;
-	auio.uio_rw = UIO_WRITE;
-	auio.uio_td = td;
-	auio.uio_offset = 0;			/* XXX */
-	auio.uio_resid = 0;
-	iov = mp->msg_iov;
-	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
-		if ((auio.uio_resid += iov->iov_len) < 0) {
-			error = EINVAL;
-			goto bad;
-		}
-	}
-	if (mp->msg_name) {
+	if (mp->msg_name != NULL) {
 		error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
 		if (error)
-			goto bad;
-	}
+			return error;
+		mp->msg_name = to;
+	} else
+		to = NULL;
+
 	if (mp->msg_control) {
 		if (mp->msg_controllen < sizeof(struct cmsghdr)
 #ifdef COMPAT_OLDSOCK
@@ -690,7 +661,59 @@
 		}
 #endif
 	} else {
-		control = 0;
+		control = NULL;
+	}
+
+	error = kern_sendit(td, s, mp, flags, control);
+
+bad:
+	if (to)
+		FREE(to, M_SONAME);
+	return (error);
+}
+
+int
+kern_sendit(td, s, mp, flags, control)
+	struct thread *td;
+	int s;
+	struct msghdr *mp;
+	int flags;
+	struct mbuf *control;
+{
+	struct uio auio;
+	struct iovec *iov;
+	struct socket *so;
+	int i;
+	int len, error;
+#ifdef KTRACE
+	struct iovec *ktriov = NULL;
+	struct uio ktruio;
+	int iovlen;
+#endif
+
+	mtx_lock(&Giant);
+	if ((error = fgetsock(td, s, &so, NULL)) != 0)
+		goto bad2;
+
+#ifdef MAC
+	error = mac_check_socket_send(td->td_ucred, so);
+	if (error)
+		goto bad;
+#endif
+
+	auio.uio_iov = mp->msg_iov;
+	auio.uio_iovcnt = mp->msg_iovlen;
+	auio.uio_segflg = UIO_USERSPACE;
+	auio.uio_rw = UIO_WRITE;
+	auio.uio_td = td;
+	auio.uio_offset = 0;			/* XXX */
+	auio.uio_resid = 0;
+	iov = mp->msg_iov;
+	for (i = 0; i < mp->msg_iovlen; i++, iov++) {
+		if ((auio.uio_resid += iov->iov_len) < 0) {
+			error = EINVAL;
+			goto bad;
+		}
 	}
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_GENIO)) {
@@ -701,8 +724,9 @@
 	}
 #endif
 	len = auio.uio_resid;
-	error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control,
-						     flags, td);
+	error = so->so_proto->pr_usrreqs->pru_sosend(so, mp->msg_name, &auio,
+	    0, control, flags, td);
+
 	if (error) {
 		if (auio.uio_resid != len && (error == ERESTART ||
 		    error == EINTR || error == EWOULDBLOCK))
@@ -728,8 +752,8 @@
 #endif
 bad:
 	fputsock(so);
-	if (to)
-		FREE(to, M_SONAME);
+bad2:
+	mtx_unlock(&Giant);
 	return (error);
 }
 
@@ -762,9 +786,7 @@
 #endif
 	aiov.iov_base = uap->buf;
 	aiov.iov_len = uap->len;
-	mtx_lock(&Giant);
 	error = sendit(td, uap->s, &msg, uap->flags);
-	mtx_unlock(&Giant);
 	return (error);
 }
 
@@ -794,9 +816,7 @@
 	aiov.iov_len = uap->len;
 	msg.msg_control = 0;
 	msg.msg_flags = 0;
-	mtx_lock(&Giant);
 	error = sendit(td, uap->s, &msg, uap->flags);
-	mtx_unlock(&Giant);
 	return (error);
 }
 
@@ -816,7 +836,6 @@
 	struct iovec aiov[UIO_SMALLIOV], *iov;
 	int error;
 
-	mtx_lock(&Giant);
 	error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
 	if (error)
 		goto done2;
@@ -842,7 +861,6 @@
 	if (iov != aiov)
 		FREE(iov, M_IOV);
 done2:
-	mtx_unlock(&Giant);
 	return (error);
 }
 #endif
@@ -863,7 +881,6 @@
 	struct iovec aiov[UIO_SMALLIOV], *iov;
 	int error;
 
-	mtx_lock(&Giant);
 	error = copyin(uap->msg, &msg, sizeof (msg));
 	if (error)
 		goto done2;
@@ -891,7 +908,6 @@
 	if (iov != aiov)
 		FREE(iov, M_IOV);
 done2:
-	mtx_unlock(&Giant);
 	return (error);
 }
 
Index: sys/sys/syscallsubr.h
===================================================================
RCS file: /cvs/FreeBSD-CVS/src/sys/sys/syscallsubr.h,v
retrieving revision 1.6
diff -u -r1.6 syscallsubr.h
--- sys/sys/syscallsubr.h	3 Feb 2003 17:36:52 -0000	1.6
+++ sys/sys/syscallsubr.h	8 Feb 2003 20:47:07 -0000
@@ -32,6 +32,8 @@
 #include <sys/uio.h>
 
 struct sockaddr;
+struct msghdr;
+struct mbuf;
 
 int	kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg,
 	    u_int buflen);
@@ -70,6 +72,8 @@
 int	kern_rmdir(struct thread *td, char *path, enum uio_seg pathseg);
 int	kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
 	    fd_set *fd_ex, struct timeval *tvp);
+int	kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
+	    struct mbuf *control);
 int	kern_sigaction(struct thread *td, int sig, struct sigaction *act,
 	    struct sigaction *oact, int flags);
 int	kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200303312248.aa21293>