[libvirt] [PATCH 1/6] util: create new virmodule.{c, h} files for dlopen support code

Daniel P. Berrangé berrange at redhat.com
Wed Apr 25 15:52:38 UTC 2018


The driver.{c,h} files are primarily targetted at loading hypervisor
drivers and some helper functions in that area. It also, however,
contains a generically useful function for loading extension modules
that is called by the storage driver. Split that functionality off
into a new virmodule.{c,h} file to isolate it.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 src/driver.c                    | 133 +-------------------------------
 src/driver.h                    |   3 -
 src/libvirt_driver_modules.syms |   1 -
 src/libvirt_private.syms        |   3 +
 src/storage/storage_backend.c   |   3 +-
 src/util/Makefile.inc.am        |   2 +
 src/util/virmodule.c            | 163 ++++++++++++++++++++++++++++++++++++++++
 src/util/virmodule.h            |  29 +++++++
 8 files changed, 201 insertions(+), 136 deletions(-)
 create mode 100644 src/util/virmodule.c
 create mode 100644 src/util/virmodule.h

diff --git a/src/driver.c b/src/driver.c
index 447f61d554..8b5ade763f 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -28,6 +28,7 @@
 #include "viralloc.h"
 #include "virfile.h"
 #include "virlog.h"
+#include "virmodule.h"
 #include "virthread.h"
 #include "configmake.h"
 
@@ -38,136 +39,6 @@ VIR_LOG_INIT("driver");
 /* XXX re-implement this for other OS, or use libtools helper lib ? */
 #define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/connection-driver"
 
-#ifdef HAVE_DLFCN_H
-# include <dlfcn.h>
-
-
-static void *
-virDriverLoadModuleFile(const char *file)
-{
-    void *handle = NULL;
-    int flags = RTLD_NOW | RTLD_GLOBAL;
-
-# ifdef RTLD_NODELETE
-    flags |= RTLD_NODELETE;
-# endif
-
-    VIR_DEBUG("Load module file '%s'", file);
-
-    virUpdateSelfLastChanged(file);
-
-    if (!(handle = dlopen(file, flags))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Failed to load module '%s': %s"), file, dlerror());
-        return NULL;
-    }
-
-    return handle;
-}
-
-
-static void *
-virDriverLoadModuleFunc(void *handle,
-                        const char *file,
-                        const char *funcname)
-{
-    void *regsym;
-
-    VIR_DEBUG("Lookup function '%s'", funcname);
-
-    if (!(regsym = dlsym(handle, funcname))) {
-        virReportError(VIR_ERR_INTERNAL_ERROR,
-                       _("Failed to find symbol '%s' in module '%s': %s"),
-                       funcname, file, dlerror());
-        return NULL;
-    }
-
-    return regsym;
-}
-
-
-/**
- * virDriverLoadModuleFull:
- * @path: filename of module to load
- * @regfunc: name of the function that registers the module
- *
- * Loads a loadable module named @path and calls the
- * registration function @regfunc. The module will never
- * be unloaded because unloading is not safe in a multi-threaded
- * application.
- *
- * The module is automatically looked up in the appropriate place (git or
- * installed directory).
- *
- * Returns 0 on success, 1 if the module was not found and -1 on any error.
- */
-int
-virDriverLoadModuleFull(const char *path,
-                        const char *regfunc,
-                        bool required)
-{
-    void *rethandle = NULL;
-    int (*regsym)(void);
-    int ret = -1;
-
-    if (!virFileExists(path)) {
-        if (required) {
-            virReportSystemError(errno,
-                                 _("Failed to find module '%s'"), path);
-            return -1;
-        } else {
-            VIR_INFO("Module '%s' does not exist", path);
-            return 1;
-        }
-    }
-
-    if (!(rethandle = virDriverLoadModuleFile(path)))
-        goto cleanup;
-
-    if (!(regsym = virDriverLoadModuleFunc(rethandle, path, regfunc)))
-        goto cleanup;
-
-    if ((*regsym)() < 0) {
-        /* regsym() should report an error itself, but lets
-         * just make sure */
-        virErrorPtr err = virGetLastError();
-        if (err == NULL) {
-            virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Failed to execute symbol '%s' in module '%s'"),
-                           regfunc, path);
-        }
-        goto cleanup;
-    }
-
-    rethandle = NULL;
-    ret = 0;
-
- cleanup:
-    if (rethandle)
-        dlclose(rethandle);
-    return ret;
-}
-
-#else /* ! HAVE_DLFCN_H */
-int
-virDriverLoadModuleFull(const char *path ATTRIBUTE_UNUSED,
-                        const char *regfunc ATTRIBUTE_UNUSED,
-                        bool required)
-{
-    VIR_DEBUG("dlopen not available on this platform");
-    if (required) {
-        virReportSystemError(ENOSYS,
-                             _("Failed to find module '%s': %s"), path);
-        return -1;
-    } else {
-        /* Since we have no dlopen(), but definition we have no
-         * loadable modules on disk, so we can resaonably
-         * return '1' instead of an error.
-         */
-        return 1;
-    }
-}
-#endif /* ! HAVE_DLFCN_H */
 
 
 int
