svn commit: r314404 - head/sys/compat/linux

Dmitry Chagin dchagin at FreeBSD.org
Tue Feb 28 19:55:18 UTC 2017


Author: dchagin
Date: Tue Feb 28 19:55:16 2017
New Revision: 314404
URL: https://svnweb.freebsd.org/changeset/base/314404

Log:
  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.
  
  MFC after:	1 month

Modified:
  head/sys/compat/linux/linux_event.c

Modified: head/sys/compat/linux/linux_event.c
==============================================================================
--- head/sys/compat/linux/linux_event.c	Tue Feb 28 19:54:22 2017	(r314403)
+++ head/sys/compat/linux/linux_event.c	Tue Feb 28 19:55:16 2017	(r314404)
@@ -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);


More information about the svn-src-all mailing list