From 866c17cef5ab4305d0087cf2823e92f0057904c0 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Fri, 12 Feb 2016 16:31:46 -0500 Subject: [PATCH] Add libkmod rmmod support MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit We previously had support to load modules with libkmod but we always unload modules by calling the modprobe binary. This patch adds the libkmod module unloading which is faster and gives us better error handling. This implementation also graciously handles built-in lttng kernel modules. Signed-off-by: Michael Jeanson Signed-off-by: Jérémie Galarneau --- src/bin/lttng-sessiond/modprobe.c | 104 +++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 9 deletions(-) diff --git a/src/bin/lttng-sessiond/modprobe.c b/src/bin/lttng-sessiond/modprobe.c index 6f9a9978a..90fec711b 100644 --- a/src/bin/lttng-sessiond/modprobe.c +++ b/src/bin/lttng-sessiond/modprobe.c @@ -92,6 +92,7 @@ static int probes_capacity; #if HAVE_KMOD #include + static void log_kmod(void *data, int priority, const char *file, int line, const char *fn, const char *format, va_list args) { @@ -104,21 +105,39 @@ 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) + +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; +} + +static int modprobe_lttng(struct kern_modules_param *modules, + int entries, int required) +{ + 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; @@ -155,6 +174,73 @@ error: return ret; } +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; +} + +static void modprobe_remove_lttng(const struct kern_modules_param *modules, + int entries, int required) +{ + 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; + + 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 (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, @@ -203,8 +289,6 @@ error: return ret; } -#endif /* HAVE_KMOD */ - static void modprobe_remove_lttng(const struct kern_modules_param *modules, int entries, int required) { @@ -234,6 +318,8 @@ static void modprobe_remove_lttng(const struct kern_modules_param *modules, } } +#endif /* HAVE_KMOD */ + /* * Remove control kernel module(s) in reverse load order. */ -- 2.34.1