Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-7-0]: src/sys Pull up following revision(s) (requested by christo...
details: https://anonhg.NetBSD.org/src/rev/78fd9d19ae28
branches: netbsd-7-0
changeset: 801333:78fd9d19ae28
user: snj <snj%NetBSD.org@localhost>
date: Sat Jul 08 16:51:56 2017 +0000
description:
Pull up following revision(s) (requested by christos in ticket #1442):
sys/kern/kern_event.c: revision 1.92 via patch
sys/miscfs/genfs/genfs_vnops.c: revision 1.198 via patch
sys/sys/event.h: revision 1.30 via patch
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
diffstat:
sys/kern/kern_event.c | 116 +++++++++++++++++++++++++-------------
sys/miscfs/genfs/genfs_vnops.c | 35 +++++++++++-
sys/sys/event.h | 123 ++++++++++++++++++++++-------------------
3 files changed, 175 insertions(+), 99 deletions(-)
diffs (truncated from 585 to 300 lines):
diff -r 69cfa7dbd0dc -r 78fd9d19ae28 sys/kern/kern_event.c
--- a/sys/kern/kern_event.c Sat Jul 08 16:32:05 2017 +0000
+++ b/sys/kern/kern_event.c Sat Jul 08 16:51:56 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_event.c,v 1.80.2.1 2015/04/14 04:39:58 snj Exp $ */
+/* $NetBSD: kern_event.c,v 1.80.2.1.2.1 2017/07/08 16:51:56 snj Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -58,11 +58,12 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.80.2.1 2015/04/14 04:39:58 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.80.2.1.2.1 2017/07/08 16:51:56 snj Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/wait.h>
#include <sys/proc.h>
#include <sys/file.h>
#include <sys/select.h>
@@ -779,7 +780,7 @@
* kevent(2) system call.
*/
int
-kevent_fetch_changes(void *private, const struct kevent *changelist,
+kevent_fetch_changes(void *ctx, const struct kevent *changelist,
struct kevent *changes, size_t index, int n)
{
@@ -787,7 +788,7 @@
}
int
-kevent_put_events(void *private, struct kevent *events,
+kevent_put_events(void *ctx, struct kevent *events,
struct kevent *eventlist, size_t index, int n)
{
@@ -851,7 +852,7 @@
timeout = &ts;
}
- kq = (struct kqueue *)fp->f_data;
+ kq = fp->f_data;
nerrors = 0;
ichange = 0;
@@ -867,21 +868,19 @@
kevp->flags &= ~EV_SYSFLAGS;
/* register each knote */
error = kqueue_register(kq, kevp);
- if (error) {
- if (nevents != 0) {
- kevp->flags = EV_ERROR;
- kevp->data = error;
- error = (*keops->keo_put_events)
- (keops->keo_private, kevp,
- eventlist, nerrors, 1);
- if (error)
- goto done;
- nevents--;
- nerrors++;
- } else {
- goto done;
- }
- }
+ if (!error && !(kevp->flags & EV_RECEIPT))
+ continue;
+ if (nevents == 0)
+ goto done;
+ kevp->flags = EV_ERROR;
+ kevp->data = error;
+ error = (*keops->keo_put_events)
+ (keops->keo_private, kevp,
+ eventlist, nerrors, 1);
+ if (error)
+ goto done;
+ nevents--;
+ nerrors++;
}
nchanges -= n; /* update the results */
ichange += n;
@@ -934,8 +933,9 @@
/* search if knote already exists */
if (kfilter->filtops->f_isfd) {
/* monitoring a file descriptor */
- fd = kev->ident;
- if ((fp = fd_getfile(fd)) == NULL) {
+ /* validate descriptor */
+ if (kev->ident > INT_MAX
+ || (fp = fd_getfile(fd = kev->ident)) == NULL) {
rw_exit(&kqueue_filter_lock);
kmem_free(newkn, sizeof(*newkn));
return EBADF;
@@ -986,6 +986,7 @@
kev->data = 0;
kn->kn_kevent = *kev;
+ KASSERT(kn->kn_fop != NULL);
/*
* apply reference count to knote structure, and
* do not release it at the end of this routine.
@@ -1019,8 +1020,11 @@
KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
if (error != 0) {
#ifdef DIAGNOSTIC
- printf("%s: event not supported for file type"
- " %d\n", __func__, fp ? fp->f_type : -1);
+
+ 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 */
knote_detach(kn, fdp, false);
@@ -1043,6 +1047,7 @@
* support events, and the attach routine is
* broken and does not return an error.
*/
+ KASSERT(kn->kn_fop != NULL);
KASSERT(kn->kn_fop->f_event != NULL);
KERNEL_LOCK(1, NULL); /* XXXSMP */
rv = (*kn->kn_fop->f_event)(kn, 0);
@@ -1150,7 +1155,7 @@
struct kqueue *kq;
struct kevent *kevp;
struct timespec ats, sleepts;
- struct knote *kn, *marker;
+ struct knote *kn, *marker, morker;
size_t count, nkev, nevents;
int timeout, error, rv;
filedesc_t *fdp;
@@ -1178,7 +1183,8 @@
timeout = 0;
}
- marker = kmem_zalloc(sizeof(*marker), KM_SLEEP);
+ memset(&morker, 0, sizeof(morker));
+ marker = &morker;
marker->kn_status = KN_MARKER;
mutex_spin_enter(&kq->kq_lock);
retry:
@@ -1199,10 +1205,19 @@
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) {
@@ -1213,35 +1228,43 @@
(timeout = gettimeleft(&ats,
&sleepts)) <= 0))
goto done;
+ mutex_exit(&fdp->fd_lock);
goto retry;
}
/* someone else's marker. */
kn = TAILQ_NEXT(kn, kn_tqe);
}
kq_check(kq);
+ kq->kq_count--;
TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
- kq->kq_count--;
kn->kn_status &= ~KN_QUEUED;
+ kn->kn_status |= KN_BUSY;
kq_check(kq);
if (kn->kn_status & KN_DISABLED) {
+ kn->kn_status &= ~KN_BUSY;
/* don't want disabled events */
continue;
}
if ((kn->kn_flags & EV_ONESHOT) == 0) {
mutex_spin_exit(&kq->kq_lock);
+ 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);
/* Re-poll if note was re-enqueued. */
- if ((kn->kn_status & KN_QUEUED) != 0)
+ if ((kn->kn_status & KN_QUEUED) != 0) {
+ kn->kn_status &= ~KN_BUSY;
continue;
+ }
if (rv == 0) {
/*
* non-ONESHOT event that hasn't
* triggered again, so de-queue.
*/
- kn->kn_status &= ~KN_ACTIVE;
+ kn->kn_status &= ~(KN_ACTIVE|KN_BUSY);
continue;
}
}
@@ -1250,29 +1273,36 @@
nkev++;
if (kn->kn_flags & EV_ONESHOT) {
/* delete ONESHOT events after retrieval */
+ kn->kn_status &= ~KN_BUSY;
mutex_spin_exit(&kq->kq_lock);
+ knote_detach(kn, fdp, true);
mutex_enter(&fdp->fd_lock);
- knote_detach(kn, fdp, true);
mutex_spin_enter(&kq->kq_lock);
} else if (kn->kn_flags & EV_CLEAR) {
/* clear state after retrieval */
kn->kn_data = 0;
kn->kn_fflags = 0;
- kn->kn_status &= ~KN_ACTIVE;
+ kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE|KN_BUSY);
+ } else if (kn->kn_flags & EV_DISPATCH) {
+ kn->kn_status |= KN_DISABLED;
+ kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE|KN_BUSY);
} else {
/* add event back on list */
kq_check(kq);
+ kn->kn_status |= KN_QUEUED;
+ kn->kn_status &= ~KN_BUSY;
TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
kq->kq_count++;
- kn->kn_status |= KN_QUEUED;
kq_check(kq);
}
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;
@@ -1285,11 +1315,10 @@
break;
}
}
+ done:
+ mutex_spin_exit(&kq->kq_lock);
+ mutex_exit(&fdp->fd_lock);
}
- done:
- mutex_spin_exit(&kq->kq_lock);
- if (marker != NULL)
- kmem_free(marker, sizeof(*marker));
if (nkev != 0) {
/* copyout remaining events */
error = (*keops->keo_put_events)(keops->keo_private,
@@ -1510,6 +1539,8 @@
struct knote *kn, *tmpkn;
SLIST_FOREACH_SAFE(kn, list, kn_selnext, tmpkn) {
+ KASSERT(kn->kn_fop != NULL);
+ KASSERT(kn->kn_fop->f_event != NULL);
if ((*kn->kn_fop->f_event)(kn, hint))
knote_activate(kn);
}
@@ -1550,8 +1581,10 @@
KASSERT((kn->kn_status & KN_MARKER) == 0);
KASSERT(mutex_owned(&fdp->fd_lock));
+ KASSERT(kn->kn_fop != NULL);
/* Remove from monitored object. */
if (dofop) {
+ KASSERT(kn->kn_fop->f_detach != NULL);
KERNEL_LOCK(1, NULL); /* XXXSMP */
(*kn->kn_fop->f_detach)(kn);
KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
@@ -1566,14 +1599,17 @@
SLIST_REMOVE(list, kn, knote, kn_link);
/* Remove from kqueue. */
- /* XXXAD should verify not in use by kqueue_scan. */
+again:
mutex_spin_enter(&kq->kq_lock);
if ((kn->kn_status & KN_QUEUED) != 0) {
kq_check(kq);
+ kq->kq_count--;
TAILQ_REMOVE(&kq->kq_head, kn, kn_tqe);
kn->kn_status &= ~KN_QUEUED;
Home |
Main Index |
Thread Index |
Old Index