diff options
-rw-r--r-- | sys/conf/options | 1 | ||||
-rw-r--r-- | sys/net/netisr.c | 87 | ||||
-rw-r--r-- | sys/sys/kernel.h | 6 |
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); |