Index: kern_event.c =================================================================== RCS file: /home/joerg/repo/netbsd/src/sys/kern/kern_event.c,v retrieving revision 1.91 diff -u -p -r1.91 kern_event.c --- kern_event.c 11 May 2017 23:50:17 -0000 1.91 +++ kern_event.c 30 Jun 2017 14:35:15 -0000 @@ -1204,10 +1204,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 +1227,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 +1249,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 +1272,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 +1297,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 +1314,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,