X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmodprobe.c;h=d63483481369436f5d639463c7832caa5f9de9a7;hp=90fec711b8120c740d0ac4d48239b68c7db097c4;hb=46440d0ccf65b098757389ffebb0f7452626c4a3;hpb=866c17cef5ab4305d0087cf2823e92f0057904c0 diff --git a/src/bin/lttng-sessiond/modprobe.c b/src/bin/lttng-sessiond/modprobe.c index 90fec711b..d63483481 100644 --- a/src/bin/lttng-sessiond/modprobe.c +++ b/src/bin/lttng-sessiond/modprobe.c @@ -16,6 +16,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +/** + * @file modprobe.c + * + * @brief modprobe related functions. + * + */ + #define _LGPL_SOURCE #include #include @@ -27,6 +34,7 @@ #include "modprobe.h" #include "kern-modules.h" +#include "lttng-sessiond.h" #define LTTNG_MOD_REQUIRED 1 #define LTTNG_MOD_OPTIONAL 0 @@ -50,6 +58,7 @@ struct kern_modules_param kern_modules_probes_default[] = { { "lttng-probe-ext3" }, { "lttng-probe-ext4" }, { "lttng-probe-gpio" }, + { "lttng-probe-i2c" }, { "lttng-probe-irq" }, { "lttng-probe-jbd" }, { "lttng-probe-jbd2" }, @@ -62,6 +71,7 @@ struct kern_modules_param kern_modules_probes_default[] = { { "lttng-probe-napi" }, { "lttng-probe-net" }, { "lttng-probe-power" }, + { "lttng-probe-preemptirq" }, { "lttng-probe-printk" }, { "lttng-probe-random" }, { "lttng-probe-rcu" }, @@ -93,6 +103,9 @@ static int probes_capacity; #if HAVE_KMOD #include +/** + * @brief Logging function for libkmod integration. + */ static void log_kmod(void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) { @@ -106,6 +119,15 @@ static void log_kmod(void *data, int priority, const char *file, int line, free(str); } +/** + * @brief Setup the libkmod context. + * + * Create the context, add a custom logging function and preload the + * ressources for faster operation. + * + * @returns \c 0 on success + * \c < 0 on error + */ static int setup_kmod_ctx(struct kmod_ctx **ctx) { int ret = 0; @@ -128,6 +150,19 @@ error: return ret; } +/** + * @brief Loads the kernel modules in \p modules + * + * @param modules List of modules to load + * @param entries Number of modules in the list + * @param required Are the modules required or optionnal + * + * If the modules are required, we will return with error after the + * first failed module load, otherwise we continue loading. + * + * @returns \c 0 on success + * \c < 0 on error + */ static int modprobe_lttng(struct kern_modules_param *modules, int entries, int required) { @@ -148,9 +183,12 @@ static int modprobe_lttng(struct kern_modules_param *modules, goto error; } - ret = kmod_module_probe_insert_module(mod, KMOD_PROBE_IGNORE_LOADED, + ret = kmod_module_probe_insert_module(mod, 0, NULL, NULL, NULL, NULL); - if (ret < 0) { + if (ret == -EEXIST) { + DBG("Module %s is already loaded", modules[i].name); + ret = 0; + } else if (ret < 0) { if (required) { ERR("Unable to load required module %s", modules[i].name); @@ -162,6 +200,7 @@ static int modprobe_lttng(struct kern_modules_param *modules, } } else { DBG("Modprobe successfully %s", modules[i].name); + modules[i].loaded = true; } kmod_module_unref(mod); @@ -174,6 +213,18 @@ error: return ret; } +/** + * @brief Recursively unload modules. + * + * This function implements the same modules unloading behavior as + * 'modprobe -r' or rmmod, it will recursevily go trought the \p module + * dependencies and unload modules with a refcount of 0. + * + * @param mod The module to unload + * + * @returns \c 0 on success + * \c < 0 on error + */ static int rmmod_recurse(struct kmod_module *mod) { int ret = 0; struct kmod_list *deps, *itr; @@ -202,6 +253,14 @@ static int rmmod_recurse(struct kmod_module *mod) { return ret; } +/** + * @brief Unloads the kernel modules in \p modules + * + * @param modules List of modules to unload + * @param entries Number of modules in the list + * @param required Are the modules required or optionnal + * + */ static void modprobe_remove_lttng(const struct kern_modules_param *modules, int entries, int required) { @@ -216,6 +275,10 @@ static void modprobe_remove_lttng(const struct kern_modules_param *modules, for (i = entries - 1; i >= 0; i--) { struct kmod_module *mod = NULL; + if (!modules[i].loaded) { + continue; + } + ret = kmod_module_new_from_name(ctx, modules[i].name, &mod); if (ret < 0) { PERROR("Failed to create kmod module for %s", modules[i].name); @@ -282,6 +345,7 @@ static int modprobe_lttng(struct kern_modules_param *modules, } } else { DBG("Modprobe successfully %s", modules[i].name); + modules[i].loaded = true; } } @@ -296,6 +360,9 @@ static void modprobe_remove_lttng(const struct kern_modules_param *modules, char modprobe[256]; for (i = entries - 1; i >= 0; i--) { + if (!modules[i].loaded) { + continue; + } ret = snprintf(modprobe, sizeof(modprobe), "/sbin/modprobe -r -q %s", modules[i].name); @@ -503,12 +570,7 @@ int modprobe_lttng_data(void) * Base probes: either from command line option, environment * variable or default list. */ - if (kmod_probes_list) { - list = kmod_probes_list; - } else { - list = utils_get_kmod_probes_list(); - } - + list = config.kmod_probes_list.value; if (list) { /* User-specified probes. */ ret = append_list_to_probes(list); @@ -543,12 +605,7 @@ int modprobe_lttng_data(void) /* * Extra modules? Append them to current probes list. */ - if (kmod_extra_probes_list) { - list = kmod_extra_probes_list; - } else { - list = utils_get_extra_kmod_probes_list(); - } - + list = config.kmod_extra_probes_list.value; if (list) { ret = append_list_to_probes(list); if (ret) {