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 */
 

Reply via email to