[libvirt] [PATCH 04/11] driver: Split/refactor driver module loading

Peter Krempa pkrempa at redhat.com
Wed Feb 8 16:27:04 UTC 2017


Split the convoluted driver loader function into simpler parts which
will potentially allow reuse.
---
 src/driver.c                    | 133 +++++++++++++++++++++++++++++-----------
 src/driver.h                    |   3 +
 src/libvirt_driver_modules.syms |   1 +
 3 files changed, 101 insertions(+), 36 deletions(-)

diff --git a/src/driver.c b/src/driver.c
index 67ac02006..783e08a28 100644
--- a/src/driver.c
+++ b/src/driver.c
@@ -43,15 +43,105 @@ VIR_LOG_INIT("driver");
 # include <dlfcn.h>
 # define DEFAULT_DRIVER_DIR LIBDIR "/libvirt/connection-driver"

+
+static void *
+virDriverLoadModuleFile(const char *file)
+{
+    void *handle = NULL;
+
+    VIR_DEBUG("Load module file '%s'", file);
+
+    if (access(file, R_OK) < 0) {
+        VIR_INFO("Module %s not accessible", file);
+        return NULL;
+    }
+
+    virUpdateSelfLastChanged(file);
+
+    if (!(handle = dlopen(file, RTLD_NOW | RTLD_GLOBAL)))
+        VIR_ERROR(_("failed to load module %s %s"), file, dlerror());
+
+    return handle;
+}
+
+
+static void *
+virDriverLoadModuleFunc(void *handle,
+                        const char *funcname)
+{
+    void *regsym;
+
+    VIR_DEBUG("Lookup function '%s'", funcname);
+
+    if (!(regsym = dlsym(handle, funcname)))
+        VIR_ERROR(_("Missing module registration symbol %s"), funcname);
+
+    return regsym;
+}
+
+
+/**
+ * virDriverLoadModuleFull:
+ * @path: filename of module to load
+ * @regfunc: name of the function that registers the module
+ * @handle: Returns handle of the loaded library if not NULL
+ *
+ * Loads a loadable module named @path and calls the
+ * registration function @regfunc. If @handle is not NULL the handle is returned
+ * in the variable. Otherwise the handle is leaked so that the module stays
+ * loaded forever.
+ *
+ * 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,
+                        void **handle)
+{
+    void *rethandle = NULL;
+    int (*regsym)(void);
+    int ret = -1;
+
+    VIR_DEBUG("Module load %s", path);
+
+    if (!(rethandle = virDriverLoadModuleFile(path))) {
+        ret = 1;
+        goto cleanup;
+    }
+
+    if (!(regsym = virDriverLoadModuleFunc(rethandle, regfunc)))
+        goto cleanup;
+
+    if ((*regsym)() < 0) {
+        VIR_ERROR(_("Failed module registration %s"), regfunc);
+        goto cleanup;
+    }
+
+    if (handle)
+        VIR_STEAL_PTR(*handle, rethandle);
+    else
+        rethandle = NULL;
+
+    ret = 0;
+
+ cleanup:
+    if (rethandle)
+        dlclose(rethandle);
+    return ret;
+}
+
+
 void *
 virDriverLoadModule(const char *name)
 {
-    char *modfile = NULL, *regfunc = NULL, *fixedname = NULL;
+    char *modfile = NULL;
+    char *fixedname = NULL;
+    char *regfunc = NULL;
     char *tmp;
     void *handle = NULL;
-    int (*regsym)(void);
-
-    VIR_DEBUG("Module load %s", name);

     if (!(modfile = virFileFindResourceFull(name,
                                             "libvirt_driver_",
@@ -61,19 +151,6 @@ virDriverLoadModule(const char *name)
                                             "LIBVIRT_DRIVER_DIR")))
         return NULL;

-    if (access(modfile, R_OK) < 0) {
-        VIR_INFO("Module %s not accessible", modfile);
-        goto cleanup;
-    }
-
-    virUpdateSelfLastChanged(modfile);
-
-    handle = dlopen(modfile, RTLD_NOW | RTLD_GLOBAL);
-    if (!handle) {
-        VIR_ERROR(_("failed to load module %s %s"), modfile, dlerror());
-        goto cleanup;
-    }
-
     if (VIR_STRDUP_QUIET(fixedname, name) < 0) {
         VIR_ERROR(_("out of memory"));
         goto cleanup;
@@ -88,29 +165,13 @@ virDriverLoadModule(const char *name)
     if (virAsprintfQuiet(&regfunc, "%sRegister", fixedname) < 0)
         goto cleanup;

-    regsym = dlsym(handle, regfunc);
-    if (!regsym) {
-        VIR_ERROR(_("Missing module registration symbol %s"), regfunc);
-        goto cleanup;
-    }
-
-    if ((*regsym)() < 0) {
-        VIR_ERROR(_("Failed module registration %s"), regfunc);
-        goto cleanup;
-    }
-
-    VIR_FREE(modfile);
-    VIR_FREE(regfunc);
-    VIR_FREE(fixedname);
-    return handle;
+    virDriverLoadModuleFull(modfile, regfunc, &handle);

  cleanup:
     VIR_FREE(modfile);
-    VIR_FREE(regfunc);
     VIR_FREE(fixedname);
-    if (handle)
-        dlclose(handle);
-    return NULL;
+    VIR_FREE(regfunc);
+    return handle;
 }


diff --git a/src/driver.h b/src/driver.h
index e4e382b63..885e8843e 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -100,5 +100,8 @@ int virSetSharedSecretDriver(virSecretDriverPtr driver) ATTRIBUTE_RETURN_CHECK;
 int virSetSharedStorageDriver(virStorageDriverPtr driver) ATTRIBUTE_RETURN_CHECK;

 void *virDriverLoadModule(const char *name);
+int virDriverLoadModuleFull(const char *name,
+                            const char *regfunc,
+                            void **handle);

 #endif /* __VIR_DRIVER_H__ */
diff --git a/src/libvirt_driver_modules.syms b/src/libvirt_driver_modules.syms
index f9d0ee9b9..bd9bf1c31 100644
--- a/src/libvirt_driver_modules.syms
+++ b/src/libvirt_driver_modules.syms
@@ -4,6 +4,7 @@

 # driver.h
 virDriverLoadModule;
+virDriverLoadModuleFull;

 # Let emacs know we want case-insensitive sorting
 # Local Variables:
-- 
2.11.0




More information about the libvir-list mailing list