From 9d96c75bad48308c4bb8d0d815d6a4f2132a4a17 Mon Sep 17 00:00:00 2001 From: mpi Date: Mon, 22 Aug 2016 10:40:36 +0000 Subject: [PATCH] Call csignal() and selwakeup() from a KERNEL_LOCK'd task. This will allow us make bpf_tap() KERNEL_LOCK() free. Discussed with dlg@ and input from guenther@ --- sys/net/bpf.c | 29 +++++++++++++++++++++++++---- sys/net/bpfdesc.h | 6 +++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/sys/net/bpf.c b/sys/net/bpf.c index d731632a2bd..98a367b70c4 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf.c,v 1.147 2016/08/15 07:20:14 mpi Exp $ */ +/* $OpenBSD: bpf.c,v 1.148 2016/08/22 10:40:36 mpi Exp $ */ /* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */ /* @@ -57,6 +57,8 @@ #include #include #include +#include +#include #include #include @@ -103,6 +105,7 @@ int bpf_setif(struct bpf_d *, struct ifreq *); int bpfpoll(dev_t, int, struct proc *); int bpfkqfilter(dev_t, struct knote *); void bpf_wakeup(struct bpf_d *); +void bpf_wakeup_cb(void *); void bpf_catchpacket(struct bpf_d *, u_char *, size_t, size_t, void (*)(const void *, void *, size_t), struct timeval *); void bpf_reset_d(struct bpf_d *); @@ -345,6 +348,7 @@ bpfopen(dev_t dev, int flag, int mode, struct proc *p) bd->bd_unit = unit; bd->bd_bufsize = bpf_bufsize; bd->bd_sig = SIGIO; + task_set(&bd->bd_wake_task, bpf_wakeup_cb, bd); if (flag & FNONBLOCK) bd->bd_rtout = -1; @@ -515,12 +519,29 @@ bpfread(dev_t dev, struct uio *uio, int ioflag) void bpf_wakeup(struct bpf_d *d) { - wakeup((caddr_t)d); + /* + * As long as csignal() and selwakeup() need to be protected + * by the KERNEL_LOCK() we have to delay the wakeup to + * another context to keep the hot path KERNEL_LOCK()-free. + */ + bpf_get(d); + if (!task_add(systq, &d->bd_wake_task)) + bpf_put(d); +} + +void +bpf_wakeup_cb(void *xd) +{ + struct bpf_d *d = xd; + + KERNEL_ASSERT_LOCKED(); + + wakeup(d); if (d->bd_async && d->bd_sig) - csignal(d->bd_pgid, d->bd_sig, - d->bd_siguid, d->bd_sigeuid); + csignal(d->bd_pgid, d->bd_sig, d->bd_siguid, d->bd_sigeuid); selwakeup(&d->bd_sel); + bpf_put(d); } int diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h index e5c7cea9172..bb62a371130 100644 --- a/sys/net/bpfdesc.h +++ b/sys/net/bpfdesc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bpfdesc.h,v 1.30 2016/03/30 12:33:10 dlg Exp $ */ +/* $OpenBSD: bpfdesc.h,v 1.31 2016/08/22 10:40:36 mpi Exp $ */ /* $NetBSD: bpfdesc.h,v 1.11 1995/09/27 18:30:42 thorpej Exp $ */ /* @@ -42,8 +42,6 @@ #ifdef _KERNEL -#include - /* * Descriptor associated with each open bpf file. */ @@ -90,6 +88,8 @@ struct bpf_d { struct selinfo bd_sel; /* bsd select info */ int bd_unit; /* logical unit number */ LIST_ENTRY(bpf_d) bd_list; /* descriptor list */ + + struct task bd_wake_task; /* delay csignal() and selwakeup() */ }; /* -- 2.20.1