aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/conf/options1
-rw-r--r--sys/net/netisr.c87
-rw-r--r--sys/sys/kernel.h6
3 files changed, 91 insertions, 3 deletions
diff --git a/sys/conf/options b/sys/conf/options
index d0d79902d6ac..2ef8b20b1211 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -361,6 +361,7 @@ LIBMCHAIN
MBUF_STRESS_TEST opt_mbuf_stress_test.h
NCP
NETATALK opt_atalk.h
+NET_WITH_GIANT opt_net.h
PPP_BSDCOMP opt_ppp.h
PPP_DEFLATE opt_ppp.h
PPP_FILTER opt_ppp.h
diff --git a/sys/net/netisr.c b/sys/net/netisr.c
index 8f573d9ca536..ec7b7ad8fb82 100644
--- a/sys/net/netisr.c
+++ b/sys/net/netisr.c
@@ -27,6 +27,8 @@
* $FreeBSD$
*/
+#include "opt_net.h"
+
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/rtprio.h>
@@ -55,11 +57,18 @@
/*
* debug_mpsafenet controls network subsystem-wide use of the Giant lock,
- * from system calls down to interrupt handlers. It can be changed only
- * via a tunable at boot, not at run-time, due to the complexity of
- * unwinding.
+ * from system calls down to interrupt handlers. It can be changed only via
+ * a tunable at boot, not at run-time, due to the complexity of unwinding.
+ * The compiled default is set via a kernel option; right now, the default
+ * unless otherwise specified is to run the network stack without Giant.
*/
+#ifdef NET_WITH_GIANT
int debug_mpsafenet = 0;
+#else
+int debug_mpsafenet = 1;
+#endif
+int debug_mpsafenet_toolatetotwiddle = 0;
+
TUNABLE_INT("debug.mpsafenet", &debug_mpsafenet);
SYSCTL_INT(_debug, OID_AUTO, mpsafenet, CTLFLAG_RD, &debug_mpsafenet, 0,
"Enable/disable MPSAFE network support");
@@ -74,6 +83,78 @@ struct netisr {
static void *net_ih;
+/*
+ * Note all network code is currently capable of running MPSAFE; however,
+ * most of it is. Since those sections that are not are generally optional
+ * components not shipped with default kernels, we provide a basic way to
+ * determine whether MPSAFE operation is permitted: based on a default of
+ * yes, we permit non-MPSAFE components to use a registration call to
+ * identify that they require Giant. If the system is early in the boot
+ * process still, then we change the debug_mpsafenet setting to choose a
+ * non-MPSAFE execution mode (degraded). If it's too late for that (since
+ * the setting cannot be changed at run time), we generate a console warning
+ * that the configuration may be unsafe.
+ */
+static int mpsafe_warn_count;
+
+/*
+ * Function call implementing registration of a non-MPSAFE network component.
+ */
+void
+net_warn_not_mpsafe(const char *component)
+{
+
+ /*
+ * If we're running with Giant over the network stack, there is no
+ * problem.
+ */
+ if (!debug_mpsafenet)
+ return;
+
+ /*
+ * If it's not too late to change the MPSAFE setting for the network
+ * stack, do so now. This effectively suppresses warnings by
+ * components registering later.
+ */
+ if (!debug_mpsafenet_toolatetotwiddle) {
+ debug_mpsafenet = 0;
+ printf("WARNING: debug.mpsafenet forced to = as %s requires "
+ "Giant\n", component);
+ return;
+ }
+
+ /*
+ * We must run without Giant, so generate a console warning with some
+ * information with what to do about it. The system may be operating
+ * unsafely, however.
+ */
+ printf("WARNING: Network stack Giant-free, but %s requires Giant.\n",
+ component);
+ if (mpsafe_warn_count == 0)
+ printf(" Consider adding 'options NET_WITH_GIANT' or "
+ "setting debug.mpsafenet=0\n");
+ mpsafe_warn_count++;
+}
+
+/*
+ * This sysinit is run after any pre-loaded or compiled-in components have
+ * announced that they require Giant, but before any modules loaded at
+ * run-time.
+ */
+static void
+net_mpsafe_toolate(void *arg)
+{
+
+ debug_mpsafenet_toolatetotwiddle = 1;
+
+ if (!debug_mpsafenet)
+ printf("WARNING: MPSAFE network stack disabled, expect "
+ "reduced performance.\n");
+}
+
+SYSINIT(net_mpsafe_toolate, SI_SUB_SETTINGS, SI_ORDER_ANY, net_mpsafe_toolate,
+ NULL);
+
void
legacy_setsoftnet(void)
{
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
index eb6a350c292d..9c449ec93a4a 100644
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -106,6 +106,7 @@ enum sysinit_sub_id {
SI_SUB_TUNABLES = 0x0700000, /* establish tunable values */
SI_SUB_CONSOLE = 0x0800000, /* console*/
SI_SUB_COPYRIGHT = 0x0800001, /* first use of console*/
+ SI_SUB_SETTINGS = 0x0880000, /* check and recheck settings */
SI_SUB_MTX_POOL_STATIC = 0x0900000, /* static mutex pool */
SI_SUB_LOCKMGR = 0x0980000, /* lockmgr locks */
SI_SUB_VM = 0x1000000, /* virtual memory system init*/
@@ -327,6 +328,11 @@ struct tunable_str {
#define TUNABLE_STR_FETCH(path, var, size) \
getenv_string((path), (var), (size))
+void net_warn_not_mpsafe(const char *component);
+#define NET_NEEDS_GIANT(component) \
+ SYSINIT(__net_warn_not_mpsafe_ ## __FILE__, \
+ SI_SUB_SETTINGS, SI_ORDER_SECOND, net_warn_not_mpsafe, component);
+
struct intr_config_hook {
TAILQ_ENTRY(intr_config_hook) ich_links;
void (*ich_func)(void *arg);