From 66e31344b108643a51f5f4b9757c95ba3e8177e1 Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Tue, 14 Feb 2012 16:22:33 -0500 Subject: [PATCH] Implement refcount handling in DTrace modules to ensure that they cannot be unloaded while probes are enabled. Signed-off-by: Kris Van Hees --- dtrace/dt_test.h | 4 ++-- dtrace/dt_test_dev.c | 4 ++-- dtrace/dt_test_mod.c | 4 +++- dtrace/dtrace.h | 30 +++++++++++++++++++++++++++++- dtrace/profile.h | 4 ++-- dtrace/profile_dev.c | 4 ++-- dtrace/profile_mod.c | 2 ++ dtrace/sdt_dev.c | 4 ++-- dtrace/sdt_impl.h | 4 ++-- dtrace/sdt_mod.c | 2 ++ dtrace/systrace.h | 4 ++-- dtrace/systrace_dev.c | 4 ++-- dtrace/systrace_mod.c | 4 +++- 13 files changed, 55 insertions(+), 19 deletions(-) diff --git a/dtrace/dt_test.h b/dtrace/dt_test.h index 7ce73d10e8a0..d7d980296ac5 100644 --- a/dtrace/dt_test.h +++ b/dtrace/dt_test.h @@ -28,8 +28,8 @@ #define _DT_TEST_H_ extern void dt_test_provide(void *, const dtrace_probedesc_t *); -extern int dt_test_enable(void *arg, dtrace_id_t, void *); -extern void dt_test_disable(void *arg, dtrace_id_t, void *); +extern int _dt_test_enable(void *arg, dtrace_id_t, void *); +extern void _dt_test_disable(void *arg, dtrace_id_t, void *); extern void dt_test_destroy(void *, dtrace_id_t, void *); extern dtrace_provider_id_t dt_test_id; diff --git a/dtrace/dt_test_dev.c b/dtrace/dt_test_dev.c index 7af3b5c08560..edcdac203a5e 100644 --- a/dtrace/dt_test_dev.c +++ b/dtrace/dt_test_dev.c @@ -46,14 +46,14 @@ void dt_test_provide(void *arg, const dtrace_probedesc_t *desc) "dt_test", NULL, "test", 0, NULL); } -int dt_test_enable(void *arg, dtrace_id_t id, void *parg) +int _dt_test_enable(void *arg, dtrace_id_t id, void *parg) { enabled = 1; return 0; } -void dt_test_disable(void *arg, dtrace_id_t id, void *parg) +void _dt_test_disable(void *arg, dtrace_id_t id, void *parg) { enabled = 0; } diff --git a/dtrace/dt_test_mod.c b/dtrace/dt_test_mod.c index 4ad3d7b493d2..fb2c27b6b886 100644 --- a/dtrace/dt_test_mod.c +++ b/dtrace/dt_test_mod.c @@ -44,6 +44,8 @@ static const dtrace_pattr_t dt_test_attr = { { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, }; +DT_PROVIDER_POPS(dt_test) + static dtrace_pops_t dt_test_pops = { dt_test_provide, NULL, @@ -57,4 +59,4 @@ static dtrace_pops_t dt_test_pops = { dt_test_destroy }; -DT_PROVIDER_MODULE(dt_test, DTRACE_PRIV_USER); +DT_PROVIDER_MODULE(dt_test, DTRACE_PRIV_USER) diff --git a/dtrace/dtrace.h b/dtrace/dtrace.h index 53b444b43a74..ff054d294da7 100644 --- a/dtrace/dtrace.h +++ b/dtrace/dtrace.h @@ -2135,8 +2135,36 @@ extern int dtrace_badattr(const dtrace_attribute_t *); extern int dtrace_badname(const char *); extern void dtrace_cred2priv(const cred_t *, uint32_t *, uid_t *); +#define DT_PROVIDER_POPS(name) \ + static unsigned int name##_refc = 0; \ + \ + static int name##_enable(void *arg, dtrace_id_t id, void *parg) \ + { \ + int rc = 0; \ + \ + if (name##_refc++ == 0) { \ + if ((rc = try_module_get(THIS_MODULE)) == 0) \ + return 0; \ + } \ + \ + if ((rc = _##name##_enable(arg, id, parg)) != 0) { \ + if (--name##_refc == 0) \ + module_put(THIS_MODULE); \ + } \ + \ + return rc; \ + } \ + \ + static void name##_disable(void *arg, dtrace_id_t id, void *parg) \ + { \ + _##name##_disable(arg, id, parg); \ + \ + if (--name##_refc == 0) \ + module_put(THIS_MODULE); \ + } + #define DT_PROVIDER_MODULE(name, priv) \ - dtrace_provider_id_t name##_id; \ + dtrace_provider_id_t name##_id; \ \ static int __init name##_init(void) \ { \ diff --git a/dtrace/profile.h b/dtrace/profile.h index 8f96a8acb2dd..40949f8dce12 100644 --- a/dtrace/profile.h +++ b/dtrace/profile.h @@ -2,8 +2,8 @@ #define _PROFILE_H_ extern void profile_provide(void *, const dtrace_probedesc_t *); -extern int profile_enable(void *, dtrace_id_t, void *); -extern void profile_disable(void *, dtrace_id_t, void *); +extern int _profile_enable(void *, dtrace_id_t, void *); +extern void _profile_disable(void *, dtrace_id_t, void *); extern int profile_usermode(void *, dtrace_id_t, void *); extern void profile_destroy(void *, dtrace_id_t, void *); diff --git a/dtrace/profile_dev.c b/dtrace/profile_dev.c index 38a65e4ac10c..143a571bbc8c 100644 --- a/dtrace/profile_dev.c +++ b/dtrace/profile_dev.c @@ -333,7 +333,7 @@ void profile_provide(void *arg, const dtrace_probedesc_t *desc) profile_create(interval, name, kind); } -int profile_enable(void *arg, dtrace_id_t id, void *parg) +int _profile_enable(void *arg, dtrace_id_t id, void *parg) { profile_probe_t *prof = parg; cyc_omni_handler_t omni; @@ -367,7 +367,7 @@ int profile_enable(void *arg, dtrace_id_t id, void *parg) return 0; } -void profile_disable(void *arg, dtrace_id_t id, void *parg) +void _profile_disable(void *arg, dtrace_id_t id, void *parg) { profile_probe_t *prof = parg; diff --git a/dtrace/profile_mod.c b/dtrace/profile_mod.c index 5ca3e4637b7a..1a42a2e2f50e 100644 --- a/dtrace/profile_mod.c +++ b/dtrace/profile_mod.c @@ -44,6 +44,8 @@ static const dtrace_pattr_t profile_attr = { { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, }; +DT_PROVIDER_POPS(profile) + static dtrace_pops_t profile_pops = { profile_provide, NULL, diff --git a/dtrace/sdt_dev.c b/dtrace/sdt_dev.c index 504e380be171..846afb984563 100644 --- a/dtrace/sdt_dev.c +++ b/dtrace/sdt_dev.c @@ -142,7 +142,7 @@ void sdt_provide_module(void *arg, struct module *mp) } } -int sdt_enable(void *arg, dtrace_id_t id, void *parg) +int _sdt_enable(void *arg, dtrace_id_t id, void *parg) { sdt_probe_t *sdp = parg; @@ -150,7 +150,7 @@ int sdt_enable(void *arg, dtrace_id_t id, void *parg) return 0; } -void sdt_disable(void *arg, dtrace_id_t id, void *parg) +void _sdt_disable(void *arg, dtrace_id_t id, void *parg) { sdt_probe_t *sdp = parg; diff --git a/dtrace/sdt_impl.h b/dtrace/sdt_impl.h index 31a7788b13a9..c6a066d56e1a 100644 --- a/dtrace/sdt_impl.h +++ b/dtrace/sdt_impl.h @@ -23,8 +23,8 @@ typedef struct sdt_probe { extern dtrace_mprovider_t sdt_providers[]; extern void sdt_provide_module(void *, struct module *); -extern int sdt_enable(void *, dtrace_id_t, void *); -extern void sdt_disable(void *, dtrace_id_t, void *); +extern int _sdt_enable(void *, dtrace_id_t, void *); +extern void _sdt_disable(void *, dtrace_id_t, void *); extern void sdt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *); extern uint64_t sdt_getarg(void *, dtrace_id_t, void *, int, int); extern void sdt_destroy(void *, dtrace_id_t, void *); diff --git a/dtrace/sdt_mod.c b/dtrace/sdt_mod.c index cbb93d30691f..55f7c862097e 100644 --- a/dtrace/sdt_mod.c +++ b/dtrace/sdt_mod.c @@ -109,6 +109,8 @@ static dtrace_pattr_t iscsi_attr = { { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA }, }; +DT_PROVIDER_POPS(sdt) + static dtrace_pops_t sdt_pops = { NULL, sdt_provide_module, diff --git a/dtrace/systrace.h b/dtrace/systrace.h index f53152bd5979..d726cb3a3282 100644 --- a/dtrace/systrace.h +++ b/dtrace/systrace.h @@ -27,8 +27,8 @@ #include "dtrace.h" extern void systrace_provide(void *, const dtrace_probedesc_t *); -extern int systrace_enable(void *arg, dtrace_id_t, void *); -extern void systrace_disable(void *arg, dtrace_id_t, void *); +extern int _systrace_enable(void *arg, dtrace_id_t, void *); +extern void _systrace_disable(void *arg, dtrace_id_t, void *); extern void systrace_destroy(void *, dtrace_id_t, void *); extern dtrace_provider_id_t syscall_id; diff --git a/dtrace/systrace_dev.c b/dtrace/systrace_dev.c index 732db2653b61..50ea38862b76 100644 --- a/dtrace/systrace_dev.c +++ b/dtrace/systrace_dev.c @@ -109,7 +109,7 @@ static dt_sys_call_t get_intercept(int sysnum) } } -int systrace_enable(void *arg, dtrace_id_t id, void *parg) +int _systrace_enable(void *arg, dtrace_id_t id, void *parg) { int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg); int enabled = @@ -135,7 +135,7 @@ int systrace_enable(void *arg, dtrace_id_t id, void *parg) return 0; } -void systrace_disable(void *arg, dtrace_id_t id, void *parg) +void _systrace_disable(void *arg, dtrace_id_t id, void *parg) { int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg); int enabled = diff --git a/dtrace/systrace_mod.c b/dtrace/systrace_mod.c index 4e87ec13350d..3f89f8ea2f59 100644 --- a/dtrace/systrace_mod.c +++ b/dtrace/systrace_mod.c @@ -44,6 +44,8 @@ static const dtrace_pattr_t syscall_attr = { { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, }; +DT_PROVIDER_POPS(systrace) + static dtrace_pops_t syscall_pops = { systrace_provide, NULL, @@ -57,4 +59,4 @@ static dtrace_pops_t syscall_pops = { systrace_destroy }; -DT_PROVIDER_MODULE(syscall, DTRACE_PRIV_USER); +DT_PROVIDER_MODULE(syscall, DTRACE_PRIV_USER) -- 2.50.1