summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_syscall.c15
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_socket.h10
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_syscalls.h3
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_socket.c163
4 files changed, 182 insertions, 9 deletions
diff --git a/usr/src/uts/common/brand/lx/os/lx_syscall.c b/usr/src/uts/common/brand/lx/os/lx_syscall.c
index ed0ccc4cb7..5a8f9322a0 100644
--- a/usr/src/uts/common/brand/lx/os/lx_syscall.c
+++ b/usr/src/uts/common/brand/lx/os/lx_syscall.c
@@ -23,6 +23,7 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2018 Joyent, Inc.
+ * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
*/
#include <sys/kmem.h>
@@ -564,7 +565,7 @@ lx_sysent_t lx_sysent32[] = {
{"access", lx_access, 0, 2}, /* 33 */
{"nice", lx_nice, 0, 1}, /* 34 */
{"ftime", NULL, NOSYS_OBSOLETE, 0}, /* 35 */
- {"sync", lx_sync, 0, 0}, /* 36 */
+ {"sync", lx_sync, 0, 0}, /* 36 */
{"kill", lx_kill, 0, 2}, /* 37 */
{"rename", lx_rename, 0, 2}, /* 38 */
{"mkdir", lx_mkdir, 0, 2}, /* 39 */
@@ -607,7 +608,7 @@ lx_sysent_t lx_sysent32[] = {
{"getrlimit", lx_oldgetrlimit, 0, 2}, /* 76 */
{"getrusage", lx_getrusage, 0, 2}, /* 77 */
{"gettimeofday", lx_gettimeofday, 0, 2}, /* 78 */
- {"settimeofday", NULL, 0, 2}, /* 79 */
+ {"settimeofday", NULL, 0, 2}, /* 79 */
{"getgroups16", NULL, 0, 2}, /* 80 */
{"setgroups16", NULL, 0, 2}, /* 81 */
{"select", NULL, NOSYS_OBSOLETE, 0}, /* 82 */
@@ -869,7 +870,7 @@ lx_sysent_t lx_sysent32[] = {
{"pwritev", lx_pwritev32, 0, 5}, /* 334 */
{"rt_tgsigqueueinfo", NULL, 0, 4}, /* 335 */
{"perf_event_open", NULL, NOSYS_NULL, 0}, /* 336 */
- {"recvmmsg", NULL, NOSYS_NULL, 0}, /* 337 */
+ {"recvmmsg", lx_recvmmsg, 0, 5}, /* 337 */
{"fanotify_init", NULL, NOSYS_NULL, 0}, /* 338 */
{"fanotify_mark", NULL, NOSYS_NULL, 0}, /* 339 */
{"prlimit64", lx_prlimit64, 0, 4}, /* 340 */
@@ -877,7 +878,7 @@ lx_sysent_t lx_sysent32[] = {
{"open_by_handle_at", NULL, NOSYS_NULL, 0}, /* 342 */
{"clock_adjtime", NULL, NOSYS_NULL, 0}, /* 343 */
{"syncfs", lx_syncfs, 0, 1}, /* 344 */
- {"sendmmsg", NULL, NOSYS_NULL, 0}, /* 345 */
+ {"sendmmsg", lx_sendmmsg, 0, 4}, /* 345 */
{"setns", NULL, NOSYS_NULL, 0}, /* 346 */
{"process_vm_readv", NULL, NOSYS_NULL, 0}, /* 347 */
{"process_vm_writev", NULL, NOSYS_NULL, 0}, /* 348 */
@@ -1196,9 +1197,9 @@ lx_sysent_t lx_sysent64[] = {
{"inotify_init1", NULL, 0, 1}, /* 294 */
{"preadv", lx_preadv, 0, 4}, /* 295 */
{"pwritev", lx_pwritev, 0, 4}, /* 296 */
- {"rt_tgsigqueueinfo", NULL, 0, 4}, /* 297 */
+ {"rt_tgsigqueueinfo", NULL, 0, 4}, /* 297 */
{"perf_event_open", NULL, NOSYS_NULL, 0}, /* 298 */
- {"recvmmsg", NULL, NOSYS_NULL, 0}, /* 299 */
+ {"recvmmsg", lx_recvmmsg, 0, 5}, /* 299 */
{"fanotify_init", NULL, NOSYS_NULL, 0}, /* 300 */
{"fanotify_mark", NULL, NOSYS_NULL, 0}, /* 301 */
{"prlimit64", lx_prlimit64, 0, 4}, /* 302 */
@@ -1206,7 +1207,7 @@ lx_sysent_t lx_sysent64[] = {
{"open_by_handle_at", NULL, NOSYS_NULL, 0}, /* 304 */
{"clock_adjtime", NULL, NOSYS_NULL, 0}, /* 305 */
{"syncfs", lx_syncfs, 0, 1}, /* 306 */
- {"sendmmsg", NULL, NOSYS_NULL, 0}, /* 307 */
+ {"sendmmsg", lx_sendmmsg, 0, 4}, /* 307 */
{"setns", NULL, NOSYS_NULL, 0}, /* 309 */
{"getcpu", lx_getcpu, 0, 3}, /* 309 */
{"process_vm_readv", NULL, NOSYS_NULL, 0}, /* 310 */
diff --git a/usr/src/uts/common/brand/lx/sys/lx_socket.h b/usr/src/uts/common/brand/lx/sys/lx_socket.h
index eb9826eebe..99489e4d13 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_socket.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_socket.h
@@ -22,6 +22,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2016 Joyent, Inc.
+ * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
*/
#ifndef _SYS_LX_SOCKET_H
@@ -403,6 +404,10 @@ typedef struct lx_msghdr {
int msg_flags; /* flags on received message */
} lx_msghdr_t;
+typedef struct lx_mmsghdr {
+ lx_msghdr_t msg_hdr; /* message header */
+ unsigned int msg_len; /* no. of bytes transmitted */
+} lx_mmsghdr_t;
#if defined(_LP64)
@@ -416,6 +421,11 @@ typedef struct lx_msghdr32 {
int32_t msg_flags; /* flags on received message */
} lx_msghdr32_t;
+typedef struct lx_mmsghdr32 {
+ lx_msghdr32_t msg_hdr; /* message header */
+ unsigned int msg_len; /* no. of bytes transmitted */
+} lx_mmsghdr32_t;
+
#endif
typedef struct lx_sockaddr_in6 {
diff --git a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
index ad6a0e13b4..78fbf6e0a8 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
@@ -23,6 +23,7 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2018 Joyent, Inc.
+ * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
*/
#ifndef _SYS_LINUX_SYSCALLS_H
@@ -191,6 +192,7 @@ extern long lx_readv();
extern long lx_reboot();
extern long lx_recv();
extern long lx_recvmsg();
+extern long lx_recvmmsg();
extern long lx_recvfrom();
extern long lx_rename();
extern long lx_renameat();
@@ -209,6 +211,7 @@ extern long lx_sched_yield();
extern long lx_select();
extern long lx_send();
extern long lx_sendmsg();
+extern long lx_sendmmsg();
extern long lx_sendto();
extern long lx_set_robust_list();
extern long lx_set_thread_area();
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_socket.c b/usr/src/uts/common/brand/lx/syscall/lx_socket.c
index e961abdac1..a95e220ea2 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_socket.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_socket.c
@@ -23,6 +23,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2018 Joyent, Inc.
+ * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
*/
#include <sys/errno.h>
@@ -2103,6 +2104,120 @@ noiov:
return (res);
}
+long
+lx_recvmmsg(int sock, void *msg, uint_t vlen, int flags, timespec_t *timeoutp)
+{
+ hrtime_t deadline = 0;
+ uint_t rcvd = 0;
+ long ret = 0;
+ boolean_t waitforone;
+
+ waitforone = ((flags & LX_MSG_WAITFORONE) != 0);
+ flags &= ~LX_MSG_WAITFORONE;
+
+ /*
+ * We want to limit the work that a thread calling recvmmsg() can
+ * perform in the kernel so that it cannot accrue too high a priority.
+ * Artificially capping vlen means that the thread will return to
+ * userspace after processing at most IOV_MAX messages, giving the
+ * system a chance to reset the thread priority.
+ *
+ * Linux does not cap vlen here and recvmmsg() is expected to return
+ * once vlen messages have been received, a timeout occurs, or if an
+ * error is encountered; the artificial cap adds another case.
+ *
+ * It is possible that returning "early" in this emulation will
+ * cause problems with some applications however a properly written
+ * recvmmsg() consumer should consume only the received datagrams
+ * and try again if it wants more. This may need revisiting in the
+ * future.
+ */
+ if (vlen > IOV_MAX)
+ vlen = IOV_MAX;
+
+ if (timeoutp != NULL) {
+ timespec_t timeout;
+ uhrtime_t utime = (uhrtime_t)gethrtime();
+
+ if (get_udatamodel() == DATAMODEL_NATIVE) {
+ if (copyin(timeoutp, &timeout, sizeof (timestruc_t)))
+ return (set_errno(EFAULT));
+ } else {
+ timestruc32_t timeout32;
+ if (copyin(timeoutp, &timeout32,
+ sizeof (timestruc32_t)))
+ return (set_errno(EFAULT));
+ timeout.tv_sec = (time_t)timeout32.tv_sec;
+ timeout.tv_nsec = timeout32.tv_nsec;
+ }
+
+ if (itimerspecfix(&timeout))
+ return (set_errno(EINVAL));
+
+ /*
+ * Make sure that deadline will not overflow. itimerspecfix()
+ * has already checked for negative values and too big a value
+ * in tv_nsec
+ */
+ if (timeout.tv_sec >= HRTIME_MAX / NANOSEC)
+ return (set_errno(EINVAL));
+
+ utime += timeout.tv_sec * NANOSEC;
+ utime += timeout.tv_nsec;
+
+ if (utime > HRTIME_MAX)
+ return (set_errno(EINVAL));
+
+ deadline = (hrtime_t)utime;
+ }
+
+ for (rcvd = 0; rcvd < vlen; rcvd++) {
+ uint_t *ptr;
+
+ if (get_udatamodel() == DATAMODEL_NATIVE) {
+ lx_mmsghdr_t *hdr = (lx_mmsghdr_t *)msg;
+ hdr += rcvd;
+ ret = lx_recvmsg(sock, (lx_msghdr_t *)hdr, flags);
+ ptr = &hdr->msg_len;
+ } else {
+ lx_mmsghdr32_t *hdr = (lx_mmsghdr32_t *)msg;
+ hdr += rcvd;
+ ret = lx_recvmsg(sock, (lx_msghdr32_t *)hdr, flags);
+ ptr = &hdr->msg_len;
+ }
+ if (ttolwp(curthread)->lwp_errno != 0)
+ break;
+ copyout(&ret, ptr, sizeof (*ptr));
+ /*
+ * If MSG_WAITFORONE is set, set MSG_DONTWAIT after the
+ * first packet has been received.
+ */
+ if (waitforone) {
+ flags |= LX_MSG_DONTWAIT;
+ waitforone = B_FALSE;
+ }
+ /*
+ * The Linux man page documents the timeout option as
+ * only being checked after each datagram is received.
+ * The man page does not document ETIMEDOUT as a return
+ * code so we do not set an errno.
+ */
+ if (deadline > 0 && gethrtime() >= deadline)
+ break;
+ }
+
+ if (rcvd > 0) {
+ /*
+ * Any error code is deliberately discarded if any message
+ * was successfully received.
+ */
+ ttolwp(curthread)->lwp_errno = 0;
+ return (rcvd);
+ }
+
+ return (ret);
+}
+
/*
* Custom version of socket_sendmsg for error-handling overrides.
*/
@@ -2442,6 +2557,50 @@ lx_sendmsg(int sock, void *msg, int flags)
return (res);
}
+long
+lx_sendmmsg(int sock, void *msg, uint_t vlen, int flags)
+{
+ long ret = 0;
+ uint_t sent = 0;
+
+ /*
+ * Linux caps vlen to UIO_MAXIOV (1024).
+ */
+ if (vlen > IOV_MAX)
+ vlen = IOV_MAX;
+
+ if (get_udatamodel() == DATAMODEL_NATIVE) {
+ lx_mmsghdr_t *hdr = msg;
+
+ for (sent = 0; sent < vlen; sent++, hdr++) {
+ ret = lx_sendmsg(sock, (lx_msghdr_t *)hdr, flags);
+ if (ttolwp(curthread)->lwp_errno != 0)
+ break;
+ copyout(&ret, &hdr->msg_len, sizeof (hdr->msg_len));
+ }
+ } else {
+ lx_mmsghdr32_t *hdr = msg;
+
+ for (sent = 0; sent < vlen; sent++, hdr++) {
+ ret = lx_sendmsg(sock, (lx_msghdr32_t *)hdr, flags);
+ if (ttolwp(curthread)->lwp_errno != 0)
+ break;
+ copyout(&ret, &hdr->msg_len, sizeof (hdr->msg_len));
+ }
+ }
+
+ if (sent > 0) {
+ /*
+ * Any error code is deliberately discarded if any message
+ * was successfully sent.
+ */
+ ttolwp(curthread)->lwp_errno = 0;
+ return (sent);
+ }
+
+ return (ret);
+}
+
/*
* Linux socket option type definitions
*
@@ -4318,8 +4477,8 @@ static struct {
lx_sendmsg, 3, /* sendmsg */
lx_recvmsg, 3, /* recvmsg */
lx_accept4, 4, /* accept4 */
- NULL, 5, /* recvmmsg */
- NULL, 4 /* sendmmsg */
+ lx_recvmmsg, 5, /* recvmmsg */
+ lx_sendmmsg, 4 /* sendmmsg */
};
long