Ran into problems with running kqueue/aio with WITNESS etc. Sometimes things are locked sometimes not. knlist_remove is called telling it whether it is locked or not ie: extern void knlist_remove(struct knlist *knl, struct knote *kn, int islocked); so I changed: extern int knlist_empty(struct knlist *knl); to: extern int knlist_empty(struct knlist *knl, int islocked); and then updated things to reflect that following what that state of the lock for knlist_remove. If it is not locked, it gets a lock and frees it after. This now fixes a panic when a process using kqueue/aio is killed on shutdown with WITNESS. It changes an API/ABI so it probably can't merged back. If there are no objections then I'll commit it. Here is the patch: Index: fs/fifofs/fifo_vnops.c =================================================================== RCS file: /cvs/src/sys/fs/fifofs/fifo_vnops.c,v retrieving revision 1.157 diff -u -p -r1.157 fifo_vnops.c --- fs/fifofs/fifo_vnops.c 16 Aug 2011 20:07:47 -0000 1.157 +++ fs/fifofs/fifo_vnops.c 26 Jan 2012 20:50:31 -0000 _at__at_ -324,7 +324,7 _at__at_ filt_fifordetach(struct knote *kn) SOCKBUF_LOCK(&so->so_rcv); knlist_remove(&so->so_rcv.sb_sel.si_note, kn, 1); - if (knlist_empty(&so->so_rcv.sb_sel.si_note)) + if (knlist_empty(&so->so_rcv.sb_sel.si_note, 1)) so->so_rcv.sb_flags &= ~SB_KNOTE; SOCKBUF_UNLOCK(&so->so_rcv); } _at__at_ -352,7 +352,7 _at__at_ filt_fifowdetach(struct knote *kn) SOCKBUF_LOCK(&so->so_snd); knlist_remove(&so->so_snd.sb_sel.si_note, kn, 1); - if (knlist_empty(&so->so_snd.sb_sel.si_note)) + if (knlist_empty(&so->so_snd.sb_sel.si_note, 1)) so->so_snd.sb_flags &= ~SB_KNOTE; SOCKBUF_UNLOCK(&so->so_snd); } Index: kern/kern_event.c =================================================================== RCS file: /cvs/src/sys/kern/kern_event.c,v retrieving revision 1.146 diff -u -p -r1.146 kern_event.c --- kern/kern_event.c 16 Sep 2011 13:58:51 -0000 1.146 +++ kern/kern_event.c 26 Jan 2012 20:50:31 -0000 _at__at_ -1650,7 +1650,7 _at__at_ kqueue_close(struct file *fp, struct thr KASSERT(kq->kq_refcnt == 1, ("other refs are out there!")); fdp = kq->kq_fdp; - KASSERT(knlist_empty(&kq->kq_sel.si_note), + KASSERT(knlist_empty(&kq->kq_sel.si_note, 1), ("kqueue's knlist not empty")); for (i = 0; i < kq->kq_knlistsize; i++) { _at__at_ -1735,7 +1735,7 _at__at_ kqueue_wakeup(struct kqueue *kq) if (!SEL_WAITING(&kq->kq_sel)) kq->kq_state &= ~KQ_SEL; } - if (!knlist_empty(&kq->kq_sel.si_note)) + if (!knlist_empty(&kq->kq_sel.si_note, 1)) kqueue_schedtask(kq); if ((kq->kq_state & KQ_ASYNC) == KQ_ASYNC) { pgsigio(&kq->kq_sigio, SIGIO, 0); _at__at_ -1867,10 +1867,18 _at__at_ knlist_remove_inevent(struct knlist *knl } int -knlist_empty(struct knlist *knl) +knlist_empty(struct knlist *knl, int knlislocked) { - KNL_ASSERT_LOCKED(knl); - return SLIST_EMPTY(&knl->kl_list); + int error; + + KNL_ASSERT_LOCK(knl, knlislocked); + if (!knlislocked) + knl->kl_lock(knl->kl_lockarg); + error = SLIST_EMPTY(&knl->kl_list); + if (!knlislocked) + knl->kl_unlock(knl->kl_lockarg); + + return error; } static struct mtx knlist_lock; _at__at_ -1931,7 +1939,9 _at__at_ knlist_init(struct knlist *knl, void *lo else knl->kl_assert_unlocked = kl_assert_unlocked; + knl->kl_lock(knl->kl_lockarg); SLIST_INIT(&knl->kl_list); + knl->kl_unlock(knl->kl_lockarg); } void Index: kern/uipc_socket.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_socket.c,v retrieving revision 1.358 diff -u -p -r1.358 uipc_socket.c --- kern/uipc_socket.c 25 Aug 2011 15:51:54 -0000 1.358 +++ kern/uipc_socket.c 26 Jan 2012 20:50:31 -0000 _at__at_ -3188,7 +3188,7 _at__at_ filt_sordetach(struct knote *kn) SOCKBUF_LOCK(&so->so_rcv); knlist_remove(&so->so_rcv.sb_sel.si_note, kn, 1); - if (knlist_empty(&so->so_rcv.sb_sel.si_note)) + if (knlist_empty(&so->so_rcv.sb_sel.si_note, 1)) so->so_rcv.sb_flags &= ~SB_KNOTE; SOCKBUF_UNLOCK(&so->so_rcv); } _at__at_ -3222,7 +3222,7 _at__at_ filt_sowdetach(struct knote *kn) SOCKBUF_LOCK(&so->so_snd); knlist_remove(&so->so_snd.sb_sel.si_note, kn, 1); - if (knlist_empty(&so->so_snd.sb_sel.si_note)) + if (knlist_empty(&so->so_snd.sb_sel.si_note, 1)) so->so_snd.sb_flags &= ~SB_KNOTE; SOCKBUF_UNLOCK(&so->so_snd); } Index: kern/vfs_aio.c =================================================================== RCS file: /cvs/src/sys/kern/vfs_aio.c,v retrieving revision 1.249 diff -u -p -r1.249 vfs_aio.c --- kern/vfs_aio.c 16 Sep 2011 13:58:51 -0000 1.249 +++ kern/vfs_aio.c 26 Jan 2012 20:50:31 -0000 _at__at_ -2531,7 +2533,7 _at__at_ filt_aiodetach(struct knote *kn) { struct aiocblist *aiocbe = kn->kn_ptr.p_aio; - if (!knlist_empty(&aiocbe->klist)) + if (!knlist_empty(&aiocbe->klist, 0)) knlist_remove(&aiocbe->klist, kn, 0); } _at__at_ -2576,7 +2578,7 _at__at_ filt_liodetach(struct knote *kn) { struct aioliojob * lj = kn->kn_ptr.p_lio; - if (!knlist_empty(&lj->klist)) + if (!knlist_empty(&lj->klist, 0)) knlist_remove(&lj->klist, kn, 0); } Index: sys/event.h =================================================================== RCS file: /cvs/src/sys/sys/event.h,v retrieving revision 1.49 diff -u -p -r1.49 event.h --- sys/event.h 31 Dec 2009 20:29:58 -0000 1.49 +++ sys/event.h 26 Jan 2012 20:50:37 -0000 _at__at_ -244,7 +244,7 _at__at_ extern void knote_fork(struct knlist *li extern void knlist_add(struct knlist *knl, struct knote *kn, int islocked); extern void knlist_remove(struct knlist *knl, struct knote *kn, int islocked); extern void knlist_remove_inevent(struct knlist *knl, struct knote *kn); -extern int knlist_empty(struct knlist *knl); +extern int knlist_empty(struct knlist *knl, int islocked); extern void knlist_init(struct knlist *knl, void *lock, void (*kl_lock)(void *), void (*kl_unlock)(void *), void (*kl_assert_locked)(void *), void (*kl_assert_unlocked)(void *)); Thanks, Doug A.Received on Thu Jan 26 2012 - 20:32:03 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:23 UTC