| From ec3b6f34ab30ee0609ff7b6fd37d856f105866fd Mon Sep 17 00:00:00 2001 |
| Message-Id: <ec3b6f34ab30ee0609ff7b6fd37d856f105866fd.1391615407.git.jdenemar@redhat.com> |
| From: John Ferlan <jferlan@redhat.com> |
| 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 <jferlan@redhat.com> |
| Signed-off-by: Jiri Denemark <jdenemar@redhat.com> |
| |
| 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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -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 |
| + * <http://www.gnu.org/licenses/>. |
| + * |
| + */ |
| + |
| +#include <config.h> |
| +#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 |
| |
| |
| @@ -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 |
| + * <http://www.gnu.org/licenses/>. |
| + * |
| + */ |
| + |
| +#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 |
| |