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)