View | Details | Raw Unified | Return to bug 240590 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/compat/linux/linux_event.c (-31 / +45 lines)
Lines 98-111 __attribute__((packed)) Link Here
98
#define	LINUX_MAX_EVENTS	(INT_MAX / sizeof(struct epoll_event))
98
#define	LINUX_MAX_EVENTS	(INT_MAX / sizeof(struct epoll_event))
99
99
100
static void	epoll_fd_install(struct thread *td, int fd, epoll_udata_t udata);
100
static void	epoll_fd_install(struct thread *td, int fd, epoll_udata_t udata);
101
static int	epoll_to_kevent(struct thread *td, struct file *epfp,
101
static int	epoll_to_kevent(struct thread *td, int fd,
102
		    int fd, struct epoll_event *l_event, int *kev_flags,
102
		    struct epoll_event *l_event, struct kevent *kevent,
103
		    struct kevent *kevent, int *nkevents);
103
		    int *nkevents);
104
static void	kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event);
104
static void	kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event);
105
static int	epoll_kev_copyout(void *arg, struct kevent *kevp, int count);
105
static int	epoll_kev_copyout(void *arg, struct kevent *kevp, int count);
106
static int	epoll_kev_copyin(void *arg, struct kevent *kevp, int count);
106
static int	epoll_kev_copyin(void *arg, struct kevent *kevp, int count);
107
static int	epoll_delete_event(struct thread *td, struct file *epfp,
107
static int	epoll_register_kevent(struct thread *td, struct file *epfp,
108
		    int fd, int filter);
108
		    int fd, int filter, unsigned int flags);
109
static int	epoll_fd_registered(struct thread *td, struct file *epfp,
110
		    int fd);
109
static int	epoll_delete_all_events(struct thread *td, struct file *epfp,
111
static int	epoll_delete_all_events(struct thread *td, struct file *epfp,
110
		    int fd);
112
		    int fd);
111
113
Lines 296-326 linux_epoll_create1(struct thread *td, struct linux_epoll_create1_args *args) Link Here
296
298
297
/* Structure converting function from epoll to kevent. */
299
/* Structure converting function from epoll to kevent. */
298
static int
300
static int
299
epoll_to_kevent(struct thread *td, struct file *epfp,
301
epoll_to_kevent(struct thread *td, int fd, struct epoll_event *l_event,
300
    int fd, struct epoll_event *l_event, int *kev_flags,
301
    struct kevent *kevent, int *nkevents)
302
    struct kevent *kevent, int *nkevents)
302
{
303
{
303
	uint32_t levents = l_event->events;
304
	uint32_t levents = l_event->events;
304
	struct linux_pemuldata *pem;
305
	struct linux_pemuldata *pem;
305
	struct proc *p;
306
	struct proc *p;
307
	unsigned short kev_flags = EV_ADD | EV_ENABLE;
306
308
307
	/* flags related to how event is registered */
309
	/* flags related to how event is registered */
308
	if ((levents & LINUX_EPOLLONESHOT) != 0)
310
	if ((levents & LINUX_EPOLLONESHOT) != 0)
309
		*kev_flags |= EV_DISPATCH;
311
		kev_flags |= EV_DISPATCH;
310
	if ((levents & LINUX_EPOLLET) != 0)
312
	if ((levents & LINUX_EPOLLET) != 0)
311
		*kev_flags |= EV_CLEAR;
313
		kev_flags |= EV_CLEAR;
312
	if ((levents & LINUX_EPOLLERR) != 0)
314
	if ((levents & LINUX_EPOLLERR) != 0)
313
		*kev_flags |= EV_ERROR;
315
		kev_flags |= EV_ERROR;
314
	if ((levents & LINUX_EPOLLRDHUP) != 0)
316
	if ((levents & LINUX_EPOLLRDHUP) != 0)
315
		*kev_flags |= EV_EOF;
317
		kev_flags |= EV_EOF;
316
318
317
	/* flags related to what event is registered */
319
	/* flags related to what event is registered */
318
	if ((levents & LINUX_EPOLL_EVRD) != 0) {
320
	if ((levents & LINUX_EPOLL_EVRD) != 0) {
319
		EV_SET(kevent++, fd, EVFILT_READ, *kev_flags, 0, 0, 0);
321
		EV_SET(kevent++, fd, EVFILT_READ, kev_flags, 0, 0, 0);
320
		++(*nkevents);
322
		++(*nkevents);
321
	}
323
	}
322
	if ((levents & LINUX_EPOLL_EVWR) != 0) {
324
	if ((levents & LINUX_EPOLL_EVWR) != 0) {
323
		EV_SET(kevent++, fd, EVFILT_WRITE, *kev_flags, 0, 0, 0);
325
		EV_SET(kevent++, fd, EVFILT_WRITE, kev_flags, 0, 0, 0);
326
		++(*nkevents);
327
	}
328
	/* zero event mask is legal */
329
	if ((levents & (LINUX_EPOLL_EVRD | LINUX_EPOLL_EVWR)) == 0) {
330
		EV_SET(kevent++, fd, EVFILT_READ, EV_ADD|EV_DISABLE, 0, 0, 0);
324
		++(*nkevents);
331
		++(*nkevents);
325
	}
332
	}
326
333
Lines 451-457 linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args) Link Here
451
					epoll_kev_copyin};
