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 <[email protected]>
@@ -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