On Wed, Sep 18, 2013 at 08:46:48PM +0200, Mateusz Guzik wrote: > On Wed, Sep 18, 2013 at 05:56:04PM +0000, Roman Divacky wrote: > > Author: rdivacky > > Date: Wed Sep 18 17:56:04 2013 > > New Revision: 255672 > > URL: http://svnweb.freebsd.org/changeset/base/255672 > > > > Log: > > Implement epoll support in Linuxulator. This is a tiny wrapper around > > kqueue > > to implement epoll subset of functionality. The kqueue user data are 32bit > > on i386 which is not enough for epoll user data so this patch overrides > > kqueue fileops to maintain enough space in struct file. > > > > Initial patch developed by me in 2007 and then extended and finished > > by Yuri Victorovich. > > >
I'm strongly dislike a hacking kqueue file ops. I would prefer more generic mechanism. Maybe we need a emulator file ops in struct file, or a per proc list of such files. Any ideas? > First of all thank you both for doing this work. > > I have some important though (I didn't spend too much on this, so maybe > I missed some stuff or what I write here is incorrect). > > In general some lines are longer than 80 characters and simple stile > violations are present ("if (!error)"). > > > +/* Create a new epoll file descriptor. */ > > + > > +static int > > +linux_epoll_create_common(struct thread *td) > > +{ > > + struct file *fp; > > + int error; > > + > > + error = kern_kqueue_locked(td, &fp); > > +#if EPOLL_WIDE_USER_DATA > > + if (error == 0) { > > + epoll_init_user_data(td, fp); > > + fdrop(fp, td); > > + } > > +#endif > > + return (error); > > +} > > This leaks fd reference if EPOLL_WIDE_USER_DATA is not defined. > > > +int > > +linux_epoll_create1(struct thread *td, struct linux_epoll_create1_args > > *args) > > +{ > > + int error; > > + > > + error = linux_epoll_create_common(td); > > + > > + if (!error) { > > + if (args->flags & LINUX_EPOLL_CLOEXEC) > > + > > td->td_proc->p_fd->fd_ofiles[td->td_retval[0]].fde_flags |= UF_EXCLOSE; > > This is very racy for no good reason. This should be passed down to > kqueue and be set on fd creation. > > > + if (args->flags & LINUX_EPOLL_NONBLOCK) > > + linux_msg(td, "epoll_create1 doesn't yet support > > EPOLL_NONBLOCK flag\n"); > > + } > > + > > + return (error); > > +} > > + > > + > > +static void > > +epoll_init_user_data(struct thread *td, struct file *epfp) > > +{ > > + struct epoll_user_data *udv; > > + > > + /* override file ops to have our close operation */ > > + atomic_store_rel_ptr((volatile uintptr_t *)&epfp->f_ops, > > (uintptr_t)&epollops); > > + > > + /* allocate epoll_user_data initially for up to 16 file descriptor > > values */ > > + udv = malloc(EPOLL_USER_DATA_SIZE(EPOLL_USER_DATA_MARGIN), > > M_LINUX_EPOLL, M_WAITOK); > > + udv->sz = EPOLL_USER_DATA_MARGIN; > > + EPOLL_USER_DATA_SET(epfp, udv); > > +} > > Is not this racy? There is a window when fd is installed with epoll ops, > yet no userdata is allocated. > > > +/*ARGSUSED*/ > > +static int > > +epoll_close(struct file *epfp, struct thread *td) > > +{ > > + /* free user data vector */ > > + free(EPOLL_USER_DATA_GET(epfp), M_LINUX_EPOLL); > > + /* over to kqueue parent */ > > + return (kqueue_close(epfp, td)); > > +} > > +#endif > > Unnecessary comments. > > > + > > +static struct file* > > +epoll_fget(struct thread *td, int epfd) > > +{ > > + struct file *fp; > > + cap_rights_t rights; > > + > > + if (fget(td, epfd, cap_rights_init(&rights, CAP_POLL_EVENT), &fp) != 0) > > + panic("epoll: no file object found for kqueue descriptor"); > > + > > + return (fp); > > +} > > + > > Callers pass arbitrary fd here (provided by the user), yet this panics > if fd is bad. > > > int > > +kern_kqueue(struct thread *td) > > +{ > > + struct file *fp; > > + int error; > > + > > + error = kern_kqueue_locked(td, &fp); > > + > > Why is this _locked? Typically such naming is used when some locks are > held around the call. > > > + fdrop(fp, td); > > If there was an error, fdrop is called even though there is nothing to > fdrop. > > > + return (error); > > +} > > > -- > Mateusz Guzik <mjguzik gmail.com> -- Have fun! chd
pgp4PKIssVjdZ.pgp
Description: PGP signature