Author: rstone
Date: Tue Mar 27 15:07:43 2012
New Revision: 233552
URL: http://svn.freebsd.org/changeset/base/233552
Log:
Instead of only iterating over the set of known SDT probes when sdt.ko is
loaded and unloaded, also have sdt.ko register callbacks with kern_sdt.c
that will be called when a newly loaded KLD module adds more probes or
a module with probes is unloaded.
This fixes two issues: first, if a module with SDT probes was loaded after
sdt.ko was loaded, those new probes would not be available in DTrace.
Second, if a module with SDT probes was unloaded while sdt.ko was loaded,
the kernel would panic the next time DTrace had cause to try and do
anything with the no-longer-existent probes.
This makes it possible to create SDT probes in KLD modules, although there
are still two caveats: first, any SDT probes in a KLD module must be part
of a DTrace provider that is defined in that module. At present DTrace
only destroys probes when the provider is destroyed, so you can still
panic the system if a KLD module creates new probes in a provider from a
different module(including the kernel) and then unload the the first module.
Second, the system will panic if you unload a module containing SDT probes
while there is an active D script that has enabled those probes.
MFC after:1 month
Modified:
head/sys/cddl/dev/sdt/sdt.c
head/sys/kern/kern_sdt.c
head/sys/sys/sdt.h
Modified: head/sys/cddl/dev/sdt/sdt.c
==
--- head/sys/cddl/dev/sdt/sdt.c Tue Mar 27 15:07:35 2012(r233551)
+++ head/sys/cddl/dev/sdt/sdt.c Tue Mar 27 15:07:43 2012(r233552)
@@ -52,6 +52,8 @@ static void sdt_destroy(void *, dtrace_i
static voidsdt_enable(void *, dtrace_id_t, void *);
static voidsdt_disable(void *, dtrace_id_t, void *);
static voidsdt_load(void *);
+static int sdt_provider_unreg_callback(struct sdt_provider *prov,
+ void *arg);
static struct cdevsw sdt_cdevsw = {
.d_version = D_VERSION,
@@ -190,7 +192,8 @@ sdt_load(void *dummy)
sdt_probe_func = dtrace_probe;
- (void) sdt_provider_listall(sdt_provider_reg_callback, NULL);
+ sdt_register_callbacks(sdt_provider_reg_callback, NULL,
+ sdt_provider_unreg_callback, NULL, sdt_probe_callback, NULL);
}
static int
@@ -206,7 +209,7 @@ sdt_unload()
sdt_probe_func = sdt_probe_stub;
- (void) sdt_provider_listall(sdt_provider_unreg_callback, NULL);
+ sdt_deregister_callbacks();
destroy_dev(sdt_cdev);
Modified: head/sys/kern/kern_sdt.c
==
--- head/sys/kern/kern_sdt.cTue Mar 27 15:07:35 2012(r233551)
+++ head/sys/kern/kern_sdt.cTue Mar 27 15:07:43 2012(r233552)
@@ -59,6 +59,16 @@ static struct sx sdt_sx;
*/
sdt_probe_func_t sdt_probe_func = sdt_probe_stub;
+static sdt_provider_listall_func_t sdt_provider_register_func = NULL;
+static sdt_provider_listall_func_t sdt_provider_deregister_func = NULL;
+static sdt_probe_listall_func_t sdt_probe_register_func = NULL;
+
+static void *sdt_provider_register_arg;
+static void *sdt_provider_deregister_arg;
+static void *sdt_probe_register_arg;
+
+static int sdt_provider_listall_locked(sdt_provider_listall_func_t, void *);
+
/*
* This is a stub for probe calls in case kernel DTrace support isn't
* compiled in. It should never get called because there is no DTrace
@@ -85,6 +95,9 @@ sdt_provider_register(void *arg)
TAILQ_INIT(&prov->probe_list);
+ if (sdt_provider_register_func != NULL)
+ sdt_provider_register_func(prov, sdt_provider_register_arg);
+
sx_xunlock(&sdt_sx);
}
@@ -100,6 +113,9 @@ sdt_provider_deregister(void *arg)
TAILQ_REMOVE(&sdt_provider_list, prov, prov_entry);
+ if (sdt_provider_deregister_func != NULL)
+ sdt_provider_deregister_func(prov, sdt_provider_deregister_arg);
+
sx_xunlock(&sdt_sx);
}
@@ -128,6 +144,9 @@ sdt_probe_register(void *arg)
probe->state = SDT_INIT;
+ if (sdt_probe_register_func != NULL)
+ sdt_probe_register_func(probe, sdt_provider_register_arg);
+
sx_xunlock(&sdt_sx);
}
@@ -203,20 +222,31 @@ SYSUNINIT(sdt, SI_SUB_KDTRACE, SI_ORDER_
* List statically defined tracing providers.
*/
int
-sdt_provider_listall(sdt_provider_listall_func_t callback_func,void *arg)
+sdt_provider_listall(sdt_provider_listall_func_t callback_func, void *arg)
+{
+ int error;
+
+ sx_xlock(&sdt_sx);
+ error = sdt_provider_listall_locked(callback_func, arg);
+ sx_xunlock(&sdt_sx);
+
+ return (error);
+}
+
+static int
+sdt_provider_listall_locked(sdt_provider_listall_func_t callback_func,
+void *arg)
{
int error = 0;
struct sdt_provider *prov;
- sx_xlock(&sdt_sx);
+ sx_