commit cc394bbc816104d95a8baf300a947dc205de27f2 Author: Vladimir Kondratyev Date: Wed Dec 27 23:46:58 2017 +0300 epoll: Store user data variable in extended data member of kevent. This makes allocation of per process epoll array unnecessary. diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c index 1dfbe239ccc..499bebe8926 100644 --- a/sys/compat/linux/linux_emul.c +++ b/sys/compat/linux/linux_emul.c @@ -143,7 +143,6 @@ linux_proc_init(struct thread *td, struct thread *newtd, int flags) { struct linux_emuldata *em; struct linux_pemuldata *pem; - struct epoll_emuldata *emd; struct proc *p; if (newtd != NULL) { @@ -185,15 +184,9 @@ linux_proc_init(struct thread *td, struct thread *newtd, int flags) em->child_clear_tid = NULL; em->child_set_tid = NULL; - /* epoll should be destroyed in a case of exec. */ pem = pem_find(p); KASSERT(pem != NULL, ("proc_exit: proc emuldata not found.\n")); pem->persona = 0; - if (pem->epoll != NULL) { - emd = pem->epoll; - pem->epoll = NULL; - free(emd, M_EPOLL); - } } } @@ -202,7 +195,6 @@ void linux_on_exit(struct proc *p) { struct linux_pemuldata *pem; - struct epoll_emuldata *emd; struct thread *td = curthread; MPASS(SV_CURPROC_ABI() == SV_ABI_LINUX); @@ -217,12 +209,6 @@ linux_on_exit(struct proc *p) p->p_emuldata = NULL; - if (pem->epoll != NULL) { - emd = pem->epoll; - pem->epoll = NULL; - free(emd, M_EPOLL); - } - sx_destroy(&pem->pem_sx); free(pem, M_LINUX); } @@ -267,7 +253,6 @@ int linux_common_execve(struct thread *td, struct image_args *eargs) { struct linux_pemuldata *pem; - struct epoll_emuldata *emd; struct vmspace *oldvmspace; struct linux_emuldata *em; struct proc *p; @@ -299,12 +284,6 @@ linux_common_execve(struct thread *td, struct image_args *eargs) p->p_emuldata = NULL; PROC_UNLOCK(p); - if (pem->epoll != NULL) { - emd = pem->epoll; - pem->epoll = NULL; - free(emd, M_EPOLL); - } - free(em, M_TEMP); free(pem, M_LINUX); } diff --git a/sys/compat/linux/linux_emul.h b/sys/compat/linux/linux_emul.h index 1bbc69ad98b..de66a7a4c82 100644 --- a/sys/compat/linux/linux_emul.h +++ b/sys/compat/linux/linux_emul.h @@ -68,7 +68,6 @@ int linux_common_execve(struct thread *, struct image_args *); struct linux_pemuldata { uint32_t flags; /* process emuldata flags */ struct sx pem_sx; /* lock for this struct */ - void *epoll; /* epoll data */ uint32_t persona; /* process execution domain */ uint32_t ptrace_flags; /* used by ptrace(2) */ }; diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c index b4b4be1f7b4..a5b88749519 100644 --- a/sys/compat/linux/linux_event.c +++ b/sys/compat/linux/linux_event.c @@ -71,25 +71,8 @@ __FBSDID("$FreeBSD$"); #include #include -/* - * epoll defines 'struct epoll_event' with the field 'data' as 64 bits - * on all architectures. But on 32 bit architectures BSD 'struct kevent' only - * has 32 bit opaque pointer as 'udata' field. So we can't pass epoll supplied - * data verbatuim. Therefore we allocate 64-bit memory block to pass - * user supplied data for every file descriptor. - */ - typedef uint64_t epoll_udata_t; -struct epoll_emuldata { - uint32_t fdc; /* epoll udata max index */ - epoll_udata_t udata[1]; /* epoll user data vector */ -}; - -#define EPOLL_DEF_SZ 16 -#define EPOLL_SIZE(fdn) \ - (sizeof(struct epoll_emuldata)+(fdn) * sizeof(epoll_udata_t)) - struct epoll_event { uint32_t events; epoll_udata_t data; @@ -101,7 +84,6 @@ __attribute__((packed)) #define LINUX_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event)) -static void epoll_fd_install(struct thread *td, int fd, epoll_udata_t udata); static int epoll_to_kevent(struct thread *td, int fd, struct epoll_event *l_event, struct kevent *kevent, int *nkevents); @@ -175,35 +157,6 @@ struct timerfd { static void linux_timerfd_expire(void *); static void linux_timerfd_curval(struct timerfd *, struct itimerspec *); -static void -epoll_fd_install(struct thread *td, int fd, epoll_udata_t udata) -{ - struct linux_pemuldata *pem; - struct epoll_emuldata *emd; - struct proc *p; - - p = td->td_proc; - - pem = pem_find(p); - KASSERT(pem != NULL, ("epoll proc emuldata not found.\n")); - - LINUX_PEM_XLOCK(pem); - if (pem->epoll == NULL) { - emd = malloc(EPOLL_SIZE(fd), M_EPOLL, M_WAITOK); - emd->fdc = fd; - pem->epoll = emd; - } else { - emd = pem->epoll; - if (fd > emd->fdc) { - emd = realloc(emd, EPOLL_SIZE(fd), M_EPOLL, M_WAITOK); - emd->fdc = fd; - pem->epoll = emd; - } - } - emd->udata[fd] = udata; - LINUX_PEM_XUNLOCK(pem); -} - static int epoll_create_common(struct thread *td, int flags) { @@ -213,8 +166,6 @@ epoll_create_common(struct thread *td, int flags) if (error != 0) return (error); - epoll_fd_install(td, EPOLL_DEF_SZ, 0); - return (0); } @@ -271,11 +222,15 @@ epoll_to_kevent(struct thread *td, int fd, struct epoll_event *l_event, /* flags related to what event is registered */ if ((levents & LINUX_EPOLL_EVRD) != 0) { - EV_SET(kevent++, fd, EVFILT_READ, kev_flags, 0, 0, 0); + EV_SET(kevent, fd, EVFILT_READ, kev_flags, 0, 0, 0); + kevent->ext[0] = l_event->data; + ++kevent; ++(*nkevents); } if ((levents & LINUX_EPOLL_EVWR) != 0) { - EV_SET(kevent++, fd, EVFILT_WRITE, kev_flags, 0, 0, 0); + EV_SET(kevent, fd, EVFILT_WRITE, kev_flags, 0, 0, 0); + kevent->ext[0] = l_event->data; + ++kevent; ++(*nkevents); } /* zero event mask is legal */ @@ -289,7 +244,6 @@ epoll_to_kevent(struct thread *td, int fd, struct epoll_event *l_event, pem = pem_find(p); KASSERT(pem != NULL, ("epoll proc emuldata not found.\n")); - KASSERT(pem->epoll != NULL, ("epoll proc epolldata not found.\n")); LINUX_PEM_XLOCK(pem); if ((pem->flags & LINUX_XUNSUP_EPOLL) == 0) { @@ -314,6 +268,8 @@ static void kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event) { + l_event->data = kevent->ext[0]; + if ((kevent->flags & EV_ERROR) != 0) { l_event->events = LINUX_EPOLLERR; return; @@ -342,30 +298,15 @@ static int epoll_kev_copyout(void *arg, struct kevent *kevp, int count) { struct epoll_copyout_args *args; - struct linux_pemuldata *pem; - struct epoll_emuldata *emd; struct epoll_event *eep; - int error, fd, i; + int error, i; args = (struct epoll_copyout_args*) arg; eep = malloc(sizeof(*eep) * count, M_EPOLL, M_WAITOK | M_ZERO); - pem = pem_find(args->p); - KASSERT(pem != NULL, ("epoll proc emuldata not found.\n")); - LINUX_PEM_SLOCK(pem); - emd = pem->epoll; - KASSERT(emd != NULL, ("epoll proc epolldata not found.\n")); - - for (i = 0; i < count; i++) { + for (i = 0; i < count; i++) kevent_to_epoll(&kevp[i], &eep[i]); - fd = kevp[i].ident; - KASSERT(fd <= emd->fdc, ("epoll user data vector" - " is too small.\n")); - eep[i].data = emd->udata[fd]; - } - LINUX_PEM_SUNLOCK(pem); - error = copyout(eep, args->leventlist, count * sizeof(*eep)); if (error == 0) { args->leventlist += count; @@ -472,8 +413,6 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args) goto leave0; } - epoll_fd_install(td, args->fd, le.data); - error = kern_kevent_fp(td, epfp, nchanges, 0, &k_ops, NULL); leave0: