Splitting up sendit
David Malone
dwmalone at maths.tcd.ie
Mon Mar 31 13:48:49 PST 2003
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);
More information about the freebsd-arch
mailing list