Author: dchagin
Date: Thu Mar 30 20:14:43 2017
New Revision: 316302
URL: https://svnweb.freebsd.org/changeset/base/316302

Log:
  MFC r314404:
  
  Linux epoll return EEXIST on case when op is EPOLL_CTL_ADD, and the supplied
  file descriptor fd is already registered with this epoll instance.

Modified:
  stable/11/sys/compat/linux/linux_event.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/compat/linux/linux_event.c
==============================================================================
--- stable/11/sys/compat/linux/linux_event.c    Thu Mar 30 20:13:47 2017        
(r316301)
+++ stable/11/sys/compat/linux/linux_event.c    Thu Mar 30 20:14:43 2017        
(r316302)
@@ -481,15 +481,34 @@ linux_epoll_ctl(struct thread *td, struc
 
        ciargs.changelist = kev;
 
+       if (args->op != LINUX_EPOLL_CTL_DEL) {
+               kev_flags = EV_ADD | EV_ENABLE;
+               error = epoll_to_kevent(td, epfp, args->fd, &le,
+                   &kev_flags, kev, &nchanges);
+               if (error != 0)
+                       goto leave0;
+       }
+
        switch (args->op) {
        case LINUX_EPOLL_CTL_MOD:
                error = epoll_delete_all_events(td, epfp, args->fd);
                if (error != 0)
                        goto leave0;
-               /* FALLTHROUGH */
+               break;
 
        case LINUX_EPOLL_CTL_ADD:
-                       kev_flags = EV_ADD | EV_ENABLE;
+               /*
+                * kqueue_register() return ENOENT if event does not exists
+                * and the EV_ADD flag is not set.
+                */
+               kev[0].flags &= ~EV_ADD;
+               error = kqfd_register(args->epfd, &kev[0], td, 1);
+               if (error != ENOENT) {
+                       error = EEXIST;
+                       goto leave0;
+               }
+               error = 0;
+               kev[0].flags |= EV_ADD;
                break;
 
        case LINUX_EPOLL_CTL_DEL:
@@ -502,11 +521,6 @@ linux_epoll_ctl(struct thread *td, struc
                goto leave0;
        }
 
-       error = epoll_to_kevent(td, epfp, args->fd, &le, &kev_flags,
-           kev, &nchanges);
-       if (error != 0)
-               goto leave0;
-
        epoll_fd_install(td, args->fd, le.data);
 
        error = kern_kevent_fp(td, epfp, nchanges, 0, &k_ops, NULL);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to