458
					epoll_kev_copyin};
452
	struct epoll_event le;
459
	struct epoll_event le;
453
	cap_rights_t rights;
460
	cap_rights_t rights;
454
	int kev_flags;
455
	int nchanges = 0;
461
	int nchanges = 0;
456
	int error;
462
	int error;
457
463
Lines 484-492 linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args) Link Here
484
	ciargs.changelist = kev;
490
	ciargs.changelist = kev;
485
491
486
	if (args->op != LINUX_EPOLL_CTL_DEL) {
492
	if (args->op != LINUX_EPOLL_CTL_DEL) {
487
		kev_flags = EV_ADD | EV_ENABLE;
493
		error = epoll_to_kevent(td, args->fd, &le, kev, &nchanges);
488
		error = epoll_to_kevent(td, epfp, args->fd, &le,
489
		    &kev_flags, kev, &nchanges);
490
		if (error != 0)
494
		if (error != 0)
491
			goto leave0;
495
			goto leave0;
492
	}
496
	}
Lines 499-517 linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args) Link Here
499
		break;
503
		break;
500
504
501
	case LINUX_EPOLL_CTL_ADD:
505
	case LINUX_EPOLL_CTL_ADD:
502
		/*
506
		if (epoll_fd_registered(td, epfp, args->fd)) {
503
		 * kqueue_register() return ENOENT if event does not exists
504
		 * and the EV_ADD flag is not set. Reset EV_ENABLE flag to
505
		 * avoid accidental activation of fired oneshot events.
506
		 */
507
		kev[0].flags &= ~(EV_ADD | EV_ENABLE);
508
		error = kqfd_register(args->epfd, &kev[0], td, M_WAITOK);
509
		if (error != ENOENT) {
510
			error = EEXIST;
507
			error = EEXIST;
511
			goto leave0;
508
			goto leave0;
512
		}
509
		}
513
		error = 0;
514
		kev[0].flags |= (EV_ADD | EV_ENABLE);
515
		break;
510
		break;
516
511
517
	case LINUX_EPOLL_CTL_DEL:
512
	case LINUX_EPOLL_CTL_DEL:
Lines 651-657 linux_epoll_pwait(struct thread *td, struct linux_epoll_pwait_args *args) Link Here
651
}
646
}
652
647
653
static int
648
static int
654
epoll_delete_event(struct thread *td, struct file *epfp, int fd, int filter)
649
epoll_register_kevent(struct thread *td, struct file *epfp, int fd, int filter,
650
    unsigned int flags)
655
{
651
{
656
	struct epoll_copyin_args ciargs;
652
	struct epoll_copyin_args ciargs;
657
	struct kevent kev;
653
	struct kevent kev;
Lines 660-677 epoll_delete_event(struct thread *td, struct file *epfp, int fd, int filter) Link Here
660
					epoll_kev_copyin};
656
					epoll_kev_copyin};
