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