Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Add {send,recv}mmsg from Linux
details: https://anonhg.NetBSD.org/src/rev/83e54cd667a2
branches: trunk
changeset: 779843:83e54cd667a2
user: christos <christos%NetBSD.org@localhost>
date: Fri Jun 22 18:26:35 2012 +0000
description:
Add {send,recv}mmsg from Linux
diffstat:
sys/kern/syscalls.master | 14 +-
sys/kern/uipc_syscalls.c | 226 ++++++++++++++++++++++++++++++++++++++++++----
sys/sys/param.h | 4 +-
sys/sys/socket.h | 15 ++-
4 files changed, 231 insertions(+), 28 deletions(-)
diffs (truncated from 384 to 300 lines):
diff -r b3ca95d2b694 -r 83e54cd667a2 sys/kern/syscalls.master
--- a/sys/kern/syscalls.master Fri Jun 22 15:09:36 2012 +0000
+++ b/sys/kern/syscalls.master Fri Jun 22 18:26:35 2012 +0000
@@ -1,4 +1,4 @@
- $NetBSD: syscalls.master,v 1.259 2012/05/05 19:37:37 christos Exp $
+ $NetBSD: syscalls.master,v 1.260 2012/06/22 18:26:35 christos Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -930,7 +930,11 @@
473 STD RUMP { int|sys||__quotactl(const char *path, \
struct quotactl_args *args); }
474 NOERR { int|sys||posix_spawn(pid_t *pid, const char *path, \
- const struct posix_spawn_file_actions *file_actions, \
- const struct posix_spawnattr *attrp, \
- char *const *argv, char *const *envp); }
-
+ const struct posix_spawn_file_actions *file_actions, \
+ const struct posix_spawnattr *attrp, \
+ char *const *argv, char *const *envp); }
+475 STD { int|sys||recvmmsg(int s, struct mmsghdr *mmsg, \
+ unsigned int vlen, unsigned int flags, \
+ struct timespec *timeout); }
+476 STD { int|sys||sendmmsg(int s, struct mmsghdr *mmsg, \
+ unsigned int vlen, unsigned int flags); }
diff -r b3ca95d2b694 -r 83e54cd667a2 sys/kern/uipc_syscalls.c
--- a/sys/kern/uipc_syscalls.c Fri Jun 22 15:09:36 2012 +0000
+++ b/sys/kern/uipc_syscalls.c Fri Jun 22 18:26:35 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_syscalls.c,v 1.154 2012/01/25 16:56:13 christos Exp $ */
+/* $NetBSD: uipc_syscalls.c,v 1.155 2012/06/22 18:26:35 christos Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.154 2012/01/25 16:56:13 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.155 2012/06/22 18:26:35 christos Exp $");
#include "opt_pipe.h"
@@ -529,14 +529,13 @@
return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
}
-int
-do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
- register_t *retsize)
+static int
+do_sys_sendmsg_so(struct lwp *l, int s, struct socket *so, file_t *fp,
+ struct msghdr *mp, int flags, register_t *retsize)
{
+
struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
struct mbuf *to, *control;
- struct socket *so;
- file_t *fp;
struct uio auio;
size_t len, iovsz;
int i, error;
@@ -610,9 +609,6 @@
memcpy(ktriov, auio.uio_iov, iovsz);
}
- if ((error = fd_getsock1(s, &so, &fp)) != 0)
- goto bad;
-
if (mp->msg_name)
MCLAIM(to, so->so_mowner);
if (mp->msg_control)
@@ -623,8 +619,6 @@
/* Protocol is responsible for freeing 'control' */
control = NULL;
- fd_putfile(s);
-
if (error) {
if (auio.uio_resid != len && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
@@ -656,6 +650,21 @@
}
int
+do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
+ register_t *retsize)
+{
+ int error;
+ struct socket *so;
+ file_t *fp;
+
+ if ((error = fd_getsock1(s, &so, &fp)) != 0)
+ return error;
+ error = do_sys_sendmsg_so(l, s, so, fp, mp, flags, retsize);
+ fd_putfile(s);
+ return error;
+}
+
+int
sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, register_t *retval)
{
/* {
@@ -729,6 +738,68 @@
return (error);
}
+int
+sys_sendmmsg(struct lwp *l, const struct sys_sendmmsg_args *uap,
+ register_t *retval)
+{
+ /* {
+ syscallarg(int) s;
+ syscallarg(struct mmsghdr *) mmsg;
+ syscallarg(unsigned int) vlen;
+ syscallarg(unsigned int) flags;
+ } */
+ struct mmsghdr mmsg;
+ struct socket *so;
+ file_t *fp;
+ struct msghdr *msg = &mmsg.msg_hdr;
+ int error, s;
+ unsigned int vlen, flags, dg;
+
+ s = SCARG(uap, s);
+ if ((error = fd_getsock1(s, &so, &fp)) != 0)
+ return error;
+
+ vlen = SCARG(uap, vlen);
+ if (vlen > 1024)
+ vlen = 1024;
+
+ flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
+
+ for (dg = 0; dg < vlen;) {
+ error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
+ if (error)
+ break;
+
+ msg->msg_flags = flags;
+
+ error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval);
+ if (error)
+ break;
+
+ ktrkuser("msghdr", msg, sizeof *msg);
+ mmsg.msg_len = *retval;
+ error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
+ if (error)
+ break;
+ dg++;
+
+ }
+
+ *retval = dg;
+ if (error)
+ so->so_error = error;
+
+ fd_putfile(s);
+
+ /*
+ * If we succeeded at least once, return 0, hopefully so->so_error
+ * will catch it next time.
+ */
+ if (dg)
+ return 0;
+ return error;
+}
+
/*
* Adjust for a truncated SCM_RIGHTS control message.
* This means closing any file descriptors that aren't present
@@ -822,12 +893,11 @@
return error;
}
-int
-do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
- struct mbuf **control, register_t *retsize)
+static int
+do_sys_recvmsg_so(struct lwp *l, int s, struct socket *so, struct msghdr *mp,
+ struct mbuf **from, struct mbuf **control, register_t *retsize)
{
struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov;
- struct socket *so;
struct uio auio;
size_t len, iovsz;
int i, error;
@@ -838,9 +908,6 @@
if (control != NULL)
*control = NULL;
- if ((error = fd_getsock(s, &so)) != 0)
- return (error);
-
iovsz = mp->msg_iovlen * sizeof(struct iovec);
if (mp->msg_flags & MSG_IOVUSRSPACE) {
@@ -913,11 +980,130 @@
out:
if (iov != aiov)
kmem_free(iov, iovsz);
- fd_putfile(s);
return (error);
}
+int
+do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
+ struct mbuf **control, register_t *retsize)
+{
+ int error;
+ struct socket *so;
+
+ if ((error = fd_getsock(s, &so)) != 0)
+ return error;
+ error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize);
+ fd_putfile(s);
+ return error;
+}
+
+int
+sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap,
+ register_t *retval)
+{
+ /* {
+ syscallarg(int) s;
+ syscallarg(struct mmsghdr *) mmsg;
+ syscallarg(unsigned int) vlen;
+ syscallarg(unsigned int) flags;
+ syscallarg(struct timespec *) timeout;
+ } */
+ struct mmsghdr mmsg;
+ struct socket *so;
+ struct msghdr *msg = &mmsg.msg_hdr;
+ int error, s;
+ struct mbuf *from, *control;
+ struct timespec ts, now;
+ unsigned int vlen, flags, dg;
+
+ if (SCARG(uap, timeout)) {
+ if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0)
+ return error;
+ getnanotime(&now);
+ timespecadd(&now, &ts, &ts);
+ }
+
+ s = SCARG(uap, s);
+ if ((error = fd_getsock(s, &so)) != 0)
+ return error;
+
+ vlen = SCARG(uap, vlen);
+ if (vlen > 1024)
+ vlen = 1024;
+
+ from = NULL;
+ flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
+
+ for (dg = 0; dg < vlen;) {
+ error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg));
+ if (error)
+ break;
+
+ msg->msg_flags = flags & ~MSG_WAITFORONE;
+
+ if (from != NULL) {
+ m_free(from);
+ from = NULL;
+ }
+
+ error = do_sys_recvmsg_so(l, s, so, msg, &from,
+ msg->msg_control != NULL ? &control : NULL, retval);
+ if (error)
+ break;
+
+ if (msg->msg_control != NULL)
+ error = copyout_msg_control(l, msg, control);
+ if (error)
+ break;
+
+ error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0,
+ from);
+ if (error)
+ break;
+
+ ktrkuser("msghdr", msg, sizeof *msg);
+ mmsg.msg_len = *retval;
+
+ error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg));
+ if (error)
+ break;
+
+ dg++;
+ if (msg->msg_flags & MSG_OOB)
+ break;
+
+ if (SCARG(uap, timeout)) {
+ getnanotime(&now);
+ timespecsub(&now, &ts, &now);
+ if (now.tv_sec > 0)
Home |
Main Index |
Thread Index |
Old Index