summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/lx_brand.c4
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/poll_select.c33
-rw-r--r--usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h1
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_syscall.c4
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_syscalls.h1
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_epoll.c108
6 files changed, 113 insertions, 38 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
index a740349cbd..c8127bac60 100644
--- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
+++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
@@ -1173,7 +1173,7 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_clock_nanosleep, /* 230: clock_nanosleep */
lx_group_exit, /* 231: exit_group */
NULL, /* 232: epoll_wait */
- lx_epoll_ctl, /* 233: epoll_ctl */
+ NULL, /* 233: epoll_ctl */
NULL, /* 234: tgkill */
lx_utimes, /* 235: utimes */
NULL, /* 236: vserver */
@@ -1526,7 +1526,7 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_group_exit, /* 252: group_exit */
NULL, /* 253: lookup_dcookie */
NULL, /* 254: epoll_create */
- lx_epoll_ctl, /* 255: epoll_ctl */
+ NULL, /* 255: epoll_ctl */
NULL, /* 256: epoll_wait */
NULL, /* 257: remap_file_pages */
NULL, /* 258: set_tid_address */
diff --git a/usr/src/lib/brand/lx/lx_brand/common/poll_select.c b/usr/src/lib/brand/lx/lx_brand/common/poll_select.c
index 029c59e4fb..793ff3bba6 100644
--- a/usr/src/lib/brand/lx/lx_brand/common/poll_select.c
+++ b/usr/src/lib/brand/lx/lx_brand/common/poll_select.c
@@ -40,7 +40,6 @@
#include <sys/brand.h>
#include <sys/poll.h>
#include <sys/syscall.h>
-#include <sys/epoll.h>
#include <sys/lx_debug.h>
#include <sys/lx_poll.h>
#include <sys/lx_syscall.h>
@@ -288,35 +287,3 @@ err:
free(sfds);
return (res);
}
-
-long
-lx_epoll_ctl(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4)
-{
- int epfd = (int)p1;
- int op = (int)p2;
- int fd = (int)p3;
- int rval;
- struct epoll_event ev;
-
- /*
- * Linux limits the max number of open files to 1m so we can also test
- * for this.
- */
- if (epfd < 0 || fd < 0 || epfd > (1024 * 1024) || fd > (1024 * 1024))
- return (-EBADF);
-
- if (epfd == fd)
- return (-EINVAL);
-
- /*
- * Unlike the base epoll_ctl, we need to return a fault if the
- * event pointer is invalid.
- */
- if (op != EPOLL_CTL_DEL) {
- if (uucopy((void *)p4, &ev, sizeof (ev)) != 0)
- return (-errno);
- }
-
- rval = epoll_ctl(epfd, op, fd, (struct epoll_event *)p4);
- return ((rval < 0) ? -errno : rval);
-}
diff --git a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h
index 17064b2c5d..4a0b19ffad 100644
--- a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h
+++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h
@@ -103,7 +103,6 @@ extern long lx_pselect6(uintptr_t, uintptr_t, uintptr_t, uintptr_t,
uintptr_t, uintptr_t);
extern long lx_poll(uintptr_t, uintptr_t, uintptr_t);
extern long lx_ppoll(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
-extern long lx_epoll_ctl(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_settimeofday(uintptr_t, uintptr_t);
extern long lx_getrusage(uintptr_t, uintptr_t);
extern long lx_mknod(uintptr_t, uintptr_t, uintptr_t);
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 4c109b57c5..34d8416757 100644
--- a/usr/src/uts/common/brand/lx/os/lx_syscall.c
+++ b/usr/src/uts/common/brand/lx/os/lx_syscall.c
@@ -778,7 +778,7 @@ lx_sysent_t lx_sysent32[] = {
{"group_exit", NULL, 0, 1}, /* 252 */
{"lookup_dcookie", NULL, NOSYS_NO_EQUIV, 0}, /* 253 */
{"epoll_create", lx_epoll_create, 0, 1}, /* 254 */
- {"epoll_ctl", NULL, 0, 4}, /* 255 */
+ {"epoll_ctl", lx_epoll_ctl, 0, 4}, /* 255 */
{"epoll_wait", lx_epoll_wait, 0, 4}, /* 256 */
{"remap_file_pages", NULL, NOSYS_NO_EQUIV, 0}, /* 257 */
{"set_tid_address", lx_set_tid_address, 0, 1}, /* 258 */
@@ -1127,7 +1127,7 @@ lx_sysent_t lx_sysent64[] = {
{"clock_nanosleep", NULL, 0, 4}, /* 230 */
{"exit_group", NULL, 0, 1}, /* 231 */
{"epoll_wait", lx_epoll_wait, 0, 4}, /* 232 */
- {"epoll_ctl", NULL, 0, 4}, /* 233 */
+ {"epoll_ctl", lx_epoll_ctl, 0, 4}, /* 233 */
{"tgkill", lx_tgkill, 0, 3}, /* 234 */
{"utimes", NULL, 0, 2}, /* 235 */
{"vserver", NULL, NOSYS_NULL, 0}, /* 236 */
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 c6b522942a..47fd9f9099 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
@@ -46,6 +46,7 @@ extern long lx_clock_settime();
extern long lx_connect();
extern long lx_epoll_create();
extern long lx_epoll_create1();
+extern long lx_epoll_ctl();
extern long lx_epoll_pwait();
extern long lx_epoll_wait();
extern long lx_fallocate();
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_epoll.c b/usr/src/uts/common/brand/lx/syscall/lx_epoll.c
index 6350492a16..2f3d3131ac 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_epoll.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_epoll.c
@@ -23,12 +23,25 @@
#include <sys/devpoll.h>
#include <sys/fcntl.h>
#include <sys/file.h>
+#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/sunldi.h>
#include <sys/vnode.h>
#include <sys/lx_brand.h>
#include <sys/lx_types.h>
+static major_t devpoll_major = 0;
+
+static boolean_t
+lx_epoll_isvalid(file_t *fp)
+{
+ vnode_t *vp = fp->f_vnode;
+
+ if (vp->v_type == VCHR && getmajor(vp->v_rdev) == devpoll_major)
+ return (B_TRUE);
+ return (B_FALSE);
+}
+
long
lx_epoll_create1(int flags)
{
@@ -64,6 +77,8 @@ lx_epoll_create1(int flags)
goto error;
}
+ devpoll_major = getmajor(vp->v_rdev);
+
fp->f_vnode = vp;
mutex_exit(&fp->f_tlock);
setf(fd, fp);
@@ -93,6 +108,93 @@ lx_epoll_create(int size)
return (lx_epoll_create1(0));
}
+
+/* Match values from libc implementation */
+#define EPOLLIGNORED (EPOLLMSG | EPOLLWAKEUP)
+#define EPOLLSWIZZLED \
+ (EPOLLRDHUP | EPOLLONESHOT | EPOLLET | EPOLLWRBAND | EPOLLWRNORM)
+
+long
+lx_epoll_ctl(int fd, int op, int pfd, void *event)
+{
+ epoll_event_t epevent;
+ dvpoll_epollfd_t dpevent[2];
+ file_t *fp;
+ iovec_t aiov;
+ uio_t auio;
+ uint32_t events, ev = 0;
+ int error = 0, i = 0;
+
+ dpevent[i].dpep_pollfd.fd = pfd;
+ switch (op) {
+ case EPOLL_CTL_DEL:
+ dpevent[i].dpep_pollfd.events = POLLREMOVE;
+ break;
+
+ case EPOLL_CTL_MOD:
+ /*
+ * In the modify case, we pass down two events: one to
+ * remove the event and another to add it back.
+ */
+ dpevent[i++].dpep_pollfd.events = POLLREMOVE;
+ dpevent[i].dpep_pollfd.fd = pfd;
+ /* FALLTHROUGH */
+
+ case EPOLL_CTL_ADD:
+ if (copyin(event, &epevent, sizeof (epevent)) != 0)
+ return (set_errno(EFAULT));
+
+ /*
+ * Mask off the events that we ignore, and then swizzle the
+ * events for which our values differ from their epoll(7)
+ * equivalents.
+ */
+ events = epevent.events;
+ ev = events & ~(EPOLLIGNORED | EPOLLSWIZZLED);
+
+ if (events & EPOLLRDHUP)
+ ev |= POLLRDHUP;
+ if (events & EPOLLET)
+ ev |= POLLET;
+ if (events & EPOLLONESHOT)
+ ev |= POLLONESHOT;
+ if (events & EPOLLWRNORM)
+ ev |= POLLWRNORM;
+ if (events & EPOLLWRBAND)
+ ev |= POLLWRBAND;
+
+ dpevent[i].dpep_data = epevent.data.u64;
+ dpevent[i].dpep_pollfd.events = ev;
+ break;
+
+ default:
+ return (set_errno(EINVAL));
+ }
+
+ if ((fp = getf(fd)) == NULL) {
+ return (set_errno(EBADF));
+ } else if (!lx_epoll_isvalid(fp)) {
+ releasef(fd);
+ return (set_errno(EINVAL));
+ }
+
+ aiov.iov_base = (void *)dpevent;
+ aiov.iov_len = sizeof (dvpoll_epollfd_t) * (i + 1);
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_resid = aiov.iov_len;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_loffset = 0;
+ auio.uio_fmode = fp->f_flag;
+
+ error = VOP_WRITE(fp->f_vnode, &auio, 1, fp->f_cred, NULL);
+
+ releasef(fd);
+ if (error)
+ return (set_errno(error));
+ return (0);
+}
+
long
lx_epoll_wait(int fd, void *events, int maxevents, int timeout)
{
@@ -105,6 +207,9 @@ lx_epoll_wait(int fd, void *events, int maxevents, int timeout)
}
if ((fp = getf(fd)) == NULL) {
return (set_errno(EBADF));
+ } else if (!lx_epoll_isvalid(fp)) {
+ releasef(fd);
+ return (set_errno(EINVAL));
}
arg.dp_nfds = maxevents;
@@ -133,6 +238,9 @@ lx_epoll_pwait(int fd, void *events, int maxevents, int timeout, void *sigmask)
}
if ((fp = getf(fd)) == NULL) {
return (set_errno(EBADF));
+ } else if (!lx_epoll_isvalid(fp)) {
+ releasef(fd);
+ return (set_errno(EINVAL));
}
arg.dp_nfds = maxevents;