linux_event.c revision 293571
1/*- 2 * Copyright (c) 2007 Roman Divacky 3 * Copyright (c) 2014 Dmitry Chagin 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29__FBSDID("$FreeBSD: stable/10/sys/compat/linux/linux_event.c 293571 2016-01-09 17:21:28Z dchagin $"); 30 31#include "opt_compat.h" 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/imgact.h> 36#include <sys/kernel.h> 37#include <sys/limits.h> 38#include <sys/lock.h> 39#include <sys/mutex.h> 40#include <sys/capability.h> 41#include <sys/types.h> 42#include <sys/file.h> 43#include <sys/filedesc.h> 44#include <sys/errno.h> 45#include <sys/event.h> 46#include <sys/poll.h> 47#include <sys/proc.h> 48#include <sys/selinfo.h> 49#include <sys/sx.h> 50#include <sys/syscallsubr.h> 51#include <sys/timespec.h> 52 53#ifdef COMPAT_LINUX32 54#include <machine/../linux32/linux.h> 55#include <machine/../linux32/linux32_proto.h> 56#else 57#include <machine/../linux/linux.h> 58#include <machine/../linux/linux_proto.h> 59#endif 60 61#include <compat/linux/linux_emul.h> 62#include <compat/linux/linux_event.h> 63#include <compat/linux/linux_file.h> 64#include <compat/linux/linux_util.h> 65 66/* 67 * epoll defines 'struct epoll_event' with the field 'data' as 64 bits 68 * on all architectures. But on 32 bit architectures BSD 'struct kevent' only 69 * has 32 bit opaque pointer as 'udata' field. So we can't pass epoll supplied 70 * data verbatuim. Therefore we allocate 64-bit memory block to pass 71 * user supplied data for every file descriptor. 72 */ 73 74typedef uint64_t epoll_udata_t; 75 76struct epoll_emuldata { 77 uint32_t fdc; /* epoll udata max index */ 78 epoll_udata_t udata[1]; /* epoll user data vector */ 79}; 80 81#define EPOLL_DEF_SZ 16 82#define EPOLL_SIZE(fdn) \ 83 (sizeof(struct epoll_emuldata)+(fdn) * sizeof(epoll_udata_t)) 84 85struct epoll_event { 86 uint32_t events; 87 epoll_udata_t data; 88} 89#if defined(__amd64__) 90__attribute__((packed)) 91#endif 92; 93 94#define LINUX_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event)) 95 96static void epoll_fd_install(struct thread *td, int fd, epoll_udata_t udata); 97static int epoll_to_kevent(struct thread *td, struct file *epfp, 98 int fd, struct epoll_event *l_event, int *kev_flags, 99 struct kevent *kevent, int *nkevents); 100static void kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event); 101static int epoll_kev_copyout(void *arg, struct kevent *kevp, int count); 102static int epoll_kev_copyin(void *arg, struct kevent *kevp, int count); 103static int epoll_delete_event(struct thread *td, struct file *epfp, 104 int fd, int filter); 105static int epoll_delete_all_events(struct thread *td, struct file *epfp, 106 int fd); 107 108struct epoll_copyin_args { 109 struct kevent *changelist; 110}; 111 112struct epoll_copyout_args { 113 struct epoll_event *leventlist; 114 struct proc *p; 115 uint32_t count; 116 int error; 117}; 118 119/* eventfd */ 120typedef uint64_t eventfd_t; 121 122static fo_rdwr_t eventfd_read; 123static fo_rdwr_t eventfd_write; 124static fo_truncate_t eventfd_truncate; 125static fo_ioctl_t eventfd_ioctl; 126static fo_poll_t eventfd_poll; 127static fo_kqfilter_t eventfd_kqfilter; 128static fo_stat_t eventfd_stat; 129static fo_close_t eventfd_close; 130 131static struct fileops eventfdops = { 132 .fo_read = eventfd_read, 133 .fo_write = eventfd_write, 134 .fo_truncate = eventfd_truncate, 135 .fo_ioctl = eventfd_ioctl, 136 .fo_poll = eventfd_poll, 137 .fo_kqfilter = eventfd_kqfilter, 138 .fo_stat = eventfd_stat, 139 .fo_close = eventfd_close, 140 .fo_chmod = invfo_chmod, 141 .fo_chown = invfo_chown, 142 .fo_sendfile = invfo_sendfile, 143 .fo_flags = DFLAG_PASSABLE 144}; 145 146static void filt_eventfddetach(struct knote *kn); 147static int filt_eventfdread(struct knote *kn, long hint); 148static int filt_eventfdwrite(struct knote *kn, long hint); 149 150static struct filterops eventfd_rfiltops = { 151 .f_isfd = 1, 152 .f_detach = filt_eventfddetach, 153 .f_event = filt_eventfdread 154}; 155static struct filterops eventfd_wfiltops = { 156 .f_isfd = 1, 157 .f_detach = filt_eventfddetach, 158 .f_event = filt_eventfdwrite 159}; 160 161struct eventfd { 162 eventfd_t efd_count; 163 uint32_t efd_flags; 164 struct selinfo efd_sel; 165 struct mtx efd_lock; 166}; 167 168static int eventfd_create(struct thread *td, uint32_t initval, int flags); 169 170 171static void 172epoll_fd_install(struct thread *td, int fd, epoll_udata_t udata) 173{ 174 struct linux_pemuldata *pem; 175 struct epoll_emuldata *emd; 176 struct proc *p; 177 178 p = td->td_proc; 179 180 pem = pem_find(p); 181 KASSERT(pem != NULL, ("epoll proc emuldata not found.\n")); 182 183 LINUX_PEM_XLOCK(pem); 184 if (pem->epoll == NULL) { 185 emd = malloc(EPOLL_SIZE(fd), M_EPOLL, M_WAITOK); 186 emd->fdc = fd; 187 pem->epoll = emd; 188 } else { 189 emd = pem->epoll; 190 if (fd > emd->fdc) { 191 emd = realloc(emd, EPOLL_SIZE(fd), M_EPOLL, M_WAITOK); 192 emd->fdc = fd; 193 pem->epoll = emd; 194 } 195 } 196 emd->udata[fd] = udata; 197 LINUX_PEM_XUNLOCK(pem); 198} 199 200static int 201epoll_create_common(struct thread *td, int flags) 202{ 203 int error; 204 205 error = kern_kqueue(td, flags); 206 if (error) 207 return (error); 208 209 epoll_fd_install(td, EPOLL_DEF_SZ, 0); 210 211 return (0); 212} 213 214int 215linux_epoll_create(struct thread *td, struct linux_epoll_create_args *args) 216{ 217 218 /* 219 * args->size is unused. Linux just tests it 220 * and then forgets it as well. 221 */ 222 if (args->size <= 0) 223 return (EINVAL); 224 225 return (epoll_create_common(td, 0)); 226} 227 228int 229linux_epoll_create1(struct thread *td, struct linux_epoll_create1_args *args) 230{ 231 int flags; 232 233 if ((args->flags & ~(LINUX_O_CLOEXEC)) != 0) 234 return (EINVAL); 235 236 flags = 0; 237 if ((args->flags & LINUX_O_CLOEXEC) != 0) 238 flags |= O_CLOEXEC; 239 240 return (epoll_create_common(td, flags)); 241} 242 243/* Structure converting function from epoll to kevent. */ 244static int 245epoll_to_kevent(struct thread *td, struct file *epfp, 246 int fd, struct epoll_event *l_event, int *kev_flags, 247 struct kevent *kevent, int *nkevents) 248{ 249 uint32_t levents = l_event->events; 250 struct linux_pemuldata *pem; 251 struct proc *p; 252 253 /* flags related to how event is registered */ 254 if ((levents & LINUX_EPOLLONESHOT) != 0) 255 *kev_flags |= EV_ONESHOT; 256 if ((levents & LINUX_EPOLLET) != 0) 257 *kev_flags |= EV_CLEAR; 258 if ((levents & LINUX_EPOLLERR) != 0) 259 *kev_flags |= EV_ERROR; 260 261 /* flags related to what event is registered */ 262 if ((levents & LINUX_EPOLL_EVRD) != 0) { 263 EV_SET(kevent++, fd, EVFILT_READ, *kev_flags, 0, 0, 0); 264 ++(*nkevents); 265 } 266 if ((levents & LINUX_EPOLL_EVWR) != 0) { 267 EV_SET(kevent++, fd, EVFILT_WRITE, *kev_flags, 0, 0, 0); 268 ++(*nkevents); 269 } 270 271 if ((levents & ~(LINUX_EPOLL_EVSUP)) != 0) { 272 p = td->td_proc; 273 274 pem = pem_find(p); 275 KASSERT(pem != NULL, ("epoll proc emuldata not found.\n")); 276 KASSERT(pem->epoll != NULL, ("epoll proc epolldata not found.\n")); 277 278 LINUX_PEM_XLOCK(pem); 279 if ((pem->flags & LINUX_XUNSUP_EPOLL) == 0) { 280 pem->flags |= LINUX_XUNSUP_EPOLL; 281 LINUX_PEM_XUNLOCK(pem); 282 linux_msg(td, "epoll_ctl unsupported flags: 0x%x\n", 283 levents); 284 } else 285 LINUX_PEM_XUNLOCK(pem); 286 return (EINVAL); 287 } 288 289 return (0); 290} 291 292/* 293 * Structure converting function from kevent to epoll. In a case 294 * this is called on error in registration we store the error in 295 * event->data and pick it up later in linux_epoll_ctl(). 296 */ 297static void 298kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event) 299{ 300 301 if ((kevent->flags & EV_ERROR) != 0) { 302 l_event->events = LINUX_EPOLLERR; 303 return; 304 } 305 306 switch (kevent->filter) { 307 case EVFILT_READ: 308 l_event->events = LINUX_EPOLLIN|LINUX_EPOLLRDNORM|LINUX_EPOLLPRI; 309 break; 310 case EVFILT_WRITE: 311 l_event->events = LINUX_EPOLLOUT|LINUX_EPOLLWRNORM; 312 break; 313 } 314} 315 316/* 317 * Copyout callback used by kevent. This converts kevent 318 * events to epoll events and copies them back to the 319 * userspace. This is also called on error on registering 320 * of the filter. 321 */ 322static int 323epoll_kev_copyout(void *arg, struct kevent *kevp, int count) 324{ 325 struct epoll_copyout_args *args; 326 struct linux_pemuldata *pem; 327 struct epoll_emuldata *emd; 328 struct epoll_event *eep; 329 int error, fd, i; 330 331 args = (struct epoll_copyout_args*) arg; 332 eep = malloc(sizeof(*eep) * count, M_EPOLL, M_WAITOK | M_ZERO); 333 334 pem = pem_find(args->p); 335 KASSERT(pem != NULL, ("epoll proc emuldata not found.\n")); 336 LINUX_PEM_SLOCK(pem); 337 emd = pem->epoll; 338 KASSERT(emd != NULL, ("epoll proc epolldata not found.\n")); 339 340 for (i = 0; i < count; i++) { 341 kevent_to_epoll(&kevp[i], &eep[i]); 342 343 fd = kevp[i].ident; 344 KASSERT(fd <= emd->fdc, ("epoll user data vector" 345 " is too small.\n")); 346 eep[i].data = emd->udata[fd]; 347 } 348 LINUX_PEM_SUNLOCK(pem); 349 350 error = copyout(eep, args->leventlist, count * sizeof(*eep)); 351 if (error == 0) { 352 args->leventlist += count; 353 args->count += count; 354 } else if (args->error == 0) 355 args->error = error; 356 357 free(eep, M_EPOLL); 358 return (error); 359} 360 361/* 362 * Copyin callback used by kevent. This copies already 363 * converted filters from kernel memory to the kevent 364 * internal kernel memory. Hence the memcpy instead of 365 * copyin. 366 */ 367static int 368epoll_kev_copyin(void *arg, struct kevent *kevp, int count) 369{ 370 struct epoll_copyin_args *args; 371 372 args = (struct epoll_copyin_args*) arg; 373 374 memcpy(kevp, args->changelist, count * sizeof(*kevp)); 375 args->changelist += count; 376 377 return (0); 378} 379 380/* 381 * Load epoll filter, convert it to kevent filter 382 * and load it into kevent subsystem. 383 */ 384int 385linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args) 386{ 387 struct file *epfp, *fp; 388 struct epoll_copyin_args ciargs; 389 struct kevent kev[2]; 390 struct kevent_copyops k_ops = { &ciargs, 391 NULL, 392 epoll_kev_copyin}; 393 struct epoll_event le; 394 cap_rights_t rights; 395 int kev_flags; 396 int nchanges = 0; 397 int error; 398 399 if (args->op != LINUX_EPOLL_CTL_DEL) { 400 error = copyin(args->event, &le, sizeof(le)); 401 if (error != 0) 402 return (error); 403 } 404 405 error = fget(td, args->epfd, 406 cap_rights_init(&rights, CAP_KQUEUE_CHANGE), &epfp); 407 if (error != 0) 408 return (error); 409 if (epfp->f_type != DTYPE_KQUEUE) 410 goto leave1; 411 412 /* Protect user data vector from incorrectly supplied fd. */ 413 error = fget(td, args->fd, cap_rights_init(&rights, CAP_POLL_EVENT), &fp); 414 if (error != 0) 415 goto leave1; 416 417 /* Linux disallows spying on himself */ 418 if (epfp == fp) { 419 error = EINVAL; 420 goto leave0; 421 } 422 423 ciargs.changelist = kev; 424 425 switch (args->op) { 426 case LINUX_EPOLL_CTL_MOD: 427 /* 428 * We don't memorize which events were set for this FD 429 * on this level, so just delete all we could have set: 430 * EVFILT_READ and EVFILT_WRITE, ignoring any errors 431 */ 432 error = epoll_delete_all_events(td, epfp, args->fd); 433 if (error) 434 goto leave0; 435 /* FALLTHROUGH */ 436 437 case LINUX_EPOLL_CTL_ADD: 438 kev_flags = EV_ADD | EV_ENABLE; 439 break; 440 441 case LINUX_EPOLL_CTL_DEL: 442 /* CTL_DEL means unregister this fd with this epoll */ 443 error = epoll_delete_all_events(td, epfp, args->fd); 444 goto leave0; 445 446 default: 447 error = EINVAL; 448 goto leave0; 449 } 450 451 error = epoll_to_kevent(td, epfp, args->fd, &le, &kev_flags, 452 kev, &nchanges); 453 if (error) 454 goto leave0; 455 456 epoll_fd_install(td, args->fd, le.data); 457 458 error = kern_kevent_fp(td, epfp, nchanges, 0, &k_ops, NULL); 459 460leave0: 461 fdrop(fp, td); 462 463leave1: 464 fdrop(epfp, td); 465 return (error); 466} 467 468/* 469 * Wait for a filter to be triggered on the epoll file descriptor. 470 */ 471int 472linux_epoll_wait(struct thread *td, struct linux_epoll_wait_args *args) 473{ 474 struct file *epfp; 475 struct timespec ts, *tsp; 476 cap_rights_t rights; 477 struct epoll_copyout_args coargs; 478 struct kevent_copyops k_ops = { &coargs, 479 epoll_kev_copyout, 480 NULL}; 481 int error; 482 483 if (args->maxevents <= 0 || args->maxevents > LINUX_MAX_EVENTS) 484 return (EINVAL); 485 486 error = fget(td, args->epfd, 487 cap_rights_init(&rights, CAP_KQUEUE_EVENT), &epfp); 488 if (error != 0) 489 return (error); 490 491 coargs.leventlist = args->events; 492 coargs.p = td->td_proc; 493 coargs.count = 0; 494 coargs.error = 0; 495 496 if (args->timeout != -1) { 497 if (args->timeout < 0) { 498 error = EINVAL; 499 goto leave; 500 } 501 /* Convert from milliseconds to timespec. */ 502 ts.tv_sec = args->timeout / 1000; 503 ts.tv_nsec = (args->timeout % 1000) * 1000000; 504 tsp = &ts; 505 } else { 506 tsp = NULL; 507 } 508 509 error = kern_kevent_fp(td, epfp, 0, args->maxevents, &k_ops, tsp); 510 if (error == 0 && coargs.error != 0) 511 error = coargs.error; 512 513 /* 514 * kern_kevent might return ENOMEM which is not expected from epoll_wait. 515 * Maybe we should translate that but I don't think it matters at all. 516 */ 517 if (error == 0) 518 td->td_retval[0] = coargs.count; 519leave: 520 fdrop(epfp, td); 521 return (error); 522} 523 524static int 525epoll_delete_event(struct thread *td, struct file *epfp, int fd, int filter) 526{ 527 struct epoll_copyin_args ciargs; 528 struct kevent kev; 529 struct kevent_copyops k_ops = { &ciargs, 530 NULL, 531 epoll_kev_copyin}; 532 int error; 533 534 ciargs.changelist = &kev; 535 EV_SET(&kev, fd, filter, EV_DELETE | EV_DISABLE, 0, 0, 0); 536 537 error = kern_kevent_fp(td, epfp, 1, 0, &k_ops, NULL); 538 539 /* 540 * here we ignore ENONT, because we don't keep track of events here 541 */ 542 if (error == ENOENT) 543 error = 0; 544 return (error); 545} 546 547static int 548epoll_delete_all_events(struct thread *td, struct file *epfp, int fd) 549{ 550 int error1, error2; 551 552 error1 = epoll_delete_event(td, epfp, fd, EVFILT_READ); 553 error2 = epoll_delete_event(td, epfp, fd, EVFILT_WRITE); 554 555 /* report any errors we got */ 556 return (error1 == 0 ? error2 : error1); 557} 558 559static int 560eventfd_create(struct thread *td, uint32_t initval, int flags) 561{ 562 struct filedesc *fdp; 563 struct eventfd *efd; 564 struct file *fp; 565 int fflags, fd, error; 566 567 fflags = 0; 568 if ((flags & LINUX_O_CLOEXEC) != 0) 569 fflags |= O_CLOEXEC; 570 571 fdp = td->td_proc->p_fd; 572 error = falloc(td, &fp, &fd, fflags); 573 if (error) 574 return (error); 575 576 efd = malloc(sizeof(*efd), M_EPOLL, M_WAITOK | M_ZERO); 577 efd->efd_flags = flags; 578 efd->efd_count = initval; 579 mtx_init(&efd->efd_lock, "eventfd", NULL, MTX_DEF); 580 581 knlist_init_mtx(&efd->efd_sel.si_note, &efd->efd_lock); 582 583 fflags = FREAD | FWRITE; 584 if ((flags & LINUX_O_NONBLOCK) != 0) 585 fflags |= FNONBLOCK; 586 587 finit(fp, fflags, DTYPE_LINUXEFD, efd, &eventfdops); 588 fdrop(fp, td); 589 590 td->td_retval[0] = fd; 591 return (error); 592} 593 594int 595linux_eventfd(struct thread *td, struct linux_eventfd_args *args) 596{ 597 598 return (eventfd_create(td, args->initval, 0)); 599} 600 601int 602linux_eventfd2(struct thread *td, struct linux_eventfd2_args *args) 603{ 604 605 if ((args->flags & ~(LINUX_O_CLOEXEC|LINUX_O_NONBLOCK|LINUX_EFD_SEMAPHORE)) != 0) 606 return (EINVAL); 607 608 return (eventfd_create(td, args->initval, args->flags)); 609} 610 611static int 612eventfd_close(struct file *fp, struct thread *td) 613{ 614 struct eventfd *efd; 615 616 efd = fp->f_data; 617 if (fp->f_type != DTYPE_LINUXEFD || efd == NULL) 618 return (EBADF); 619 620 seldrain(&efd->efd_sel); 621 knlist_destroy(&efd->efd_sel.si_note); 622 623 fp->f_ops = &badfileops; 624 mtx_destroy(&efd->efd_lock); 625 free(efd, M_EPOLL); 626 627 return (0); 628} 629 630static int 631eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred, 632 int flags, struct thread *td) 633{ 634 struct eventfd *efd; 635 eventfd_t count; 636 int error; 637 638 efd = fp->f_data; 639 if (fp->f_type != DTYPE_LINUXEFD || efd == NULL) 640 return (EBADF); 641 642 if (uio->uio_resid < sizeof(eventfd_t)) 643 return (EINVAL); 644 645 error = 0; 646 mtx_lock(&efd->efd_lock); 647retry: 648 if (efd->efd_count == 0) { 649 if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) { 650 mtx_unlock(&efd->efd_lock); 651 return (EAGAIN); 652 } 653 error = mtx_sleep(&efd->efd_count, &efd->efd_lock, PCATCH, "lefdrd", 0); 654 if (error == 0) 655 goto retry; 656 } 657 if (error == 0) { 658 if ((efd->efd_flags & LINUX_EFD_SEMAPHORE) != 0) { 659 count = 1; 660 --efd->efd_count; 661 } else { 662 count = efd->efd_count; 663 efd->efd_count = 0; 664 } 665 KNOTE_LOCKED(&efd->efd_sel.si_note, 0); 666 selwakeup(&efd->efd_sel); 667 wakeup(&efd->efd_count); 668 mtx_unlock(&efd->efd_lock); 669 error = uiomove(&count, sizeof(eventfd_t), uio); 670 } else 671 mtx_unlock(&efd->efd_lock); 672 673 return (error); 674} 675 676static int 677eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred, 678 int flags, struct thread *td) 679{ 680 struct eventfd *efd; 681 eventfd_t count; 682 int error; 683 684 efd = fp->f_data; 685 if (fp->f_type != DTYPE_LINUXEFD || efd == NULL) 686 return (EBADF); 687 688 if (uio->uio_resid < sizeof(eventfd_t)) 689 return (EINVAL); 690 691 error = uiomove(&count, sizeof(eventfd_t), uio); 692 if (error) 693 return (error); 694 if (count == UINT64_MAX) 695 return (EINVAL); 696 697 mtx_lock(&efd->efd_lock); 698retry: 699 if (UINT64_MAX - efd->efd_count <= count) { 700 if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) { 701 mtx_unlock(&efd->efd_lock); 702 return (EAGAIN); 703 } 704 error = mtx_sleep(&efd->efd_count, &efd->efd_lock, 705 PCATCH, "lefdwr", 0); 706 if (error == 0) 707 goto retry; 708 } 709 if (error == 0) { 710 efd->efd_count += count; 711 KNOTE_LOCKED(&efd->efd_sel.si_note, 0); 712 selwakeup(&efd->efd_sel); 713 wakeup(&efd->efd_count); 714 } 715 mtx_unlock(&efd->efd_lock); 716 717 return (error); 718} 719 720static int 721eventfd_poll(struct file *fp, int events, struct ucred *active_cred, 722 struct thread *td) 723{ 724 struct eventfd *efd; 725 int revents = 0; 726 727 efd = fp->f_data; 728 if (fp->f_type != DTYPE_LINUXEFD || efd == NULL) 729 return (POLLERR); 730 731 mtx_lock(&efd->efd_lock); 732 if ((events & (POLLIN|POLLRDNORM)) && efd->efd_count > 0) 733 revents |= events & (POLLIN|POLLRDNORM); 734 if ((events & (POLLOUT|POLLWRNORM)) && UINT64_MAX - 1 > efd->efd_count) 735 revents |= events & (POLLOUT|POLLWRNORM); 736 if (revents == 0) 737 selrecord(td, &efd->efd_sel); 738 mtx_unlock(&efd->efd_lock); 739 740 return (revents); 741} 742 743/*ARGSUSED*/ 744static int 745eventfd_kqfilter(struct file *fp, struct knote *kn) 746{ 747 struct eventfd *efd; 748 749 efd = fp->f_data; 750 if (fp->f_type != DTYPE_LINUXEFD || efd == NULL) 751 return (EINVAL); 752 753 mtx_lock(&efd->efd_lock); 754 switch (kn->kn_filter) { 755 case EVFILT_READ: 756 kn->kn_fop = &eventfd_rfiltops; 757 break; 758 case EVFILT_WRITE: 759 kn->kn_fop = &eventfd_wfiltops; 760 break; 761 default: 762 mtx_unlock(&efd->efd_lock); 763 return (EINVAL); 764 } 765 766 kn->kn_hook = efd; 767 knlist_add(&efd->efd_sel.si_note, kn, 1); 768 mtx_unlock(&efd->efd_lock); 769 770 return (0); 771} 772 773static void 774filt_eventfddetach(struct knote *kn) 775{ 776 struct eventfd *efd = kn->kn_hook; 777 778 mtx_lock(&efd->efd_lock); 779 knlist_remove(&efd->efd_sel.si_note, kn, 1); 780 mtx_unlock(&efd->efd_lock); 781} 782 783/*ARGSUSED*/ 784static int 785filt_eventfdread(struct knote *kn, long hint) 786{ 787 struct eventfd *efd = kn->kn_hook; 788 int ret; 789 790 mtx_assert(&efd->efd_lock, MA_OWNED); 791 ret = (efd->efd_count > 0); 792 793 return (ret); 794} 795 796/*ARGSUSED*/ 797static int 798filt_eventfdwrite(struct knote *kn, long hint) 799{ 800 struct eventfd *efd = kn->kn_hook; 801 int ret; 802 803 mtx_assert(&efd->efd_lock, MA_OWNED); 804 ret = (UINT64_MAX - 1 > efd->efd_count); 805 806 return (ret); 807} 808 809/*ARGSUSED*/ 810static int 811eventfd_truncate(struct file *fp, off_t length, struct ucred *active_cred, 812 struct thread *td) 813{ 814 815 return (ENXIO); 816} 817 818/*ARGSUSED*/ 819static int 820eventfd_ioctl(struct file *fp, u_long cmd, void *data, 821 struct ucred *active_cred, struct thread *td) 822{ 823 824 return (ENXIO); 825} 826 827/*ARGSUSED*/ 828static int 829eventfd_stat(struct file *fp, struct stat *st, struct ucred *active_cred, 830 struct thread *td) 831{ 832 833 return (ENXIO); 834} 835