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