Module Name: src Committed By: snj Date: Wed Jul 5 20:04:40 UTC 2017
Modified Files: src/sys/kern [netbsd-8]: kern_event.c src/sys/miscfs/genfs [netbsd-8]: genfs_vnops.c src/sys/sys [netbsd-8]: event.h Log Message: Pull up following revision(s) (requested by christos in ticket #91): sys/kern/kern_event.c: revision 1.92 sys/miscfs/genfs/genfs_vnops.c: revision 1.198 sys/sys/event.h: revision 1.30 Provide EVFILT_WRITE; this is what FreeBSD does and go wants it. Makes go unit tests pass. -- fix file descriptor locking (from joerg). fixes kernel crashes by running go To generate a diff of this commit: cvs rdiff -u -r1.91 -r1.91.2.1 src/sys/kern/kern_event.c cvs rdiff -u -r1.195.4.1 -r1.195.4.2 src/sys/miscfs/genfs/genfs_vnops.c cvs rdiff -u -r1.28 -r1.28.2.1 src/sys/sys/event.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_event.c diff -u src/sys/kern/kern_event.c:1.91 src/sys/kern/kern_event.c:1.91.2.1 --- src/sys/kern/kern_event.c:1.91 Thu May 11 23:50:17 2017 +++ src/sys/kern/kern_event.c Wed Jul 5 20:04:40 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_event.c,v 1.91 2017/05/11 23:50:17 christos Exp $ */ +/* $NetBSD: kern_event.c,v 1.91.2.1 2017/07/05 20:04:40 snj Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -58,7 +58,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.91 2017/05/11 23:50:17 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.91.2.1 2017/07/05 20:04:40 snj Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -1021,8 +1021,9 @@ kqueue_register(struct kqueue *kq, struc if (error != 0) { #ifdef DIAGNOSTIC - printf("%s: event not supported for file type" - " %d (error %d)\n", __func__, kn->kn_obj ? + printf("%s: event type %d not supported for " + "file type %d (error %d)\n", __func__, + kn->kn_filter, kn->kn_obj ? ((file_t *)kn->kn_obj)->f_type : -1, error); #endif /* knote_detach() drops fdp->fd_lock */ @@ -1204,10 +1205,19 @@ kqueue_scan(file_t *fp, size_t maxevents error = 0; } } + mutex_spin_exit(&kq->kq_lock); } else { /* mark end of knote list */ TAILQ_INSERT_TAIL(&kq->kq_head, marker, kn_tqe); + /* + * Acquire the fdp->fd_lock interlock to avoid races with + * file creation/destruction from other threads. + */ + mutex_spin_exit(&kq->kq_lock); + mutex_enter(&fdp->fd_lock); + mutex_spin_enter(&kq->kq_lock); + while (count != 0) { kn = TAILQ_FIRST(&kq->kq_head); /* get next knote */ while ((kn->kn_status & KN_MARKER) != 0) { @@ -1218,6 +1228,7 @@ kqueue_scan(file_t *fp, size_t maxevents (timeout = gettimeleft(&ats, &sleepts)) <= 0)) goto done; + mutex_exit(&fdp->fd_lock); goto retry; } /* someone else's marker. */ @@ -1239,6 +1250,7 @@ kqueue_scan(file_t *fp, size_t maxevents KASSERT(kn->kn_fop != NULL); KASSERT(kn->kn_fop->f_event != NULL); KERNEL_LOCK(1, NULL); /* XXXSMP */ + KASSERT(mutex_owned(&fdp->fd_lock)); rv = (*kn->kn_fop->f_event)(kn, 0); KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */ mutex_spin_enter(&kq->kq_lock); @@ -1261,10 +1273,10 @@ kqueue_scan(file_t *fp, size_t maxevents nkev++; if (kn->kn_flags & EV_ONESHOT) { /* delete ONESHOT events after retrieval */ - mutex_spin_exit(&kq->kq_lock); - mutex_enter(&fdp->fd_lock); kn->kn_status &= ~KN_BUSY; + mutex_spin_exit(&kq->kq_lock); knote_detach(kn, fdp, true); + mutex_enter(&fdp->fd_lock); mutex_spin_enter(&kq->kq_lock); } else if (kn->kn_flags & EV_CLEAR) { /* clear state after retrieval */ @@ -1286,9 +1298,11 @@ kqueue_scan(file_t *fp, size_t maxevents if (nkev == kevcnt) { /* do copyouts in kevcnt chunks */ mutex_spin_exit(&kq->kq_lock); + mutex_exit(&fdp->fd_lock); error = (*keops->keo_put_events) (keops->keo_private, kevbuf, ulistp, nevents, nkev); + mutex_enter(&fdp->fd_lock); mutex_spin_enter(&kq->kq_lock); nevents += nkev; nkev = 0; @@ -1301,9 +1315,10 @@ kqueue_scan(file_t *fp, size_t maxevents break; } } - } done: - mutex_spin_exit(&kq->kq_lock); + mutex_spin_exit(&kq->kq_lock); + mutex_exit(&fdp->fd_lock); + } if (nkev != 0) { /* copyout remaining events */ error = (*keops->keo_put_events)(keops->keo_private, Index: src/sys/miscfs/genfs/genfs_vnops.c diff -u src/sys/miscfs/genfs/genfs_vnops.c:1.195.4.1 src/sys/miscfs/genfs/genfs_vnops.c:1.195.4.2 --- src/sys/miscfs/genfs/genfs_vnops.c:1.195.4.1 Sun Jun 4 20:35:01 2017 +++ src/sys/miscfs/genfs/genfs_vnops.c Wed Jul 5 20:04:40 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: genfs_vnops.c,v 1.195.4.1 2017/06/04 20:35:01 bouyer Exp $ */ +/* $NetBSD: genfs_vnops.c,v 1.195.4.2 2017/07/05 20:04:40 snj Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.195.4.1 2017/06/04 20:35:01 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.195.4.2 2017/07/05 20:04:40 snj Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -500,6 +500,32 @@ filt_genfsread(struct knote *kn, long hi } static int +filt_genfswrite(struct knote *kn, long hint) +{ + struct vnode *vp = (struct vnode *)kn->kn_hook; + + /* + * filesystem is gone, so set the EOF flag and schedule + * the knote for deletion. + */ + switch (hint) { + case NOTE_REVOKE: + KASSERT(mutex_owned(vp->v_interlock)); + kn->kn_flags |= (EV_EOF | EV_ONESHOT); + return (1); + case 0: + mutex_enter(vp->v_interlock); + kn->kn_data = 0; + mutex_exit(vp->v_interlock); + return 1; + default: + KASSERT(mutex_owned(vp->v_interlock)); + kn->kn_data = 0; + return 1; + } +} + +static int filt_genfsvnode(struct knote *kn, long hint) { struct vnode *vp = (struct vnode *)kn->kn_hook; @@ -530,6 +556,8 @@ filt_genfsvnode(struct knote *kn, long h static const struct filterops genfsread_filtops = { 1, NULL, filt_genfsdetach, filt_genfsread }; +static const struct filterops genfswrite_filtops = + { 1, NULL, filt_genfsdetach, filt_genfswrite }; static const struct filterops genfsvnode_filtops = { 1, NULL, filt_genfsdetach, filt_genfsvnode }; @@ -549,6 +577,9 @@ genfs_kqfilter(void *v) case EVFILT_READ: kn->kn_fop = &genfsread_filtops; break; + case EVFILT_WRITE: + kn->kn_fop = &genfswrite_filtops; + break; case EVFILT_VNODE: kn->kn_fop = &genfsvnode_filtops; break; Index: src/sys/sys/event.h diff -u src/sys/sys/event.h:1.28 src/sys/sys/event.h:1.28.2.1 --- src/sys/sys/event.h:1.28 Fri Jun 2 19:44:06 2017 +++ src/sys/sys/event.h Wed Jul 5 20:04:40 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: event.h,v 1.28 2017/06/02 19:44:06 kamil Exp $ */ +/* $NetBSD: event.h,v 1.28.2.1 2017/07/05 20:04:40 snj Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon <jle...@freebsd.org> @@ -187,10 +187,10 @@ struct knote { TAILQ_ENTRY(knote) kn_tqe; /* q: for struct kqueue */ struct kqueue *kn_kq; /* q: which queue we are on */ struct kevent kn_kevent; - uint32_t kn_status; - uint32_t kn_sfflags; /* saved filter flags */ - uintptr_t kn_sdata; /* saved data field */ - void *kn_obj; /* pointer to monitored obj */ + uint32_t kn_status; /* q: flags below */ + uint32_t kn_sfflags; /* saved filter flags */ + uintptr_t kn_sdata; /* saved data field */ + void *kn_obj; /* monitored obj */ const struct filterops *kn_fop; struct kfilter *kn_kfilter; void *kn_hook; @@ -200,7 +200,8 @@ struct knote { #define KN_DISABLED 0x04U /* event is disabled */ #define KN_DETACHED 0x08U /* knote is detached */ #define KN_MARKER 0x10U /* is a marker */ -#define KN_BUSY 0x20U /* is being scanned */ +#define KN_BUSY 0x20U /* is being scanned */ +/* Toggling KN_BUSY also requires kn_kq->kq_fdp->fd_lock. */ #define kn_id kn_kevent.ident #define kn_filter kn_kevent.filter