visa@, mpi@, I'm asking you to review, because you are involved in the
kevent(9) development.

Hrvoje, if you want to test this diff, you need to disable pipex(4) with
"net.pipex.enable=0".

Index: sys/net/if_pppx.c
===================================================================
RCS file: /cvs/src/sys/net/if_pppx.c,v
retrieving revision 1.124
diff -u -p -r1.124 if_pppx.c
--- sys/net/if_pppx.c   26 Nov 2022 17:50:26 -0000      1.124
+++ sys/net/if_pppx.c   25 Jan 2023 19:30:51 -0000
@@ -56,7 +56,7 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <sys/vnode.h>
-#include <sys/selinfo.h>
+#include <sys/event.h>
 #include <sys/refcnt.h>
 
 #include <net/if.h>
@@ -125,10 +125,10 @@ struct pppx_dev {
        int                     pxd_unit;       /* [I] */
 
        /* kq shizz */
-       struct selinfo          pxd_rsel;
-       struct mutex            pxd_rsel_mtx;
-       struct selinfo          pxd_wsel;
-       struct mutex            pxd_wsel_mtx;
+       struct klist            pxd_rklist;
+       struct mutex            pxd_rklist_mtx;
+       struct klist            pxd_wklist;
+       struct mutex            pxd_wklist_mtx;
 
        /* queue of packets for userland to service - protected by splnet */
        struct mbuf_queue       pxd_svcq;
@@ -195,22 +195,40 @@ void              pppxattach(int);
 
 void           filt_pppx_rdetach(struct knote *);
 int            filt_pppx_read(struct knote *, long);
+int            filt_pppx_rmodify(struct kevent *kev, struct knote *kn);
+int            filt_pppx_rprocess(struct knote *kn, struct kevent *kev);
 
 const struct filterops pppx_rd_filtops = {
-       .f_flags        = FILTEROP_ISFD,
+       .f_flags        = FILTEROP_ISFD | FILTEROP_MPSAFE,
        .f_attach       = NULL,
        .f_detach       = filt_pppx_rdetach,
        .f_event        = filt_pppx_read,
+       .f_modify       = filt_pppx_rmodify,
+       .f_process      = filt_pppx_rprocess,
 };
 
 void           filt_pppx_wdetach(struct knote *);
 int            filt_pppx_write(struct knote *, long);
+int            filt_pppx_wmodify(struct kevent *kev, struct knote *kn);
+int            filt_pppx_wprocess(struct knote *kn, struct kevent *kev);
 
 const struct filterops pppx_wr_filtops = {
-       .f_flags        = FILTEROP_ISFD,
+       .f_flags        = FILTEROP_ISFD | FILTEROP_MPSAFE,
        .f_attach       = NULL,
        .f_detach       = filt_pppx_wdetach,
        .f_event        = filt_pppx_write,
+       .f_modify       = filt_pppx_wmodify,
+       .f_process      = filt_pppx_wprocess,
+};
+
+void           klist_pppx_assertlk(void *);
+int            klist_pppx_lock(void *);
+void           klist_pppx_unlock(void *, int);
+
+const struct klistops pppx_klistops = {
+       .klo_assertlk   = klist_pppx_assertlk,
+       .klo_lock       = klist_pppx_lock,
+       .klo_unlock     = klist_pppx_unlock,
 };
 
 struct pppx_dev *
@@ -257,8 +275,10 @@ pppxopen(dev_t dev, int flags, int mode,
        }
 
        pxd->pxd_unit = minor(dev);
-       mtx_init(&pxd->pxd_rsel_mtx, IPL_NET);
-       mtx_init(&pxd->pxd_wsel_mtx, IPL_NET);
+       mtx_init(&pxd->pxd_rklist_mtx, IPL_NET);
+       mtx_init(&pxd->pxd_wklist_mtx, IPL_NET);
+       klist_init(&pxd->pxd_rklist, &pppx_klistops, &pxd->pxd_rklist_mtx);
+       klist_init(&pxd->pxd_wklist, &pppx_klistops, &pxd->pxd_wklist_mtx);
        LIST_INIT(&pxd->pxd_pxis);
 
        mq_init(&pxd->pxd_svcq, 128, IPL_NET);
@@ -458,13 +478,13 @@ pppxkqfilter(dev_t dev, struct knote *kn
 
        switch (kn->kn_filter) {
        case EVFILT_READ:
-               mtx = &pxd->pxd_rsel_mtx;
-               klist = &pxd->pxd_rsel.si_note;
+               mtx = &pxd->pxd_rklist_mtx;
+               klist = &pxd->pxd_rklist;
                kn->kn_fop = &pppx_rd_filtops;
                break;
        case EVFILT_WRITE:
-               mtx = &pxd->pxd_wsel_mtx;
-               klist = &pxd->pxd_wsel.si_note;
+               mtx = &pxd->pxd_wklist_mtx;
+               klist = &pxd->pxd_wklist;
                kn->kn_fop = &pppx_wr_filtops;
                break;
        default:
@@ -484,11 +504,11 @@ void
 filt_pppx_rdetach(struct knote *kn)
 {
        struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook;
-       struct klist *klist = &pxd->pxd_rsel.si_note;
+       struct klist *klist = &pxd->pxd_rklist;
 
-       mtx_enter(&pxd->pxd_rsel_mtx);
+       mtx_enter(&pxd->pxd_rklist_mtx);
        klist_remove_locked(klist, kn);
-       mtx_leave(&pxd->pxd_rsel_mtx);
+       mtx_leave(&pxd->pxd_rklist_mtx);
 }
 
 int
@@ -501,15 +521,41 @@ filt_pppx_read(struct knote *kn, long hi
        return (kn->kn_data > 0);
 }
 
+int
+filt_pppx_rmodify(struct kevent *kev, struct knote *kn)
+{
+       struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook;
+       int rv;
+
+       mtx_enter(&pxd->pxd_rklist_mtx);
+       rv = knote_modify(kev, kn);
+       mtx_leave(&pxd->pxd_rklist_mtx);
+
+       return (rv);
+}
+
+int
+filt_pppx_rprocess(struct knote *kn, struct kevent *kev)
+{
+       struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook;
+       int rv;
+
+       mtx_enter(&pxd->pxd_rklist_mtx);
+       rv = knote_process(kn, kev);
+       mtx_leave(&pxd->pxd_rklist_mtx);
+
+       return (rv);
+}
+
 void
 filt_pppx_wdetach(struct knote *kn)
 {
        struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook;
-       struct klist *klist = &pxd->pxd_wsel.si_note;
+       struct klist *klist = &pxd->pxd_wklist;
 
-       mtx_enter(&pxd->pxd_wsel_mtx);
+       mtx_enter(&pxd->pxd_wklist_mtx);
        klist_remove_locked(klist, kn);
-       mtx_leave(&pxd->pxd_wsel_mtx);
+       mtx_leave(&pxd->pxd_wklist_mtx);
 }
 
 int
@@ -520,6 +566,57 @@ filt_pppx_write(struct knote *kn, long h
 }
 
 int
+filt_pppx_wmodify(struct kevent *kev, struct knote *kn)
+{
+       struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook;
+       int rv;
+
+       mtx_enter(&pxd->pxd_wklist_mtx);
+       rv = knote_modify(kev, kn);
+       mtx_leave(&pxd->pxd_wklist_mtx);
+
+       return (rv);
+}
+
+int
+filt_pppx_wprocess(struct knote *kn, struct kevent *kev)
+{
+       struct pppx_dev *pxd = (struct pppx_dev *)kn->kn_hook;
+       int rv;
+
+       mtx_enter(&pxd->pxd_wklist_mtx);
+       rv = knote_process(kn, kev);
+       mtx_leave(&pxd->pxd_wklist_mtx);
+
+       return (rv);
+}
+
+void
+klist_pppx_assertlk(void *arg)
+{
+       struct mutex *mtx = arg;
+
+       MUTEX_ASSERT_LOCKED(mtx);
+}
+
+int
+klist_pppx_lock(void *arg)
+{
+       struct mutex *mtx = arg;
+
+       mtx_enter(mtx);
+       return (1);
+}
+
+void
+klist_pppx_unlock(void *arg, int ls)
+{
+       struct mutex *mtx = arg;
+
+       mtx_leave(mtx);
+}
+
+int
 pppxclose(dev_t dev, int flags, int mode, struct proc *p)
 {
        struct pppx_dev *pxd;
@@ -536,6 +633,9 @@ pppxclose(dev_t dev, int flags, int mode
 
        mq_purge(&pxd->pxd_svcq);
 
+       klist_free(&pxd->pxd_rklist);
+       klist_free(&pxd->pxd_rklist);
+
        free(pxd, M_DEVBUF, sizeof(*pxd));
 
        return (0);
@@ -875,7 +975,9 @@ pppx_if_output(struct ifnet *ifp, struct
                                wakeup((caddr_t)pxi->pxi_dev);
                                pxi->pxi_dev->pxd_waiting = 0;
                        }
-                       selwakeup(&pxi->pxi_dev->pxd_rsel);
+                       mtx_enter(&pxi->pxi_dev->pxd_rklist_mtx);
+                       KNOTE(&pxi->pxi_dev->pxd_rklist, 0);
+                       mtx_leave(&pxi->pxi_dev->pxd_rklist_mtx);
                }
        }
 
@@ -928,10 +1030,10 @@ struct pppac_softc {
        LIST_ENTRY(pppac_softc)
                        sc_entry;       /* [K] */
 
-       struct mutex    sc_rsel_mtx;
-       struct selinfo  sc_rsel;
-       struct mutex    sc_wsel_mtx;
-       struct selinfo  sc_wsel;
+       struct mutex    sc_rklist_mtx;
+       struct klist    sc_rklist;
+       struct mutex    sc_wklist_mtx;
+       struct klist    sc_wklist;
 
        struct pipex_session
                        *sc_multicast_session;
@@ -944,22 +1046,40 @@ LIST_HEAD(pppac_list, pppac_softc);      /* [
 
 static void    filt_pppac_rdetach(struct knote *);
 static int     filt_pppac_read(struct knote *, long);
+int            filt_pppac_rmodify(struct kevent *kev, struct knote *kn);
+int            filt_pppac_rprocess(struct knote *kn, struct kevent *kev);
 
 static const struct filterops pppac_rd_filtops = {
-       .f_flags        = FILTEROP_ISFD,
+       .f_flags        = FILTEROP_ISFD | FILTEROP_MPSAFE,
        .f_attach       = NULL,
        .f_detach       = filt_pppac_rdetach,
-       .f_event        = filt_pppac_read
+       .f_event        = filt_pppac_read,
+       .f_modify       = filt_pppac_rmodify,
+       .f_process      = filt_pppac_rprocess,
 };
 
 static void    filt_pppac_wdetach(struct knote *);
 static int     filt_pppac_write(struct knote *, long);
+int            filt_pppac_wmodify(struct kevent *kev, struct knote *kn);
+int            filt_pppac_wprocess(struct knote *kn, struct kevent *kev);
 
 static const struct filterops pppac_wr_filtops = {
-       .f_flags        = FILTEROP_ISFD,
+       .f_flags        = FILTEROP_ISFD | FILTEROP_MPSAFE,
        .f_attach       = NULL,
        .f_detach       = filt_pppac_wdetach,
-       .f_event        = filt_pppac_write
+       .f_event        = filt_pppac_write,
+       .f_modify       = filt_pppac_wmodify,
+       .f_process      = filt_pppac_wprocess,
+};
+
+void           klist_pppac_assertlk(void *);
+int            klist_pppac_lock(void *);
+void           klist_pppac_unlock(void *, int);
+
+const struct klistops pppac_klistops = {
+       .klo_assertlk   = klist_pppac_assertlk,
+       .klo_lock       = klist_pppac_lock,
+       .klo_unlock     = klist_pppac_unlock,
 };
 
 static struct pppac_list pppac_devs = LIST_HEAD_INITIALIZER(pppac_devs);
@@ -1020,8 +1140,10 @@ pppacopen(dev_t dev, int flags, int mode
        session->ownersc = sc;
        sc->sc_multicast_session = session;
 
-       mtx_init(&sc->sc_rsel_mtx, IPL_SOFTNET);
-       mtx_init(&sc->sc_wsel_mtx, IPL_SOFTNET);
+       mtx_init(&sc->sc_rklist_mtx, IPL_SOFTNET);
+       mtx_init(&sc->sc_wklist_mtx, IPL_SOFTNET);
+       klist_init(&sc->sc_rklist, &pppac_klistops, &sc->sc_rklist_mtx);
+       klist_init(&sc->sc_wklist, &pppac_klistops, &sc->sc_wklist_mtx);
        mq_init(&sc->sc_mq, IFQ_MAXLEN, IPL_SOFTNET);
 
        ifp = &sc->sc_if;
@@ -1210,13 +1332,13 @@ pppackqfilter(dev_t dev, struct knote *k
 
        switch (kn->kn_filter) {
        case EVFILT_READ:
-               mtx = &sc->sc_rsel_mtx;
-               klist = &sc->sc_rsel.si_note;
+               mtx = &sc->sc_rklist_mtx;
+               klist = &sc->sc_rklist;
                kn->kn_fop = &pppac_rd_filtops;
                break;
        case EVFILT_WRITE:
-               mtx = &sc->sc_wsel_mtx;
-               klist = &sc->sc_wsel.si_note;
+               mtx = &sc->sc_wklist_mtx;
+               klist = &sc->sc_wklist;
                kn->kn_fop = &pppac_wr_filtops;
                break;
        default:
@@ -1236,11 +1358,11 @@ static void
 filt_pppac_rdetach(struct knote *kn)
 {
        struct pppac_softc *sc = kn->kn_hook;
-       struct klist *klist = &sc->sc_rsel.si_note;
+       struct klist *klist = &sc->sc_rklist;
 
-       mtx_enter(&sc->sc_rsel_mtx);
+       mtx_enter(&sc->sc_rklist_mtx);
        klist_remove_locked(klist, kn);
-       mtx_leave(&sc->sc_rsel_mtx);
+       mtx_leave(&sc->sc_rklist_mtx);
 }
 
 static int
@@ -1253,15 +1375,41 @@ filt_pppac_read(struct knote *kn, long h
        return (kn->kn_data > 0);
 }
 
+int
+filt_pppac_rmodify(struct kevent *kev, struct knote *kn)
+{
+       struct pppac_softc *sc = kn->kn_hook;
+       int rv;
+
+       mtx_enter(&sc->sc_rklist_mtx);
+       rv = knote_modify(kev, kn);
+       mtx_leave(&sc->sc_rklist_mtx);
+
+       return (rv);
+}
+
+int
+filt_pppac_rprocess(struct knote *kn, struct kevent *kev)
+{
+       struct pppac_softc *sc = kn->kn_hook;
+       int rv;
+
+       mtx_enter(&sc->sc_rklist_mtx);
+       rv = knote_process(kn, kev);
+       mtx_leave(&sc->sc_rklist_mtx);
+
+       return (rv);
+}
+
 static void
 filt_pppac_wdetach(struct knote *kn)
 {
        struct pppac_softc *sc = kn->kn_hook;
-       struct klist *klist = &sc->sc_wsel.si_note;
+       struct klist *klist = &sc->sc_wklist;
 
-       mtx_enter(&sc->sc_wsel_mtx);
+       mtx_enter(&sc->sc_wklist_mtx);
        klist_remove_locked(klist, kn);
-       mtx_leave(&sc->sc_wsel_mtx);
+       mtx_leave(&sc->sc_wklist_mtx);
 }
 
 static int
@@ -1272,11 +1420,61 @@ filt_pppac_write(struct knote *kn, long 
 }
 
 int
+filt_pppac_wmodify(struct kevent *kev, struct knote *kn)
+{
+       struct pppac_softc *sc = kn->kn_hook;
+       int rv;
+
+       mtx_enter(&sc->sc_wklist_mtx);
+       rv = knote_modify(kev, kn);
+       mtx_leave(&sc->sc_wklist_mtx);
+
+       return (rv);
+}
+
+int
+filt_pppac_wprocess(struct knote *kn, struct kevent *kev)
+{
+       struct pppac_softc *sc = kn->kn_hook;
+       int rv;
+
+       mtx_enter(&sc->sc_wklist_mtx);
+       rv = knote_process(kn, kev);
+       mtx_leave(&sc->sc_wklist_mtx);
+
+       return (rv);
+}
+
+void
+klist_pppac_assertlk(void *arg)
+{
+       struct mutex *mtx = arg;
+
+       MUTEX_ASSERT_LOCKED(mtx);
+}
+
+int
+klist_pppac_lock(void *arg)
+{
+       struct mutex *mtx = arg;
+
+       mtx_enter(mtx);
+       return (1);
+}
+
+void
+klist_pppac_unlock(void *arg, int ls)
+{
+       struct mutex *mtx = arg;
+
+       mtx_leave(mtx);
+}
+
+int
 pppacclose(dev_t dev, int flags, int mode, struct proc *p)
 {
        struct pppac_softc *sc = pppac_lookup(dev);
        struct ifnet *ifp = &sc->sc_if;
-       int s;
 
        sc->sc_ready = 0;
 
@@ -1286,10 +1484,8 @@ pppacclose(dev_t dev, int flags, int mod
 
        if_detach(ifp);
 
-       s = splhigh();
-       klist_invalidate(&sc->sc_rsel.si_note);
-       klist_invalidate(&sc->sc_wsel.si_note);
-       splx(s);
+       klist_free(&sc->sc_rklist);
+       klist_free(&sc->sc_wklist);
 
        pool_put(&pipex_session_pool, sc->sc_multicast_session);
        pipex_destroy_all_sessions(sc);
@@ -1461,6 +1657,8 @@ bad:
 
        if (!mq_empty(&sc->sc_mq)) {
                wakeup(sc);
-               selwakeup(&sc->sc_rsel);
+               mtx_enter(&sc->sc_rklist_mtx);
+               KNOTE(&sc->sc_rklist, 0);
+               mtx_leave(&sc->sc_rklist_mtx);
        }
 }

Reply via email to