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

Reply via email to