From ec3b6f34ab30ee0609ff7b6fd37d856f105866fd Mon Sep 17 00:00:00 2001 Message-Id: From: John Ferlan Date: Tue, 4 Feb 2014 13:34:52 -0500 Subject: [PATCH] utils: Introduce functions for kernel module manipulation https://bugzilla.redhat.com/show_bug.cgi?id=1045124 virKModConfig() - Return a buffer containing kernel module configuration virKModLoad() - Load a specific module into the kernel configuration virKModUnload() - Unload a specific module from the kernel configuration virKModIsBlacklisted() - Determine whether a module is blacklisted within the kernel configuration (cherry picked from commit 4a2179ea9224ec01c036de116c0c226ce3f4d436) Signed-off-by: John Ferlan Signed-off-by: Jiri Denemark --- configure.ac | 6 ++ src/Makefile.am | 1 + src/libvirt_private.syms | 7 ++ src/util/virkmod.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virkmod.h | 34 +++++++++ 5 files changed, 229 insertions(+) create mode 100644 src/util/virkmod.c create mode 100644 src/util/virkmod.h diff --git a/configure.ac b/configure.ac index eb20f1c..1fe901d 100644 --- a/configure.ac +++ b/configure.ac @@ -327,6 +327,8 @@ AC_PATH_PROG([UDEVSETTLE], [udevsettle], [], [/sbin:/usr/sbin:/usr/local/sbin:$PATH]) AC_PATH_PROG([MODPROBE], [modprobe], [modprobe], [/sbin:/usr/sbin:/usr/local/sbin:$PATH]) +AC_PATH_PROG([RMMOD], [rmmod], [rmmod], + [/sbin:/usr/sbin:/usr/local/sbin:$PATH]) AC_PATH_PROG([OVSVSCTL], [ovs-vsctl], [ovs-vsctl], [/sbin:/usr/sbin:/usr/local/sbin:$PATH]) AC_PATH_PROG([SCRUB], [scrub], [scrub], @@ -353,6 +355,10 @@ if test -n "$MODPROBE"; then AC_DEFINE_UNQUOTED([MODPROBE],["$MODPROBE"], [Location or name of the modprobe program]) fi +if test -n "$RMMOD"; then + AC_DEFINE_UNQUOTED([RMMOD],["$RMMOD"], + [Location or name of the rmmod program]) +fi AC_DEFINE_UNQUOTED([SCRUB],["$SCRUB"], [Location or name of the scrub program (for wiping algorithms)]) diff --git a/src/Makefile.am b/src/Makefile.am index 2dddf15..8a7cefb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -122,6 +122,7 @@ UTIL_SOURCES = \ util/virnetdevvportprofile.h util/virnetdevvportprofile.c \ util/virnetlink.c util/virnetlink.h \ util/virnodesuspend.c util/virnodesuspend.h \ + util/virkmod.c util/virkmod.h \ util/virnuma.c util/virnuma.h \ util/virobject.c util/virobject.h \ util/virpci.c util/virpci.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index a07b52e..a1b3e4a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1547,6 +1547,13 @@ virKeyFileLoadFile; virKeyFileNew; +# util/virkmod.h +virKModConfig; +virKModIsBlacklisted; +virKModLoad; +virKModUnload; + + # util/virlockspace.h virLockSpaceAcquireResource; virLockSpaceCreateResource; diff --git a/src/util/virkmod.c b/src/util/virkmod.c new file mode 100644 index 0000000..73cb3c7 --- /dev/null +++ b/src/util/virkmod.c @@ -0,0 +1,181 @@ +/* + * virkmod.c: helper APIs for managing kernel modules + * + * Copyright (C) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + */ + +#include +#include "viralloc.h" +#include "virkmod.h" +#include "vircommand.h" +#include "virstring.h" + +static int +doModprobe(const char *opts, const char *module, char **outbuf, char **errbuf) +{ + int ret = -1; + virCommandPtr cmd = NULL; + + cmd = virCommandNew(MODPROBE); + if (opts) + virCommandAddArg(cmd, opts); + if (module) + virCommandAddArg(cmd, module); + if (outbuf) + virCommandSetOutputBuffer(cmd, outbuf); + if (errbuf) + virCommandSetErrorBuffer(cmd, errbuf); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virCommandFree(cmd); + return ret; +} + +static int +doRmmod(const char *module, char **errbuf) +{ + int ret = -1; + virCommandPtr cmd = NULL; + + cmd = virCommandNewArgList(RMMOD, module, NULL); + virCommandSetErrorBuffer(cmd, errbuf); + + if (virCommandRun(cmd, NULL) < 0) + goto cleanup; + + ret = 0; + +cleanup: + virCommandFree(cmd); + return ret; +} + +/** + * virKModConfig: + * + * Get the current kernel module configuration + * + * Returns NULL on failure or a pointer to the output which + * must be VIR_FREE()'d by the caller + */ +char * +virKModConfig(void) +{ + char *outbuf = NULL; + + if (doModprobe("-c", NULL, &outbuf, NULL) < 0) + return NULL; + + return outbuf; +} + + +/** + * virKModLoad: + * @module: Name of the module to load + * @useBlacklist: True if honoring blacklist + * + * Attempts to load a kernel module + * + * returns NULL in case of success and the error buffer output from the + * virCommandRun() on failure. The returned buffer must be VIR_FREE() + * by the caller + */ +char * +virKModLoad(const char *module, bool useBlacklist) +{ + char *errbuf = NULL; + + if (doModprobe(useBlacklist ? "-b" : NULL, module, NULL, &errbuf) < 0) + return errbuf; + + VIR_FREE(errbuf); + return NULL; +} + + +/** + * virKModUnload: + * @module: Name of the module to unload + * + * Remove or unload a module. + * + * NB: Do not use 'modprobe -r' here as that code will recursively + * unload any modules that were dependancies of the one being removed + * even if things still require them. e.g. it'll see the 'bridge' + * module has refcount of 0 and remove it, even if there are bridges + * created on the host + * + * returns NULL in case of success and the error buffer output from the + * virCommandRun() on failure. The returned buffer must be VIR_FREE() + * by the caller + */ +char * +virKModUnload(const char *module) +{ + char *errbuf = NULL; + + if (doRmmod(module, &errbuf) < 0) + return errbuf; + + VIR_FREE(errbuf); + return NULL; +} + + +/** + * virKModIsBlacklisted: + * @module: Name of the module to check for on the blacklist + * + * Search the output of the configuration data for the module being + * blacklisted. + * + * returns true when found blacklisted, false otherwise. + */ +bool +virKModIsBlacklisted(const char *module) +{ + bool retval = false; + size_t i; + char *drvblklst = NULL; + char *outbuf = NULL; + + if (virAsprintfQuiet(&drvblklst, "blacklist %s\n", module) < 0) + goto cleanup; + + /* modprobe will convert all '-' into '_', so we need to as well */ + for (i = 0; i < drvblklst[i]; i++) + if (drvblklst[i] == '-') + drvblklst[i] = '_'; + + if (doModprobe("-c", NULL, &outbuf, NULL) < 0) + goto cleanup; + + if (strstr(outbuf, drvblklst)) + retval = true; + +cleanup: + VIR_FREE(drvblklst); + VIR_FREE(outbuf); + return retval; +} diff --git a/src/util/virkmod.h b/src/util/virkmod.h new file mode 100644 index 0000000..608f1b8 --- /dev/null +++ b/src/util/virkmod.h @@ -0,0 +1,34 @@ +/* + * virkmod.h: helper APIs for managing kernel modprobe + * + * Copyright (C) 2014 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + */ + +#ifndef __VIR_KMOD_H__ +# define __VIR_KMOD_H__ + +# include "internal.h" + +char *virKModConfig(void); +char *virKModLoad(const char *, bool) + ATTRIBUTE_NONNULL(1); +char *virKModUnload(const char *) + ATTRIBUTE_NONNULL(1); +bool virKModIsBlacklisted(const char *) + ATTRIBUTE_NONNULL(1); +#endif /* __VIR_KMOD_H__ */ -- 1.8.5.3