svn commit: r236152 - in stable/9/sys: cddl/dev/sdt kern sys

Ryan Stone rstone at FreeBSD.org
Sun May 27 14:48:14 UTC 2012


Author: rstone
Date: Sun May 27 14:48:14 2012
New Revision: 236152
URL: http://svn.freebsd.org/changeset/base/236152

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/9/sys/cddl/dev/sdt/sdt.c
  stable/9/sys/kern/kern_sdt.c
  stable/9/sys/sys/sdt.h
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/cddl/dev/sdt/sdt.c
==============================================================================
--- stable/9/sys/cddl/dev/sdt/sdt.c	Sun May 27 14:25:16 2012	(r236151)
+++ stable/9/sys/cddl/dev/sdt/sdt.c	Sun May 27 14:48:14 2012	(r236152)
@@ -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/9/sys/kern/kern_sdt.c
==============================================================================
--- stable/9/sys/kern/kern_sdt.c	Sun May 27 14:25:16 2012	(r236151)
+++ stable/9/sys/kern/kern_sdt.c	Sun May 27 14:48:14 2012	(r236152)
@@ -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/9/sys/sys/sdt.h
==============================================================================
--- stable/9/sys/sys/sdt.h	Sun May 27 14:25:16 2012	(r236151)
+++ stable/9/sys/sys/sdt.h	Sun May 27 14:48:14 2012	(r236152)
@@ -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 */


More information about the svn-src-stable-9 mailing list