Date: Sun, 27 May 2012 14:52:31 +0000 (UTC) From: Ryan Stone <rstone@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r236153 - in stable/8/sys: cddl/dev/sdt kern sys Message-ID: <201205271452.q4REqVdx055768@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rstone Date: Sun May 27 14:52:31 2012 New Revision: 236153 URL: http://svn.freebsd.org/changeset/base/236153 Log: MFC r233552 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. Modified: stable/8/sys/cddl/dev/sdt/sdt.c stable/8/sys/kern/kern_sdt.c stable/8/sys/sys/sdt.h Directory Properties: stable/8/sys/ (props changed) Modified: stable/8/sys/cddl/dev/sdt/sdt.c ============================================================================== --- stable/8/sys/cddl/dev/sdt/sdt.c Sun May 27 14:48:14 2012 (r236152) +++ stable/8/sys/cddl/dev/sdt/sdt.c Sun May 27 14:52:31 2012 (r236153) @@ -52,6 +52,8 @@ static void sdt_destroy(void *, dtrace_i static void sdt_enable(void *, dtrace_id_t, void *); static void sdt_disable(void *, dtrace_id_t, void *); static void sdt_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: stable/8/sys/kern/kern_sdt.c ============================================================================== --- stable/8/sys/kern/kern_sdt.c Sun May 27 14:48:14 2012 (r236152) +++ stable/8/sys/kern/kern_sdt.c Sun May 27 14:52:31 2012 (r236153) @@ -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_assert(&sdt_sx, SX_XLOCKED); TAILQ_FOREACH(prov, &sdt_provider_list, prov_entry) { if ((error = callback_func(prov, arg)) != 0) break; } - sx_xunlock(&sdt_sx); - return (error); } @@ -271,3 +301,39 @@ sdt_argtype_listall(struct sdt_probe *pr return (error); } + +void sdt_register_callbacks(sdt_provider_listall_func_t register_prov, + void *reg_prov_arg, sdt_provider_listall_func_t deregister_prov, + void *dereg_prov_arg, sdt_probe_listall_func_t register_probe, + void * reg_probe_arg) +{ + + sx_xlock(&sdt_sx); + sdt_provider_register_func = register_prov; + sdt_provider_deregister_func = deregister_prov; + sdt_probe_register_func = register_probe; + + sdt_provider_register_arg = reg_prov_arg; + sdt_provider_deregister_arg = dereg_prov_arg; + sdt_probe_register_arg = reg_probe_arg; + + sdt_provider_listall_locked(register_prov, reg_prov_arg); + sx_xunlock(&sdt_sx); +} + +void sdt_deregister_callbacks(void) +{ + + sx_xlock(&sdt_sx); + sdt_provider_listall_locked(sdt_provider_deregister_func, + sdt_provider_deregister_arg); + + sdt_provider_register_func = NULL; + sdt_provider_deregister_func = NULL; + sdt_probe_register_func = NULL; + + sdt_provider_register_arg = NULL; + sdt_provider_deregister_arg = NULL; + sdt_probe_register_arg = NULL; + sx_xunlock(&sdt_sx); +} Modified: stable/8/sys/sys/sdt.h ============================================================================== --- stable/8/sys/sys/sdt.h Sun May 27 14:48:14 2012 (r236152) +++ stable/8/sys/sys/sdt.h Sun May 27 14:52:31 2012 (r236153) @@ -258,6 +258,10 @@ int sdt_argtype_listall(struct sdt_probe int sdt_probe_listall(struct sdt_provider *, sdt_probe_listall_func_t, void *); int sdt_provider_listall(sdt_provider_listall_func_t,void *); +void sdt_register_callbacks(sdt_provider_listall_func_t, void *, + sdt_provider_listall_func_t, void *, sdt_probe_listall_func_t, void *); +void sdt_deregister_callbacks(void); + #endif /* KDTRACE_HOOKS */ #endif /* _KERNEL */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201205271452.q4REqVdx055768>