Add {send,recv}mmsg from Linux

This commit is contained in:
christos 2012-06-22 18:26:35 +00:00
parent bda667f3a1
commit 7bee3146e4
4 changed files with 231 additions and 28 deletions

View File

@ -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 ; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@ -930,7 +930,11 @@
473 STD RUMP { int|sys||__quotactl(const char *path, \ 473 STD RUMP { int|sys||__quotactl(const char *path, \
struct quotactl_args *args); } struct quotactl_args *args); }
474 NOERR { int|sys||posix_spawn(pid_t *pid, const char *path, \ 474 NOERR { int|sys||posix_spawn(pid_t *pid, const char *path, \
const struct posix_spawn_file_actions *file_actions, \ const struct posix_spawn_file_actions *file_actions, \
const struct posix_spawnattr *attrp, \ const struct posix_spawnattr *attrp, \
char *const *argv, char *const *envp); } 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); }

View File

@ -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. * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -61,7 +61,7 @@
*/ */
#include <sys/cdefs.h> #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" #include "opt_pipe.h"
@ -529,14 +529,13 @@ sys_sendmsg(struct lwp *l, const struct sys_sendmsg_args *uap, register_t *retva
return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval); return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
} }
int static int
do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags, do_sys_sendmsg_so(struct lwp *l, int s, struct socket *so, file_t *fp,
register_t *retsize) struct msghdr *mp, int flags, register_t *retsize)
{ {
struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL; struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov = NULL;
struct mbuf *to, *control; struct mbuf *to, *control;
struct socket *so;
file_t *fp;
struct uio auio; struct uio auio;
size_t len, iovsz; size_t len, iovsz;
int i, error; int i, error;
@ -610,9 +609,6 @@ do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
memcpy(ktriov, auio.uio_iov, iovsz); memcpy(ktriov, auio.uio_iov, iovsz);
} }
if ((error = fd_getsock1(s, &so, &fp)) != 0)
goto bad;
if (mp->msg_name) if (mp->msg_name)
MCLAIM(to, so->so_mowner); MCLAIM(to, so->so_mowner);
if (mp->msg_control) if (mp->msg_control)
@ -623,8 +619,6 @@ do_sys_sendmsg(struct lwp *l, int s, struct msghdr *mp, int flags,
/* Protocol is responsible for freeing 'control' */ /* Protocol is responsible for freeing 'control' */
control = NULL; control = NULL;
fd_putfile(s);
if (error) { if (error) {
if (auio.uio_resid != len && (error == ERESTART || if (auio.uio_resid != len && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK)) error == EINTR || error == EWOULDBLOCK))
@ -655,6 +649,21 @@ bad:
return (error); return (error);
} }
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 int
sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, register_t *retval) 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 sys_recvmsg_args *uap, register_t *retva
return (error); 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. * Adjust for a truncated SCM_RIGHTS control message.
* This means closing any file descriptors that aren't present * This means closing any file descriptors that aren't present
@ -822,12 +893,11 @@ copyout_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
return error; return error;
} }
int static int
do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from, do_sys_recvmsg_so(struct lwp *l, int s, struct socket *so, struct msghdr *mp,
struct mbuf **control, register_t *retsize) struct mbuf **from, struct mbuf **control, register_t *retsize)
{ {
struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov; struct iovec aiov[UIO_SMALLIOV], *iov = aiov, *tiov, *ktriov;
struct socket *so;
struct uio auio; struct uio auio;
size_t len, iovsz; size_t len, iovsz;
int i, error; int i, error;
@ -838,9 +908,6 @@ do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
if (control != NULL) if (control != NULL)
*control = NULL; *control = NULL;
if ((error = fd_getsock(s, &so)) != 0)
return (error);
iovsz = mp->msg_iovlen * sizeof(struct iovec); iovsz = mp->msg_iovlen * sizeof(struct iovec);
if (mp->msg_flags & MSG_IOVUSRSPACE) { if (mp->msg_flags & MSG_IOVUSRSPACE) {
@ -913,11 +980,130 @@ do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from,
out: out:
if (iov != aiov) if (iov != aiov)
kmem_free(iov, iovsz); kmem_free(iov, iovsz);
fd_putfile(s);
return (error); 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 */ /* ARGSUSED */
int int
sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval) sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval)

View File

@ -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 * Copyright (c) 1982, 1986, 1989, 1993
@ -63,7 +63,7 @@
* 2.99.9 (299000900) * 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) + \ #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__) (m) * 1000000) + (p) * 100) <= __NetBSD_Version__)

View File

@ -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. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -495,6 +495,12 @@ struct msghdr {
#if defined(_NETBSD_SOURCE) #if defined(_NETBSD_SOURCE)
#define MSG_CMSG_CLOEXEC 0x0800 /* close on exec receiving fd */ #define MSG_CMSG_CLOEXEC 0x0800 /* close on exec receiving fd */
#define MSG_NBIO 0x1000 /* use non-blocking I/O */ #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 #endif
/* Extra flags used internally only */ /* Extra flags used internally only */
@ -629,6 +635,13 @@ __RENAME(__socket30)
#endif #endif
; ;
int socketpair(int, int, int, int *); 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 __END_DECLS
#endif /* !_KERNEL */ #endif /* !_KERNEL */