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