]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/compat/linux/linux_event.c
MFC r283470:
[FreeBSD/stable/10.git] / sys / compat / linux / linux_event.c
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$");
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
74 typedef uint64_t        epoll_udata_t;
75
76 struct 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
85 struct 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
96 static void     epoll_fd_install(struct thread *td, int fd, epoll_udata_t udata);
97 static 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);
100 static void     kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event);
101 static int      epoll_kev_copyout(void *arg, struct kevent *kevp, int count);
102 static int      epoll_kev_copyin(void *arg, struct kevent *kevp, int count);
103 static int      epoll_delete_event(struct thread *td, struct file *epfp,
104                     int fd, int filter);
105 static int      epoll_delete_all_events(struct thread *td, struct file *epfp,
106                     int fd);
107
108 struct epoll_copyin_args {
109         struct kevent   *changelist;
110 };
111
112 struct epoll_copyout_args {
113         struct epoll_event      *leventlist;
114         struct proc             *p;
115         uint32_t                count;
116         int                     error;
117 };
118
119 /* eventfd */
120 typedef uint64_t        eventfd_t;
121
122 static fo_rdwr_t        eventfd_read;
123 static fo_rdwr_t        eventfd_write;
124 static fo_truncate_t    eventfd_truncate;
125 static fo_ioctl_t       eventfd_ioctl;
126 static fo_poll_t        eventfd_poll;
127 static fo_kqfilter_t    eventfd_kqfilter;
128 static fo_stat_t        eventfd_stat;
129 static fo_close_t       eventfd_close;
130
131 static 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
146 static void     filt_eventfddetach(struct knote *kn);
147 static int      filt_eventfdread(struct knote *kn, long hint);
148 static int      filt_eventfdwrite(struct knote *kn, long hint);
149
150 static struct filterops eventfd_rfiltops = {
151         .f_isfd = 1,
152         .f_detach = filt_eventfddetach,
153         .f_event = filt_eventfdread
154 };
155 static struct filterops eventfd_wfiltops = {
156         .f_isfd = 1,
157         .f_detach = filt_eventfddetach,
158         .f_event = filt_eventfdwrite
159 };
160
161 struct eventfd {
162         eventfd_t       efd_count;
163         uint32_t        efd_flags;
164         struct selinfo  efd_sel;
165         struct mtx      efd_lock;
166 };
167
168 static int      eventfd_create(struct thread *td, uint32_t initval, int flags);
169
170
171 static void
172 epoll_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
200 static int
201 epoll_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
214 int
215 linux_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
228 int
229 linux_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. */
244 static int
245 epoll_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  */
297 static void
298 kevent_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  */
322 static int
323 epoll_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  */
367 static int
368 epoll_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  */
384 int
385 linux_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
460 leave0:
461         fdrop(fp, td);
462
463 leave1:
464         fdrop(epfp, td);
465         return (error);
466 }
467
468 /*
469  * Wait for a filter to be triggered on the epoll file descriptor.
470  */
471 int
472 linux_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;
519 leave:
520         fdrop(epfp, td);
521         return (error);
522 }
523
524 static int
525 epoll_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
547 static int
548 epoll_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
559 static int
560 eventfd_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
594 int
595 linux_eventfd(struct thread *td, struct linux_eventfd_args *args)
596 {
597
598         return (eventfd_create(td, args->initval, 0));
599 }
600
601 int
602 linux_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
611 static int
612 eventfd_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
630 static int
631 eventfd_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);
647 retry:
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
676 static int
677 eventfd_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);
698 retry:
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
720 static int
721 eventfd_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*/
744 static int
745 eventfd_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
773 static void
774 filt_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*/
784 static int
785 filt_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*/
797 static int
798 filt_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*/
810 static int
811 eventfd_truncate(struct file *fp, off_t length, struct ucred *active_cred,
812         struct thread *td)
813 {
814
815         return (ENXIO);
816 }
817
818 /*ARGSUSED*/
819 static int
820 eventfd_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*/
828 static int
829 eventfd_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
830         struct thread *td)
831 {
832
833         return (ENXIO);
834 }