X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fmodprobe.c;h=e1f52afd972b48aab29df0a6ac9a9d33f7b47c19;hp=ebf36646422314346c402c7373cdcccc4bc1f82b;hb=adfe4f5ee4088878b68135a4bd64e7260f2330ba;hpb=6c1c0768320135c6936c371b09731851b508c023 diff --git a/src/bin/lttng-sessiond/modprobe.c b/src/bin/lttng-sessiond/modprobe.c index ebf366464..e1f52afd9 100644 --- a/src/bin/lttng-sessiond/modprobe.c +++ b/src/bin/lttng-sessiond/modprobe.c @@ -1,22 +1,18 @@ /* - * Copyright (C) 2011 - David Goulet - * 2014 - Jan Glauber + * Copyright (C) 2011 David Goulet + * Copyright (C) 2014 Jan Glauber * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, version 2 only, - * as published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0-only * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + */ + +/** + * @file modprobe.c + * + * @brief modprobe related functions. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE #define _LGPL_SOURCE #include #include @@ -28,70 +24,206 @@ #include "modprobe.h" #include "kern-modules.h" - -#define LTTNG_MOD_REQUIRED 1 -#define LTTNG_MOD_OPTIONAL 0 +#include "lttng-sessiond.h" /* LTTng kernel tracer mandatory core modules list */ struct kern_modules_param kern_modules_control_core[] = { - { "lttng-tracer" }, /* MUST be loaded first so keep at top */ - { "lttng-lib-ring-buffer" }, - { "lttng-ring-buffer-client-discard" }, - { "lttng-ring-buffer-client-overwrite" }, - { "lttng-ring-buffer-metadata-client" }, - { "lttng-ring-buffer-client-mmap-discard" }, - { "lttng-ring-buffer-client-mmap-overwrite" }, - { "lttng-ring-buffer-metadata-mmap-client" }, -}; - -/* LTTng kernel tracer optional base modules list */ -struct kern_modules_param kern_modules_control_opt[] = { - { "lttng-types" }, - { "lttng-ftrace" }, - { "lttng-kprobes" }, - { "lttng-kretprobes" }, + { + .name = (char *) "lttng-ring-buffer-client-discard", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED, + }, + { + .name = (char *) "lttng-ring-buffer-client-overwrite", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED, + }, + { + .name = (char *) "lttng-ring-buffer-metadata-client", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED, + }, + { + .name = (char *) "lttng-ring-buffer-client-mmap-discard", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED, + }, + { + .name = (char *) "lttng-ring-buffer-client-mmap-overwrite", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED, + }, + { + .name = (char *) "lttng-ring-buffer-metadata-mmap-client", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED, + }, }; -/* LTTng kernel tracer probe modules list */ +/* LTTng kerneltracer probe modules list */ struct kern_modules_param kern_modules_probes_default[] = { - { "lttng-probe-asoc" }, - { "lttng-probe-block" }, - { "lttng-probe-btrfs" }, - { "lttng-probe-compaction" }, - { "lttng-probe-ext3" }, - { "lttng-probe-ext4" }, - { "lttng-probe-gpio" }, - { "lttng-probe-irq" }, - { "lttng-probe-jbd" }, - { "lttng-probe-jbd2" }, - { "lttng-probe-kmem" }, - { "lttng-probe-kvm" }, - { "lttng-probe-kvm-x86" }, - { "lttng-probe-kvm-x86-mmu" }, - { "lttng-probe-lock" }, - { "lttng-probe-module" }, - { "lttng-probe-napi" }, - { "lttng-probe-net" }, - { "lttng-probe-power" }, - { "lttng-probe-printk" }, - { "lttng-probe-random" }, - { "lttng-probe-rcu" }, - { "lttng-probe-regmap" }, - { "lttng-probe-regulator" }, - { "lttng-probe-rpm" }, - { "lttng-probe-sched" }, - { "lttng-probe-scsi" }, - { "lttng-probe-signal" }, - { "lttng-probe-skb" }, - { "lttng-probe-sock" }, - { "lttng-probe-statedump" }, - { "lttng-probe-sunrpc" }, - { "lttng-probe-timer" }, - { "lttng-probe-udp" }, - { "lttng-probe-vmscan" }, - { "lttng-probe-v4l2" }, - { "lttng-probe-workqueue" }, - { "lttng-probe-writeback" }, + { + .name = (char *) "lttng-probe-asoc", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-block", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-btrfs", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-compaction", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-ext3", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-ext4", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-gpio", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-i2c", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-irq", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-jbd", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-jbd2", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-kmem", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-kvm", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-kvm-x86", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-kvm-x86-mmu", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-lock", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-module", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-napi", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-net", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-power", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-preemptirq", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-printk", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-random", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-rcu", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-regmap", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-regulator", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-rpm", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-sched", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-scsi", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-signal", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-skb", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-sock", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-statedump", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-sunrpc", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-timer", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-udp", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-vmscan", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-v4l2", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-workqueue", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-writeback", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-x86-irq-vectors", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, + { + .name = (char *) "lttng-probe-x86-exceptions", + .load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL, + }, }; /* dynamic probe modules list */ @@ -99,78 +231,12 @@ static struct kern_modules_param *probes; static int nr_probes; static int probes_capacity; -void modprobe_remove_lttng(const struct kern_modules_param *modules, - int entries, int required) -{ - int ret = 0, i; - char modprobe[256]; - - for (i = entries - 1; i >= 0; i--) { - ret = snprintf(modprobe, sizeof(modprobe), - "/sbin/modprobe -r -q %s", - modules[i].name); - if (ret < 0) { - PERROR("snprintf modprobe -r"); - return; - } - modprobe[sizeof(modprobe) - 1] = '\0'; - ret = system(modprobe); - if (ret == -1) { - ERR("Unable to launch modprobe -r for module %s", - modules[i].name); - } else if (required && WEXITSTATUS(ret) != 0) { - ERR("Unable to remove module %s", - modules[i].name); - } else { - DBG("Modprobe removal successful %s", - modules[i].name); - } - } -} - -/* - * Remove control kernel module(s) in reverse load order. - */ -void modprobe_remove_lttng_control(void) -{ - modprobe_remove_lttng(kern_modules_control_opt, - ARRAY_SIZE(kern_modules_control_opt), - LTTNG_MOD_OPTIONAL); - modprobe_remove_lttng(kern_modules_control_core, - ARRAY_SIZE(kern_modules_control_core), - LTTNG_MOD_REQUIRED); -} - -/* - * Remove data kernel modules in reverse load order. - */ -void modprobe_remove_lttng_data(void) -{ - int i; - - if (probes) { - modprobe_remove_lttng(probes, nr_probes, LTTNG_MOD_OPTIONAL); - - for (i = 0; i < nr_probes; ++i) { - free(probes[i].name); - } - - free(probes); - probes = NULL; - } -} - -/* - * Remove all kernel modules in reverse order. - */ -void modprobe_remove_lttng_all(void) -{ - modprobe_remove_lttng_data(); - modprobe_remove_lttng_control(); -} - #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) { @@ -183,21 +249,60 @@ static void log_kmod(void *data, int priority, const char *file, int line, DBG("libkmod: %s", str); free(str); } -static int modprobe_lttng(struct kern_modules_param *modules, - int entries, int required) + +/** + * @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, i; - struct kmod_ctx *ctx; + int ret = 0; - ctx = kmod_new(NULL, NULL); + *ctx = kmod_new(NULL, NULL); if (!ctx) { PERROR("Unable to create kmod library context"); ret = -ENOMEM; goto error; } - kmod_set_log_fn(ctx, log_kmod, NULL); - kmod_load_resources(ctx); + kmod_set_log_fn(*ctx, log_kmod, NULL); + ret = kmod_load_resources(*ctx); + if (ret < 0) { + ERR("Failed to load kmod library resources"); + goto error; + } + +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 + * + * 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 ret = 0, i; + struct kmod_ctx *ctx; + + ret = setup_kmod_ctx(&ctx); + if (ret < 0) { + goto error; + } for (i = 0; i < entries; i++) { struct kmod_module *mod = NULL; @@ -208,10 +313,13 @@ 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 (required) { + if (ret == -EEXIST) { + DBG("Module %s is already loaded", modules[i].name); + ret = 0; + } else if (ret < 0) { + if (modules[i].load_policy == KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED) { ERR("Unable to load required module %s", modules[i].name); goto error; @@ -222,6 +330,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); @@ -234,10 +343,100 @@ 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; + + if (kmod_module_get_initstate(mod) == KMOD_MODULE_BUILTIN) { + DBG("Module %s is builtin", kmod_module_get_name(mod)); + return ret; + } + + ret = kmod_module_remove_module(mod, 0); + + deps = kmod_module_get_dependencies(mod); + if (deps != NULL) { + kmod_list_foreach(itr, deps) { + struct kmod_module *dep = kmod_module_get_module(itr); + if (kmod_module_get_refcnt(dep) == 0) { + DBG("Recursive remove module %s", + kmod_module_get_name(dep)); + rmmod_recurse(dep); + } + kmod_module_unref(dep); + } + kmod_module_unref_list(deps); + } + + 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 + * + */ +static void modprobe_remove_lttng(const struct kern_modules_param *modules, + int entries) +{ + int ret = 0, i; + struct kmod_ctx *ctx; + + ret = setup_kmod_ctx(&ctx); + if (ret < 0) { + goto error; + } + + 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); + goto error; + } + + ret = rmmod_recurse(mod); + if (ret == -EEXIST) { + DBG("Module %s is not in kernel.", modules[i].name); + } else if (modules[i].load_policy == KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED && ret < 0) { + ERR("Unable to remove module %s", modules[i].name); + } else { + DBG("Modprobe removal successful %s", + modules[i].name); + } + + kmod_module_unref(mod); + } + +error: + if (ctx) { + kmod_unref(ctx); + } +} + #else /* HAVE_KMOD */ static int modprobe_lttng(struct kern_modules_param *modules, - int entries, int required) + int entries) { int ret = 0, i; char modprobe[256]; @@ -245,7 +444,7 @@ static int modprobe_lttng(struct kern_modules_param *modules, for (i = 0; i < entries; i++) { ret = snprintf(modprobe, sizeof(modprobe), "/sbin/modprobe %s%s", - required ? "" : "-q ", + modules[i].load_policy == KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED ? "" : "-q ", modules[i].name); if (ret < 0) { PERROR("snprintf modprobe"); @@ -254,7 +453,7 @@ static int modprobe_lttng(struct kern_modules_param *modules, modprobe[sizeof(modprobe) - 1] = '\0'; ret = system(modprobe); if (ret == -1) { - if (required) { + if (modules[i].load_policy == KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED) { ERR("Unable to launch modprobe for required module %s", modules[i].name); goto error; @@ -264,7 +463,7 @@ static int modprobe_lttng(struct kern_modules_param *modules, ret = 0; } } else if (WEXITSTATUS(ret) != 0) { - if (required) { + if (modules[i].load_policy == KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED) { ERR("Unable to load required module %s", modules[i].name); goto error; @@ -275,6 +474,7 @@ static int modprobe_lttng(struct kern_modules_param *modules, } } else { DBG("Modprobe successfully %s", modules[i].name); + modules[i].loaded = true; } } @@ -282,24 +482,93 @@ error: return ret; } +static void modprobe_remove_lttng(const struct kern_modules_param *modules, + int entries) +{ + int ret = 0, i; + 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); + if (ret < 0) { + PERROR("snprintf modprobe -r"); + return; + } + modprobe[sizeof(modprobe) - 1] = '\0'; + ret = system(modprobe); + if (ret == -1) { + ERR("Unable to launch modprobe -r for module %s", + modules[i].name); + } else if (modules[i].load_policy == KERNEL_MODULE_PROPERTY_LOAD_POLICY_REQUIRED && WEXITSTATUS(ret) != 0) { + ERR("Unable to remove module %s", + modules[i].name); + } else { + DBG("Modprobe removal successful %s", + modules[i].name); + } + } +} + #endif /* HAVE_KMOD */ +/* + * Remove control kernel module(s) in reverse load order. + */ +void modprobe_remove_lttng_control(void) +{ + modprobe_remove_lttng(kern_modules_control_core, + ARRAY_SIZE(kern_modules_control_core)); +} + +static void free_probes(void) +{ + int i; + + if (!probes) { + return; + } + for (i = 0; i < nr_probes; ++i) { + free(probes[i].name); + } + free(probes); + probes = NULL; + nr_probes = 0; +} + +/* + * Remove data kernel modules in reverse load order. + */ +void modprobe_remove_lttng_data(void) +{ + if (!probes) { + return; + } + + modprobe_remove_lttng(probes, nr_probes); + free_probes(); +} + +/* + * Remove all kernel modules in reverse order. + */ +void modprobe_remove_lttng_all(void) +{ + modprobe_remove_lttng_data(); + modprobe_remove_lttng_control(); +} + /* * Load control kernel module(s). */ int modprobe_lttng_control(void) { - int ret; - - ret = modprobe_lttng(kern_modules_control_core, - ARRAY_SIZE(kern_modules_control_core), - LTTNG_MOD_REQUIRED); - if (ret != 0) - return ret; - ret = modprobe_lttng(kern_modules_control_opt, - ARRAY_SIZE(kern_modules_control_opt), - LTTNG_MOD_OPTIONAL); - return ret; + return modprobe_lttng(kern_modules_control_core, + ARRAY_SIZE(kern_modules_control_core)); } /** @@ -333,8 +602,8 @@ static int grow_probes(void) } for (i = 0; i < nr_probes; ++i) { - /* Move name pointer. */ - tmp_probes[i].name = probes[i].name; + /* Ownership of 'name' field is transferred. */ + tmp_probes[i] = probes[i]; } /* Replace probes with larger copy. */ @@ -351,11 +620,12 @@ static int grow_probes(void) static int append_list_to_probes(const char *list) { char *next; - int index = nr_probes, ret; + int ret; + char *tmp_list, *cur_list; assert(list); - char *tmp_list = strdup(list); + cur_list = tmp_list = strdup(list); if (!tmp_list) { PERROR("strdup temp list"); return -ENOMEM; @@ -365,11 +635,11 @@ static int append_list_to_probes(const char *list) size_t name_len; struct kern_modules_param *cur_mod; - next = strtok(tmp_list, ","); + next = strtok(cur_list, ","); if (!next) { break; } - tmp_list = NULL; + cur_list = NULL; /* filter leading spaces */ while (*next == ' ') { @@ -379,33 +649,40 @@ static int append_list_to_probes(const char *list) if (probes_capacity <= nr_probes) { ret = grow_probes(); if (ret) { - return ret; + goto error; } } /* Length 13 is "lttng-probe-" + \0 */ name_len = strlen(next) + 13; - cur_mod = &probes[index]; + cur_mod = &probes[nr_probes]; cur_mod->name = zmalloc(name_len); if (!cur_mod->name) { PERROR("malloc probe list"); - return -ENOMEM; + ret = -ENOMEM; + goto error; } ret = snprintf(cur_mod->name, name_len, "lttng-probe-%s", next); if (ret < 0) { PERROR("snprintf modprobe name"); - return -ENOMEM; + ret = -ENOMEM; + goto error; } - cur_mod++; + cur_mod->load_policy = KERNEL_MODULE_PROPERTY_LOAD_POLICY_OPTIONAL; + nr_probes++; } free(tmp_list); - return 0; + +error: + free(tmp_list); + free_probes(); + return ret; } /* @@ -420,24 +697,18 @@ 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); - if (ret) { return ret; } } else { /* Default probes. */ int def_len = ARRAY_SIZE(kern_modules_probes_default); - probes = zmalloc(sizeof(*probes) * def_len); + probes = zmalloc(sizeof(*probes) * def_len); if (!probes) { PERROR("malloc probe list"); return -ENOMEM; @@ -450,31 +721,36 @@ int modprobe_lttng_data(void) if (!name) { PERROR("strdup probe item"); - return -ENOMEM; + ret = -ENOMEM; + goto error; } probes[i].name = name; + probes[i].load_policy = kern_modules_probes_default[i].load_policy; } } /* * 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) { - return ret; + goto error; } } /* * Load probes modules now. */ - return modprobe_lttng(probes, nr_probes, LTTNG_MOD_OPTIONAL); + ret = modprobe_lttng(probes, nr_probes); + if (ret) { + goto error; + } + return ret; + +error: + free_probes(); + return ret; }