661
657
662
	ciargs.changelist = &kev;
658
	ciargs.changelist = &kev;
663
	EV_SET(&kev, fd, filter, EV_DELETE | EV_DISABLE, 0, 0, 0);
659
	EV_SET(&kev, fd, filter, flags, 0, 0, 0);
664
660
665
	return (kern_kevent_fp(td, epfp, 1, 0, &k_ops, NULL));
661
	return (kern_kevent_fp(td, epfp, 1, 0, &k_ops, NULL));
666
}
662
}
667
663
664
static int
665
epoll_fd_registered(struct thread *td, struct file *epfp, int fd)
666
{
667
	/*
668
	 * Set empty filter flags to avoid accidental modification of already
669
	 * registered events. In the case of re-registration:
670
	 * 1. If event does not exists kevent() does nothing and returns ENOENT
671
	 * 2. If event does exists, it's enabled/disabled state is preserved
672
	 *    but fflags, data and udata fields are overwritten.
673
	 * p.2 means that we can not store user's context pointer in udata.
674
	 */
675
	if (epoll_register_kevent(td, epfp, fd, EVFILT_READ, 0) != ENOENT ||
676
	    epoll_register_kevent(td, epfp, fd, EVFILT_WRITE, 0) != ENOENT)
677
		return (1);
678
679
	return (0);
680
}
681
668
static int
682
static int
669
epoll_delete_all_events(struct thread *td, struct file *epfp, int fd)
683
epoll_delete_all_events(struct thread *td, struct file *epfp, int fd)
670
{
684
{
671
	int error1, error2;
685
	int error1, error2;
672
686
673
	error1 = epoll_delete_event(td, epfp, fd, EVFILT_READ);
687
	error1 = epoll_register_kevent(td, epfp, fd, EVFILT_READ, EV_DELETE);
674
	error2 = epoll_delete_event(td, epfp, fd, EVFILT_WRITE);
688
	error2 = epoll_register_kevent(td, epfp, fd, EVFILT_WRITE, EV_DELETE);
675
689
676
	/* return 0 if at least one result positive */
690
	/* return 0 if at least one result positive */
677
	return (error1 == 0 ? 0 : error2);
691
	return (error1 == 0 ? 0 : error2);
(-)b/sys/compat/linux/linux_event.h (-2 / +2 lines)
Lines 45-54 Link Here
45
#define	LINUX_EPOLLONESHOT	1u<<30
45
#define	LINUX_EPOLLONESHOT	1u<<30
46
#define	LINUX_EPOLLET		1u<<31
46
#define	LINUX_EPOLLET		1u<<31
47
47
48
#define	LINUX_EPOLL_EVRD	(LINUX_EPOLLIN|LINUX_EPOLLRDNORM	\
48
#define	LINUX_EPOLL_EVRD	(LINUX_EPOLLIN|LINUX_EPOLLRDNORM)
49
		|LINUX_EPOLLHUP|LINUX_EPOLLERR|LINUX_EPOLLPRI)
50
#define	LINUX_EPOLL_EVWR	(LINUX_EPOLLOUT|LINUX_EPOLLWRNORM)
49
#define	LINUX_EPOLL_EVWR	(LINUX_EPOLLOUT|LINUX_EPOLLWRNORM)
51
#define	LINUX_EPOLL_EVSUP	(LINUX_EPOLLET|LINUX_EPOLLONESHOT	\
50
#define	LINUX_EPOLL_EVSUP	(LINUX_EPOLLET|LINUX_EPOLLONESHOT	\
51
		|LINUX_EPOLLHUP|LINUX_EPOLLERR|LINUX_EPOLLPRI		\
52
		|LINUX_EPOLL_EVRD|LINUX_EPOLL_EVWR|LINUX_EPOLLRDHUP)
52
		|LINUX_EPOLL_EVRD|LINUX_EPOLL_EVWR|LINUX_EPOLLRDHUP)
53
53
54
#define	LINUX_EPOLL_CTL_ADD	1
54
#define	LINUX_EPOLL_CTL_ADD	1

Return to bug 240590