diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/lx_brand.c | 4 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/common/poll_select.c | 33 | ||||
-rw-r--r-- | usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_syscall.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_syscalls.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_epoll.c | 108 |
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; |