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)