Module Name: src
Committed By: christos
Date: Fri Jun 22 18:26:36 UTC 2012
Modified Files:
src/sys/kern: syscalls.master uipc_syscalls.c
src/sys/sys: param.h socket.h
Log Message:
Add {send,recv}mmsg from Linux
To generate a diff of this commit:
cvs rdiff -u -r1.259 -r1.260 src/sys/kern/syscalls.master
cvs rdiff -u -r1.154 -r1.155 src/sys/kern/uipc_syscalls.c
cvs rdiff -u -r1.415 -r1.416 src/sys/sys/param.h
cvs rdiff -u -r1.106 -r1.107 src/sys/sys/socket.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/syscalls.master
diff -u src/sys/kern/syscalls.master:1.259 src/sys/kern/syscalls.master:1.260
--- src/sys/kern/syscalls.master:1.259 Sat May 5 15:37:37 2012
+++ src/sys/kern/syscalls.master Fri Jun 22 14:26:35 2012
@@ -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); }
Index: src/sys/kern/uipc_syscalls.c
diff -u src/sys/kern/uipc_syscalls.c:1.154 src/sys/kern/uipc_syscalls.c:1.155
--- src/sys/kern/uipc_syscalls.c:1.154 Wed Jan 25 11:56:13 2012
+++ src/sys/kern/uipc_syscalls.c Fri Jun 22 14:26:35 2012
@@ -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 @@ sys_sendmsg(struct lwp *l, const struct
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 @@ do_sys_sendmsg(struct lwp *l, int s, str
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 @@ do_sys_sendmsg(struct lwp *l, int s, str
/* 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 @@ bad:
}
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 @@ sys_recvmsg(struct lwp *l, const struct
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 @@ copyout_msg_control(struct lwp *l, struc
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 @@ do_sys_recvmsg(struct lwp *l, int s, str
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 @@ do_sys_recvmsg(struct lwp *l, int s, str
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)
+ break;
+ }
+
+ if (flags & MSG_WAITFORONE)
+ flags |= MSG_DONTWAIT;
+
+ }
+
+ if (from != NULL)
+ m_free(from);
+
+ *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;
+}
+
/* ARGSUSED */
int
sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval)
Index: src/sys/sys/param.h
diff -u src/sys/sys/param.h:1.415 src/sys/sys/param.h:1.416
--- src/sys/sys/param.h:1.415 Thu May 10 03:48:07 2012
+++ src/sys/sys/param.h Fri Jun 22 14:26:35 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: param.h,v 1.415 2012/05/10 07:48:07 riastradh Exp $ */
+/* $NetBSD: param.h,v 1.416 2012/06/22 18:26:35 christos Exp $ */
/*-
* Copyright (c) 1982, 1986, 1989, 1993
@@ -63,7 +63,7 @@
* 2.99.9 (299000900)
*/
-#define __NetBSD_Version__ 699000700 /* NetBSD 6.99.7 */
+#define __NetBSD_Version__ 699000800 /* NetBSD 6.99.8 */
#define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__)
Index: src/sys/sys/socket.h
diff -u src/sys/sys/socket.h:1.106 src/sys/sys/socket.h:1.107
--- src/sys/sys/socket.h:1.106 Sun Jan 29 13:33:07 2012
+++ src/sys/sys/socket.h Fri Jun 22 14:26:35 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: socket.h,v 1.106 2012/01/29 18:33:07 roy Exp $ */
+/* $NetBSD: socket.h,v 1.107 2012/06/22 18:26:35 christos Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -495,6 +495,12 @@ struct msghdr {
#if defined(_NETBSD_SOURCE)
#define MSG_CMSG_CLOEXEC 0x0800 /* close on exec receiving fd */
#define MSG_NBIO 0x1000 /* use non-blocking I/O */
+#define MSG_WAITFORONE 0x2000 /* recvmmsg() wait for one message */
+
+struct mmsghdr {
+ struct msghdr msg_hdr;
+ unsigned int msg_len;
+};
#endif
/* Extra flags used internally only */
@@ -629,6 +635,13 @@ __RENAME(__socket30)
#endif
;
int socketpair(int, int, int, int *);
+
+#if defined(_NETBSD_SOURCE)
+int sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int);
+struct timespec;
+int recvmmsg(int, struct mmsghdr *, unsigned int, unsigned int,
+ struct timespec *);
+#endif
__END_DECLS
#endif /* !_KERNEL */