fix file descriptor locking (from joerg).
fixes kernel crashes by running go XXX: pullup-7
This commit is contained in:
parent
f36a117b25
commit
c4aed00fad
|
@ -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.92 2017/07/01 20:08:56 christos 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.92 2017/07/01 20:08:56 christos Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -1021,8 +1021,9 @@ kqueue_register(struct kqueue *kq, struct kevent *kev)
|
|||
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, struct kevent *ulistp,
|
|||
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, struct kevent *ulistp,
|
|||
(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, struct kevent *ulistp,
|
|||
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, struct kevent *ulistp,
|
|||
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, struct kevent *ulistp,
|
|||
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, struct kevent *ulistp,
|
|||
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,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: event.h,v 1.29 2017/06/14 16:37:05 christos Exp $ */
|
||||
/* $NetBSD: event.h,v 1.30 2017/07/01 20:08:56 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
|
||||
|
@ -188,10 +188,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;
|
||||
|
@ -201,7 +201,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
|
||||
|
|
Loading…
Reference in New Issue