svn commit: r368306 - head/sys/cddl/dev/sdt
Mark Johnston
markj at FreeBSD.org
Thu Dec 3 17:10:00 UTC 2020
Author: markj
Date: Thu Dec 3 17:10:00 2020
New Revision: 368306
URL: https://svnweb.freebsd.org/changeset/base/368306
Log:
sdt: Create providers and probes in separate passes when loading sdt.ko
The sdt module's load handler iterates over SDT linker sets for the
kernel and all loaded modules to create probes and providers defined by
SDT(9). Probes in one module may belong to a provider in a different
module, but when a probe is created we assume that the provider is
already defined. To maintain this invariant, modify the load handler to
perform two separate passes over loaded modules: one to define providers
and the other to define probes.
The problem manifests when loading linux.ko, which depends on
linux_common.ko, which defines providers used by probes defined in
linux.ko.
Reported by: gallatin
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Modified:
head/sys/cddl/dev/sdt/sdt.c
Modified: head/sys/cddl/dev/sdt/sdt.c
==============================================================================
--- head/sys/cddl/dev/sdt/sdt.c Thu Dec 3 16:54:59 2020 (r368305)
+++ head/sys/cddl/dev/sdt/sdt.c Thu Dec 3 17:10:00 2020 (r368306)
@@ -272,26 +272,24 @@ sdt_destroy(void *arg, dtrace_id_t id, void *parg)
{
}
-/*
- * Called from the kernel linker when a module is loaded, before
- * dtrace_module_loaded() is called. This is done so that it's possible to
- * register new providers when modules are loaded. The DTrace framework
- * explicitly disallows calling into the framework from the provide_module
- * provider method, so we cannot do this there.
- */
static void
-sdt_kld_load(void *arg __unused, struct linker_file *lf)
+sdt_kld_load_providers(struct linker_file *lf)
{
struct sdt_provider **prov, **begin, **end;
- struct sdt_probe **probe, **p_begin, **p_end;
- struct sdt_argtype **argtype, **a_begin, **a_end;
if (linker_file_lookup_set(lf, "sdt_providers_set", &begin, &end,
NULL) == 0) {
for (prov = begin; prov < end; prov++)
sdt_create_provider(*prov);
}
+}
+static void
+sdt_kld_load_probes(struct linker_file *lf)
+{
+ struct sdt_probe **probe, **p_begin, **p_end;
+ struct sdt_argtype **argtype, **a_begin, **a_end;
+
if (linker_file_lookup_set(lf, "sdt_probes_set", &p_begin, &p_end,
NULL) == 0) {
for (probe = p_begin; probe < p_end; probe++) {
@@ -311,7 +309,21 @@ sdt_kld_load(void *arg __unused, struct linker_file *l
}
}
+/*
+ * Called from the kernel linker when a module is loaded, before
+ * dtrace_module_loaded() is called. This is done so that it's possible to
+ * register new providers when modules are loaded. The DTrace framework
+ * explicitly disallows calling into the framework from the provide_module
+ * provider method, so we cannot do this there.
+ */
static void
+sdt_kld_load(void *arg __unused, struct linker_file *lf)
+{
+ sdt_kld_load_providers(lf);
+ sdt_kld_load_probes(lf);
+}
+
+static void
sdt_kld_unload_try(void *arg __unused, struct linker_file *lf, int *error)
{
struct sdt_provider *prov, **curr, **begin, **end, *tmp;
@@ -349,16 +361,21 @@ sdt_kld_unload_try(void *arg __unused, struct linker_f
}
static int
-sdt_linker_file_cb(linker_file_t lf, void *arg __unused)
+sdt_load_providers_cb(linker_file_t lf, void *arg __unused)
{
+ sdt_kld_load_providers(lf);
+ return (0);
+}
- sdt_kld_load(NULL, lf);
-
+static int
+sdt_load_probes_cb(linker_file_t lf, void *arg __unused)
+{
+ sdt_kld_load_probes(lf);
return (0);
}
static void
-sdt_load()
+sdt_load(void)
{
TAILQ_INIT(&sdt_prov_list);
@@ -370,12 +387,17 @@ sdt_load()
sdt_kld_unload_try_tag = EVENTHANDLER_REGISTER(kld_unload_try,
sdt_kld_unload_try, NULL, EVENTHANDLER_PRI_ANY);
- /* Pick up probes from the kernel and already-loaded linker files. */
- linker_file_foreach(sdt_linker_file_cb, NULL);
+ /*
+ * Pick up probes from the kernel and already-loaded linker files.
+ * Define providers in a separate pass since a linker file may be using
+ * providers defined in a file that appears later in the list.
+ */
+ linker_file_foreach(sdt_load_providers_cb, NULL);
+ linker_file_foreach(sdt_load_probes_cb, NULL);
}
static int
-sdt_unload()
+sdt_unload(void)
{
struct sdt_provider *prov, *tmp;
int ret;
More information about the svn-src-head
mailing list