This patch adds functions for various usages of modprobe
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
configure.ac | 6 ++
src/Makefile.am | 1 +
src/libvirt_private.syms | 7 ++
src/util/virkmod.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/virkmod.h | 34 +++++++++
5 files changed, 230 insertions(+)
create mode 100644 src/util/virkmod.c
create mode 100644 src/util/virkmod.h
diff --git a/configure.ac b/configure.ac
index 1670a41..eb11e3b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -405,6 +405,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],
@@ -433,6 +435,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 abe0a51..b704045 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -125,6 +125,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 45f3117..372231c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1382,6 +1382,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..d39a2e3
--- /dev/null
+++ b/src/util/virkmod.c
@@ -0,0 +1,182 @@
+/*
+ * 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", 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;
+
+ /* Find module on blacklist? */
+ 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
+ * <
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.4.2