Module Name: src Committed By: riastradh Date: Sun Aug 7 20:47:05 UTC 2022
Modified Files: src/external/cddl/osnet/dev/sdt: sdt.c src/sys/modules/dtrace/sdt: Makefile Log Message: dtrace_sdt: Register sdt providers and probes in loaded modules too. To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/external/cddl/osnet/dev/sdt/sdt.c cvs rdiff -u -r1.6 -r1.7 src/sys/modules/dtrace/sdt/Makefile Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/cddl/osnet/dev/sdt/sdt.c diff -u src/external/cddl/osnet/dev/sdt/sdt.c:1.21 src/external/cddl/osnet/dev/sdt/sdt.c:1.22 --- src/external/cddl/osnet/dev/sdt/sdt.c:1.21 Mon Mar 28 12:33:20 2022 +++ src/external/cddl/osnet/dev/sdt/sdt.c Sun Aug 7 20:47:05 2022 @@ -39,7 +39,7 @@ * unloaded; in particular, probes may not span multiple kernel modules. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sdt.c,v 1.21 2022/03/28 12:33:20 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sdt.c,v 1.22 2022/08/07 20:47:05 riastradh Exp $"); #include <sys/cdefs.h> #include <sys/proc.h> @@ -52,6 +52,9 @@ __KERNEL_RCSID(0, "$NetBSD: sdt.c,v 1.21 #endif #include <sys/kernel.h> #include <sys/syslimits.h> +#ifdef __NetBSD__ +#include <sys/kobj.h> +#endif #ifdef __FreeBSD__ #include <sys/linker.h> #include <sys/linker_set.h> @@ -113,6 +116,10 @@ static dtrace_pops_t sdt_pops = { }; #ifdef __NetBSD__ +struct linker_file { + struct module lf_mod; +}; + static int sdt_open(dev_t dev, int flags, int mode, struct lwp *l) { @@ -204,14 +211,19 @@ sdt_create_probe(struct sdt_probe *probe SDT_KASSERT(prov != NULL, ("probe defined without a provider")); -#ifdef __FreeBSD__ /* If no module name was specified, use the module filename. */ if (*probe->mod == 0) { +#ifdef __NetBSD__ + const char *modname = (probe->sdtp_lf == NULL ? "netbsd" : + module_name(&probe->sdtp_lf->lf_mod)); + strlcpy(mod, modname, sizeof(mod)); +#endif +#ifdef __FreeBSD__ len = strlcpy(mod, probe->sdtp_lf->filename, sizeof(mod)); if (len > 3 && strcmp(mod + len - 3, ".ko") == 0) mod[len - 3] = '\0'; - } else #endif + } else strlcpy(mod, probe->mod, sizeof(mod)); /* @@ -258,6 +270,9 @@ sdt_enable(void *arg __unused, dtrace_id struct sdt_probe *probe = parg; probe->id = id; +#ifdef __NetBSD__ + module_hold(&probe->sdtp_lf->lf_mod); +#endif #ifdef __FreeBSD__ probe->sdtp_lf->nenabled++; if (strcmp(probe->prov->name, "lockstat") == 0) @@ -271,6 +286,9 @@ sdt_disable(void *arg __unused, dtrace_i { struct sdt_probe *probe = parg; +#ifdef __NetBSD__ + module_rele(&probe->sdtp_lf->lf_mod); +#endif #ifdef __FreeBSD__ SDT_KASSERT(probe->sdtp_lf->nenabled > 0, ("no probes enabled")); if (strcmp(probe->prov->name, "lockstat") == 0) @@ -411,63 +429,154 @@ __link_set_decl(sdt_providers_set, struc __link_set_decl(sdt_probes_set, struct sdt_probe); __link_set_decl(sdt_argtypes_set, struct sdt_argtype); -/* - * Unfortunately we don't have linker set functions and event handlers - * to support loading and unloading probes in modules... Currently if - * modules have probes, if the modules are loaded when sdt is loaded - * they will work, but they will crash unloading. - */ +static struct module_callbacks *sdt_link_set_callbacks; + static void -sdt_link_set_load(void) +sdt_link_set_load_provider(struct sdt_provider *const *provider) +{ + + sdt_create_provider(*provider); +} + +static void +sdt_link_set_unload_provider(struct sdt_provider *const *curr) +{ + struct sdt_provider *prov, *tmp; + + /* + * Go through all the providers declared in this linker file and + * unregister any that aren't declared in another loaded file. + */ + TAILQ_FOREACH_SAFE(prov, &sdt_prov_list, prov_entry, tmp) { + if (strcmp(prov->name, (*curr)->name) != 0) + continue; + + if (prov->sdt_refs == 1) { + if (dtrace_unregister(prov->id) != 0) { + return; + } + TAILQ_REMOVE(&sdt_prov_list, prov, prov_entry); + free(__UNCONST(prov->name), M_SDT); + free(prov, M_SDT); + } else + prov->sdt_refs--; + break; + } +} + +static void +sdt_link_set_load_probe(struct sdt_probe *const *probe, struct module *mod) +{ + struct linker_file *lf = mod == NULL ? NULL : + container_of(mod, struct linker_file, lf_mod); + + (*probe)->sdtp_lf = lf; + sdt_create_probe(*probe); + TAILQ_INIT(&(*probe)->argtype_list); +} + +static void +sdt_link_set_load_argtype(struct sdt_argtype *const *argtype) +{ + + (*argtype)->probe->n_args++; + TAILQ_INSERT_TAIL(&(*argtype)->probe->argtype_list, + *argtype, argtype_entry); +} + +static void +sdt_link_set_load_module(struct module *mod) { struct sdt_provider * const *provider; struct sdt_probe * const *probe; struct sdt_argtype * const *argtype; + void *p; + size_t size, n; - __link_set_foreach(provider, sdt_providers_set) { - sdt_create_provider(*provider); + /* + * Skip builtin modules -- they are handled separately with + * __link_set_foreach. + */ + if (module_source(mod) == MODULE_SOURCE_KERNEL) + return; + + if (kobj_find_section(mod->mod_kobj, "link_set_sdt_providers_set", + &p, &size) == 0) { + n = size/sizeof(*provider); + for (provider = p; n --> 0; provider++) + sdt_link_set_load_provider(provider); } - __link_set_foreach(probe, sdt_probes_set) { - (*probe)->sdtp_lf = NULL; // XXX: we don't support it - sdt_create_probe(*probe); - TAILQ_INIT(&(*probe)->argtype_list); + if (kobj_find_section(mod->mod_kobj, "link_set_sdt_probes_set", + &p, &size) == 0) { + n = size/sizeof(*probe); + for (probe = p; n --> 0; probe++) + sdt_link_set_load_probe(probe, mod); } - __link_set_foreach(argtype, sdt_argtypes_set) { - (*argtype)->probe->n_args++; - TAILQ_INSERT_TAIL(&(*argtype)->probe->argtype_list, - *argtype, argtype_entry); + if (kobj_find_section(mod->mod_kobj, "link_set_sdt_argtypes_set", + &p, &size) == 0) { + n = size/sizeof(*argtype); + for (argtype = p; n --> 0; argtype++) + sdt_link_set_load_argtype(argtype); } } static void -sdt_link_set_unload(void) +sdt_link_set_unload_module(struct module *mod) { - struct sdt_provider * const *curr, *prov, *tmp; + struct sdt_provider *const *curr; + void *p; + size_t size, n; /* - * Go through all the providers declared in this linker file and - * unregister any that aren't declared in another loaded file. + * Skip builtin modules -- they are handled separately with + * __link_set_foreach. */ - __link_set_foreach(curr, sdt_providers_set) { - TAILQ_FOREACH_SAFE(prov, &sdt_prov_list, prov_entry, tmp) { - if (strcmp(prov->name, (*curr)->name) != 0) - continue; + if (module_source(mod) == MODULE_SOURCE_KERNEL) + return; - if (prov->sdt_refs == 1) { - if (dtrace_unregister(prov->id) != 0) { - return; - } - TAILQ_REMOVE(&sdt_prov_list, prov, prov_entry); - free(__UNCONST(prov->name), M_SDT); - free(prov, M_SDT); - } else - prov->sdt_refs--; - break; - } + if (kobj_find_section(mod->mod_kobj, "link_set_sdt_providers_set", + &p, &size) == 0) { + n = size/sizeof(*curr); + for (curr = p; n --> 0; curr++) + sdt_link_set_unload_provider(curr); } } + +static void +sdt_link_set_load(void) +{ + struct sdt_provider * const *provider; + struct sdt_probe * const *probe; + struct sdt_argtype * const *argtype; + + __link_set_foreach(provider, sdt_providers_set) { + sdt_link_set_load_provider(provider); + } + __link_set_foreach(probe, sdt_probes_set) { + sdt_link_set_load_probe(probe, NULL); + } + __link_set_foreach(argtype, sdt_argtypes_set) { + sdt_link_set_load_argtype(argtype); + } + + sdt_link_set_callbacks = module_register_callbacks( + sdt_link_set_load_module, sdt_link_set_unload_module); +} + +static void +sdt_link_set_unload(void) +{ + struct sdt_provider *const *curr; + + module_unregister_callbacks(sdt_link_set_callbacks); + sdt_link_set_callbacks = NULL; + + __link_set_foreach(curr, sdt_providers_set) { + sdt_link_set_unload_provider(curr); + } +} #endif @@ -508,7 +617,6 @@ sdt_unload(void) #ifdef __NetBSD__ sdt_exit(); - sdt_link_set_unload(); #endif TAILQ_FOREACH_SAFE(prov, &sdt_prov_list, prov_entry, tmp) { Index: src/sys/modules/dtrace/sdt/Makefile diff -u src/sys/modules/dtrace/sdt/Makefile:1.6 src/sys/modules/dtrace/sdt/Makefile:1.7 --- src/sys/modules/dtrace/sdt/Makefile:1.6 Thu Sep 18 19:45:24 2014 +++ src/sys/modules/dtrace/sdt/Makefile Sun Aug 7 20:47:05 2022 @@ -11,5 +11,6 @@ CPPFLAGS+= -I${NETBSDSRCDIR}/external/cd -I${NETBSDSRCDIR}/external/cddl/osnet/dist/uts/common CPPFLAGS+= -Wno-unknown-pragmas +CPPFLAGS+= -Wno-sign-compare .include <bsd.kmodule.mk>