@@ -188,7 +59,7 @@ virDriverLoadModule(const char *name,
                                             "LIBVIRT_DRIVER_DIR")))
         return -1;
 
-    ret = virDriverLoadModuleFull(modfile, regfunc, required);
+    ret = virModuleLoad(modfile, regfunc, required);
 
     VIR_FREE(modfile);
 
diff --git a/src/driver.h b/src/driver.h
index b4e50ab987..0b1f7a2269 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -110,9 +110,6 @@ int virSetSharedStorageDriver(virStorageDriverPtr driver) ATTRIBUTE_RETURN_CHECK
 int virDriverLoadModule(const char *name,
                         const char *regfunc,
                         bool required);
-int virDriverLoadModuleFull(const char *path,
-                            const char *regfunc,
-                            bool required);
 
 virConnectPtr virGetConnectInterface(void);
 virConnectPtr virGetConnectNetwork(void);
diff --git a/src/libvirt_driver_modules.syms b/src/libvirt_driver_modules.syms
index bd9bf1c315..f9d0ee9b97 100644
--- a/src/libvirt_driver_modules.syms
+++ b/src/libvirt_driver_modules.syms
@@ -4,7 +4,6 @@
 
 # driver.h
 virDriverLoadModule;
-virDriverLoadModuleFull;
 
 # Let emacs know we want case-insensitive sorting
 # Local Variables:
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d2728749fb..1051a105b8 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2228,6 +2228,9 @@ virMediatedDeviceTypeFree;
 virMediatedDeviceTypeReadAttrs;
 
 
+# util/virmodule.h
+virModuleLoad;
+
 
 # util/virnetdev.h
 virNetDevAddMulti;
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index cb1bcc0944..7d226f3d3a 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -33,6 +33,7 @@
 #include "virstoragefile.h"
 #include "storage_backend.h"
 #include "virlog.h"
+#include "virmodule.h"
 #include "virfile.h"
 #include "configmake.h"
 
@@ -97,7 +98,7 @@ virStorageDriverLoadBackendModule(const char *name,
                                             "LIBVIRT_STORAGE_BACKEND_DIR")))
         return -1;
 
-    ret = virDriverLoadModuleFull(modfile, regfunc, forceload);
+    ret = virModuleLoad(modfile, regfunc, forceload);
 
     VIR_FREE(modfile);
 
diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am
index 9624fb687c..ec8745da7e 100644
--- a/src/util/Makefile.inc.am
+++ b/src/util/Makefile.inc.am
@@ -100,6 +100,8 @@ UTIL_SOURCES = \
 	util/virmacaddr.h \
 	util/virmacmap.c \
 	util/virmacmap.h \
+	util/virmodule.c \
+	util/virmodule.h \
 	util/virnetdev.c \
 	util/virnetdev.h \
 	util/virnetdevbandwidth.c \
