diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c --- a/sys/compat/linux/linux_event.c +++ b/sys/compat/linux/linux_event.c @@ -633,24 +633,18 @@ int linux_eventfd(struct thread *td, struct linux_eventfd_args *args) { - struct specialfd_eventfd ae; - - bzero(&ae, sizeof(ae)); - ae.initval = args->initval; - return (kern_specialfd(td, SPECIALFD_EVENTFD, &ae)); + return (eventfd_create_file(td, args->initval, 0)); } #endif int linux_eventfd2(struct thread *td, struct linux_eventfd2_args *args) { - struct specialfd_eventfd ae; - int flags; + int flags = 0; if ((args->flags & ~(LINUX_O_CLOEXEC | LINUX_O_NONBLOCK | LINUX_EFD_SEMAPHORE)) != 0) return (EINVAL); - flags = 0; if ((args->flags & LINUX_O_CLOEXEC) != 0) flags |= EFD_CLOEXEC; if ((args->flags & LINUX_O_NONBLOCK) != 0) @@ -658,10 +652,7 @@ if ((args->flags & LINUX_EFD_SEMAPHORE) != 0) flags |= EFD_SEMAPHORE; - bzero(&ae, sizeof(ae)); - ae.flags = flags; - ae.initval = args->initval; - return (kern_specialfd(td, SPECIALFD_EVENTFD, &ae)); + return (eventfd_create_file(td, args->initval, flags)); } int diff --git a/sys/kern/sys_eventfd.c b/sys/kern/sys_eventfd.c --- a/sys/kern/sys_eventfd.c +++ b/sys/kern/sys_eventfd.c @@ -106,15 +106,24 @@ }; int -eventfd_create_file(struct thread *td, struct file *fp, uint32_t initval, - int flags) +eventfd_create_file(struct thread *td, uint32_t initval, int flags) { struct eventfd *efd; - int fflags; + struct file *fp; + int error, fd, fflags = 0; AUDIT_ARG_FFLAGS(flags); AUDIT_ARG_VALUE(initval); + if ((flags & ~(EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE)) != 0) + return (EINVAL); + if ((flags & EFD_CLOEXEC) != 0) + fflags |= O_CLOEXEC; + + error = falloc(td, &fp, &fd, fflags); + if (error != 0) + return (error); + efd = malloc(sizeof(*efd), M_EVENTFD, M_WAITOK | M_ZERO); efd->efd_flags = flags; efd->efd_count = initval; @@ -124,9 +133,12 @@ fflags = FREAD | FWRITE; if ((flags & EFD_NONBLOCK) != 0) fflags |= FNONBLOCK; + finit(fp, fflags, DTYPE_EVENTFD, efd, &eventfdops); + fdrop(fp, td); - return (0); + td->td_retval[0] = fd; + return (error); } static int diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -936,64 +936,37 @@ } int -kern_specialfd(struct thread *td, int type, void *arg) +user_eventfd(struct thread *td, const void *arg) { - struct file *fp; - struct specialfd_eventfd *ae; - int error, fd, fflags; + struct specialfd_eventfd efd; + int error; - fflags = 0; - error = falloc_noinstall(td, &fp); + error = copyin(arg, &efd, sizeof(efd)); if (error != 0) return (error); - switch (type) { - case SPECIALFD_EVENTFD: - ae = arg; - if ((ae->flags & EFD_CLOEXEC) != 0) - fflags |= O_CLOEXEC; - error = eventfd_create_file(td, fp, ae->initval, ae->flags); - break; - default: - error = EINVAL; - break; - } - - if (error == 0) - error = finstall(td, fp, &fd, fflags, NULL); - fdrop(fp, td); - if (error == 0) - td->td_retval[0] = fd; - return (error); + return (eventfd_create_file(td, efd.initval, efd.flags)); } int sys___specialfd(struct thread *td, struct __specialfd_args *args) { - struct specialfd_eventfd ae; - int error; + size_t arg_size; + int (*specialfd_func)(struct thread *, const void *); switch (args->type) { case SPECIALFD_EVENTFD: - if (args->len != sizeof(struct specialfd_eventfd)) { - error = EINVAL; - break; - } - error = copyin(args->req, &ae, sizeof(ae)); - if (error != 0) - break; - if ((ae.flags & ~(EFD_CLOEXEC | EFD_NONBLOCK | - EFD_SEMAPHORE)) != 0) { - error = EINVAL; - break; - } - error = kern_specialfd(td, args->type, &ae); + arg_size = sizeof(struct specialfd_eventfd); + specialfd_func = user_eventfd; break; default: - error = EINVAL; - break; + return (EINVAL); } - return (error); + + if (args->len != arg_size) + return (EINVAL); + + return (specialfd_func(td, args->req)); } int diff --git a/sys/sys/eventfd.h b/sys/sys/eventfd.h --- a/sys/sys/eventfd.h +++ b/sys/sys/eventfd.h @@ -38,8 +38,7 @@ #ifdef _KERNEL -int eventfd_create_file(struct thread *td, struct file *fp, uint32_t initval, - int flags); +int eventfd_create_file(struct thread *td, uint32_t initval, int flags); #else diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -321,7 +321,7 @@ int kern_statat(struct thread *td, int flag, int fd, const char *path, enum uio_seg pathseg, struct stat *sbp, void (*hook)(struct vnode *vp, struct stat *sbp)); -int kern_specialfd(struct thread *td, int type, void *arg); +int user_eventfd(struct thread *td, const void *arg); int kern_statfs(struct thread *td, const char *path, enum uio_seg pathseg, struct statfs *buf); int kern_symlinkat(struct thread *td, const char *path1, int fd,