This makes log event filter MP-safe.

OK?

Index: kern/subr_log.c
===================================================================
RCS file: src/sys/kern/subr_log.c,v
retrieving revision 1.75
diff -u -p -r1.75 subr_log.c
--- kern/subr_log.c     2 Jul 2022 08:50:42 -0000       1.75
+++ kern/subr_log.c     10 Feb 2023 14:44:20 -0000
@@ -50,6 +50,7 @@
 #include <sys/filedesc.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
+#include <sys/event.h>
 #include <sys/fcntl.h>
 #include <sys/mutex.h>
 #include <sys/timeout.h>
@@ -75,7 +76,7 @@
  */
 struct logsoftc {
        int     sc_state;               /* [L] see above for possibilities */
-       struct  selinfo sc_selp;        /* process waiting on select call */
+       struct  klist sc_klist;         /* [L] list of knotes */
        struct  sigio_ref sc_sigio;     /* async I/O registration */
        int     sc_need_wakeup;         /* if set, wake up waiters */
        struct timeout sc_tick;         /* wakeup poll timeout */
@@ -99,17 +100,22 @@ struct     mutex log_mtx =
 
 void filt_logrdetach(struct knote *kn);
 int filt_logread(struct knote *kn, long hint);
+int filt_logmodify(struct kevent *kev, struct knote *kn);
+int filt_logprocess(struct knote *kn, struct kevent *kev);
 
 const struct filterops logread_filtops = {
-       .f_flags        = FILTEROP_ISFD,
+       .f_flags        = FILTEROP_ISFD | FILTEROP_MPSAFE,
        .f_attach       = NULL,
        .f_detach       = filt_logrdetach,
        .f_event        = filt_logread,
+       .f_modify       = filt_logmodify,
+       .f_process      = filt_logprocess,
 };
 
 int dosendsyslog(struct proc *, const char *, size_t, int, enum uio_seg);
 void logtick(void *);
 size_t msgbuf_getlen(struct msgbuf *);
+size_t msgbuf_getlen_locked(struct msgbuf *);
 void msgbuf_putchar_locked(struct msgbuf *, const char);
 
 void
@@ -189,13 +195,22 @@ msgbuf_putchar_locked(struct msgbuf *mbp
 size_t
 msgbuf_getlen(struct msgbuf *mbp)
 {
-       long len;
+       size_t len;
 
        mtx_enter(&log_mtx);
+       len = msgbuf_getlen_locked(mbp);
+       mtx_leave(&log_mtx);
+       return (len);
+}
+
+size_t
+msgbuf_getlen_locked(struct msgbuf *mbp)
+{
+       long len;
+
        len = mbp->msg_bufx - mbp->msg_bufr;
        if (len < 0)
                len += mbp->msg_bufs;
-       mtx_leave(&log_mtx);
        return (len);
 }
 
@@ -205,6 +220,7 @@ logopen(dev_t dev, int flags, int mode, 
        if (log_open)
                return (EBUSY);
        log_open = 1;
+       klist_init_mutex(&logsoftc.sc_klist, &log_mtx);
        sigio_init(&logsoftc.sc_sigio);
        timeout_set(&logsoftc.sc_tick, logtick, NULL);
        timeout_add_msec(&logsoftc.sc_tick, LOG_TICK);
@@ -227,6 +243,7 @@ logclose(dev_t dev, int flag, int mode, 
        timeout_del(&logsoftc.sc_tick);
        logsoftc.sc_state = 0;
        sigio_free(&logsoftc.sc_sigio);
+       klist_free(&logsoftc.sc_klist);
        return (0);
 }
 
@@ -302,11 +319,10 @@ int
 logkqfilter(dev_t dev, struct knote *kn)
 {
        struct klist *klist;
-       int s;
 
        switch (kn->kn_filter) {
        case EVFILT_READ:
-               klist = &logsoftc.sc_selp.si_note;
+               klist = &logsoftc.sc_klist;
                kn->kn_fop = &logread_filtops;
                break;
        default:
@@ -315,9 +331,7 @@ logkqfilter(dev_t dev, struct knote *kn)
 
        kn->kn_hook = (void *)msgbufp;
 
-       s = splhigh();
-       klist_insert_locked(klist, kn);
-       splx(s);
+       klist_insert(klist, kn);
 
        return (0);
 }
@@ -325,11 +339,7 @@ logkqfilter(dev_t dev, struct knote *kn)
 void
 filt_logrdetach(struct knote *kn)
 {
-       int s;
-
-       s = splhigh();
-       klist_remove_locked(&logsoftc.sc_selp.si_note, kn);
-       splx(s);
+       klist_remove(&logsoftc.sc_klist, kn);
 }
 
 int
@@ -337,10 +347,36 @@ filt_logread(struct knote *kn, long hint
 {
        struct msgbuf *mbp = kn->kn_hook;
 
-       kn->kn_data = msgbuf_getlen(mbp);
+       MUTEX_ASSERT_LOCKED(&log_mtx);
+
+       kn->kn_data = msgbuf_getlen_locked(mbp);
        return (kn->kn_data != 0);
 }
 
+int
+filt_logmodify(struct kevent *kev, struct knote *kn)
+{
+       int active;
+
+       mtx_enter(&log_mtx);
+       active = knote_modify(kev, kn);
+       mtx_leave(&log_mtx);
+
+       return (active);
+}
+
+int
+filt_logprocess(struct knote *kn, struct kevent *kev)
+{
+       int active;
+
+       mtx_enter(&log_mtx);
+       active = knote_process(kn, kev);
+       mtx_leave(&log_mtx);
+
+       return (active);
+}
+
 void
 logwakeup(void)
 {
@@ -381,9 +417,9 @@ logtick(void *arg)
        state = logsoftc.sc_state;
        if (logsoftc.sc_state & LOG_RDWAIT)
                logsoftc.sc_state &= ~LOG_RDWAIT;
+       knote_locked(&logsoftc.sc_klist, 0);
        mtx_leave(&log_mtx);
 
-       selwakeup(&logsoftc.sc_selp);
        if (state & LOG_ASYNC)
                pgsigio(&logsoftc.sc_sigio, SIGIO, 0);
        if (state & LOG_RDWAIT)

Reply via email to