diff --git a/src/util/virmodule.c b/src/util/virmodule.c
new file mode 100644
index 0000000000..ff8c22752e
--- /dev/null
+++ b/src/util/virmodule.c
@@ -0,0 +1,163 @@
+/*
+ * virmodule.c: APIs for dlopen'ing extension modules
+ *
+ * Copyright (C) 2012-2018 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 "internal.h"
+#include "virmodule.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virlog.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.module");
+
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+
+static void *
+virModuleLoadFile(const char *file)
+{
+    void *handle = NULL;
+    int flags = RTLD_NOW | RTLD_GLOBAL;
+
+# ifdef RTLD_NODELETE
+    flags |= RTLD_NODELETE;
+# endif
+
+    VIR_DEBUG("Load module file '%s'", file);
+
+    virUpdateSelfLastChanged(file);
+
+    if (!(handle = dlopen(file, flags))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to load module '%s': %s"), file, dlerror());
+        return NULL;
+    }
+
+    return handle;
+}
+
+
+static void *
+virModuleLoadFunc(void *handle,
+                  const char *file,
+                  const char *funcname)
+{
+    void *regsym;
+
+    VIR_DEBUG("Lookup function '%s'", funcname);
+
+    if (!(regsym = dlsym(handle, funcname))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("Failed to find symbol '%s' in module '%s': %s"),
+                       funcname, file, dlerror());
+        return NULL;
+    }
+
+    return regsym;
+}
+
+
+/**
+ * virModuleLoad:
+ * @path: filename of module to load
+ * @regfunc: name of the function that registers the module
+ * @required: true if module must exist on disk, false to silently skip
+ *
+ * Loads a loadable module named @path and calls the
+ * registration function @regfunc. The module will never
+ * be unloaded because unloading is not safe in a multi-threaded
+ * application.
+ *
+ * The module is automatically looked up in the appropriate place (git or
+ * installed directory).
+ *
+ * Returns 0 on success, 1 if the module was not found and -1 on any error.
+ */
+int
+virModuleLoad(const char *path,
+              const char *regfunc,
+              bool required)
+{
+    void *rethandle = NULL;
+    int (*regsym)(void);
+    int ret = -1;
+
+    if (!virFileExists(path)) {
+        if (required) {
+            virReportSystemError(errno,
+                                 _("Failed to find module '%s'"), path);
+            return -1;
+        } else {
+            VIR_INFO("Module '%s' does not exist", path);
+            return 1;
+        }
+    }
+
+    if (!(rethandle = virModuleLoadFile(path)))
+        goto cleanup;
+
+    if (!(regsym = virModuleLoadFunc(rethandle, path, regfunc)))
+        goto cleanup;
+
+    if ((*regsym)() < 0) {
+        /* regsym() should report an error itself, but lets
+         * just make sure */
+        virErrorPtr err = virGetLastError();
+        if (err == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Failed to execute symbol '%s' in module '%s'"),
+                           regfunc, path);
+        }
+        goto cleanup;
+    }
+
+    rethandle = NULL;
+    ret = 0;
+
+ cleanup:
+    if (rethandle)
+        dlclose(rethandle);
+    return ret;
+}
+
+#else /* ! HAVE_DLFCN_H */
+int
+virModuleLoad(const char *path ATTRIBUTE_UNUSED,
+              const char *regfunc ATTRIBUTE_UNUSED,
+              bool required)
+{
+    VIR_DEBUG("dlopen not available on this platform");
+    if (required) {
+        virReportSystemError(ENOSYS,
+                             _("Failed to find module '%s': %s"), path);
+        return -1;
+    } else {
+        /* Since we have no dlopen(), but definition we have no
+         * loadable modules on disk, so we can resaonably
+         * return '1' instead of an error.
+         */
+        return 1;
+    }
+}
+#endif /* ! HAVE_DLFCN_H */
diff --git a/src/util/virmodule.h b/src/util/virmodule.h
new file mode 100644
index 0000000000..cccd836b41
--- /dev/null
+++ b/src/util/virmodule.h
@@ -0,0 +1,29 @@
+/*
+ * virmodule.h: APIs for dlopen'ing extension modules
+ *
+ * Copyright (C) 2012-2018 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_MODULE_H__
+# define __VIR_MODULE_H__
+
+int virModuleLoad(const char *path,
+                  const char *regfunc,
+                  bool required);
+
+#endif /* __VIR_MODULE_H__ */
-- 
2.14.3




More information about the libvir-list mailing list