]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
util: create new virmodule.{c,h} files for dlopen support code
authorDaniel P. Berrangé <berrange@redhat.com>
Wed, 25 Apr 2018 14:35:27 +0000 (15:35 +0100)
committerDaniel P. Berrangé <berrange@redhat.com>
Thu, 3 May 2018 11:47:43 +0000 (12:47 +0100)
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@redhat.com>
src/driver.c
src/driver.h
src/libvirt_driver_modules.syms
src/libvirt_private.syms
src/storage/storage_backend.c
src/util/Makefile.inc.am
src/util/virmodule.c [new file with mode: 0644]
src/util/virmodule.h [new file with mode: 0644]

index 447f61d554fcae1cf44e3e0302608f7f42b1ac72..8b5ade763f7725c5f80a5b4ea132bc8c7792a6a2 100644 (file)
@@ -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);
 
index b4e50ab9873a5edf6148736f1a802d1a8a2856d6..0b1f7a2269e1696049576b5f144b34740f7a514c 100644 (file)
@@ -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);
index bd9bf1c3151d4b7ca396dd58036cd3ecca5d3608..f9d0ee9b971407ca4c429c38e25c68558aeffa09 100644 (file)
@@ -4,7 +4,6 @@
 
 # driver.h
 virDriverLoadModule;
-virDriverLoadModuleFull;
 
 # Let emacs know we want case-insensitive sorting
 # Local Variables:
index d2728749fb2ddc0fe5514bb53e049be828456680..1051a105b87164edf750dbc2f89beb3c6339b91c 100644 (file)
@@ -2228,6 +2228,9 @@ virMediatedDeviceTypeFree;
 virMediatedDeviceTypeReadAttrs;
 
 
+# util/virmodule.h
+virModuleLoad;
+
 
 # util/virnetdev.h
 virNetDevAddMulti;
index cb1bcc0944f0eea56529f238cd1da78821ceaf85..7d226f3d3aab5b74bd0a48c898f3cf9c17ca08dc 100644 (file)
@@ -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);
 
index 9624fb687c4298aa92bd032691bb86a30c00765f..ec8745da7e9a1394b7cc34949396c3d6de42d176 100644 (file)
@@ -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 (file)
index 0000000..ff8c227
--- /dev/null
@@ -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 (file)
index 0000000..cccd836
--- /dev/null
@@ -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__ */