qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 1/2] Add dynamic module loading for block dri


From: Denis V. Lunev
Subject: Re: [Qemu-devel] [PATCH v2 1/2] Add dynamic module loading for block drivers
Date: Mon, 21 Sep 2015 16:49:06 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0

On 09/08/2015 04:53 PM, Marc Marí wrote:
Extend the current module interface to allow for block drivers to be loaded
dynamically on request.

The only block drivers that can be converted into modules are the drivers
that don't perform any init operation except for registering themselves. This
is why libiscsi has been disabled as a module.

All the necessary module information is located in a new structure found in
include/qemu/module_block.h

Signed-off-by: Marc Marí <address@hidden>
---
  block.c                     | 70 +++++++++++++++++++++++++++++++++++
  configure                   |  2 +-
  include/qemu/module.h       |  3 ++
  include/qemu/module_block.h | 90 +++++++++++++++++++++++++++++++++++++++++++++
  util/module.c               | 38 ++++++-------------
  5 files changed, 175 insertions(+), 28 deletions(-)
  create mode 100644 include/qemu/module_block.h

diff --git a/block.c b/block.c
index 090923c..814429a 100644
--- a/block.c
+++ b/block.c
@@ -27,6 +27,7 @@
  #include "block/block_int.h"
  #include "block/blockjob.h"
  #include "qemu/error-report.h"
+#include "qemu/module_block.h"
  #include "qemu/module.h"
  #include "qapi/qmp/qerror.h"
  #include "qapi/qmp/qjson.h"
@@ -277,11 +278,30 @@ void bdrv_add_close_notifier(BlockDriverState *bs, 
Notifier *notify)
  BlockDriver *bdrv_find_format(const char *format_name)
  {
      BlockDriver *drv1;
+    size_t i;
+
      QLIST_FOREACH(drv1, &bdrv_drivers, list) {
          if (!strcmp(drv1->format_name, format_name)) {
              return drv1;
          }
      }
+
+    for (i = 0; i < ARRAY_SIZE(block_driver_modules); ++i) {
+        if (!strcmp(block_driver_modules[i].format_name, format_name)) {
+            block_module_load_one(block_driver_modules[i].library_name);
+            /* Copying code is not nice, but this way the current discovery is
+             * not modified. Calling recursively could fail if the library
+             * has been deleted.
+             */
+            QLIST_FOREACH(drv1, &bdrv_drivers, list) {
+                if (!strcmp(drv1->format_name, format_name)) {
+                    return drv1;
+                }
+            }
+        }
+    }
+
+
      return NULL;
  }
@@ -484,8 +504,15 @@ int get_tmp_filename(char *filename, int size)
  static BlockDriver *find_hdev_driver(const char *filename)
  {
      int score_max = 0, score;
+    size_t i;
      BlockDriver *drv = NULL, *d;
+ for (i = 0; i < ARRAY_SIZE(block_driver_modules); ++i) {
+        if (block_driver_modules[i].has_probe_device) {
+            block_module_load_one(block_driver_modules[i].library_name);
+        }
+    }
+
      QLIST_FOREACH(d, &bdrv_drivers, list) {
          if (d->bdrv_probe_device) {
              score = d->bdrv_probe_device(filename);
@@ -507,6 +534,7 @@ BlockDriver *bdrv_find_protocol(const char *filename,
      char protocol[128];
      int len;
      const char *p;
+    size_t i;
/* TODO Drivers without bdrv_file_open must be specified explicitly */ @@ -533,6 +561,7 @@ BlockDriver *bdrv_find_protocol(const char *filename,
          len = sizeof(protocol) - 1;
      memcpy(protocol, filename, len);
      protocol[len] = '\0';
+
      QLIST_FOREACH(drv1, &bdrv_drivers, list) {
          if (drv1->protocol_name &&
              !strcmp(drv1->protocol_name, protocol)) {
@@ -540,6 +569,23 @@ BlockDriver *bdrv_find_protocol(const char *filename,
          }
      }
+ for (i = 0; i < ARRAY_SIZE(block_driver_modules); ++i) {
+        if (block_driver_modules[i].protocol_name &&
+            !strcmp(block_driver_modules[i].protocol_name, protocol)) {
+            block_module_load_one(block_driver_modules[i].library_name);
+            /* Copying code is not nice, but this way the current discovery is
+             * not modified. Calling recursively could fail if the library
+             * has been deleted.
+             */
+            QLIST_FOREACH(drv1, &bdrv_drivers, list) {
+                if (drv1->protocol_name &&
+                    !strcmp(drv1->protocol_name, protocol)) {
+                    return drv1;
+                }
+            }
+        }
+    }
+
      error_setg(errp, "Unknown protocol '%s'", protocol);
      return NULL;
  }
@@ -562,8 +608,15 @@ BlockDriver *bdrv_probe_all(const uint8_t *buf, int 
buf_size,
                              const char *filename)
  {
      int score_max = 0, score;
+    size_t i;
      BlockDriver *drv = NULL, *d;
+ for (i = 0; i < ARRAY_SIZE(block_driver_modules); ++i) {
+        if (block_driver_modules[i].has_probe) {
+            block_module_load_one(block_driver_modules[i].library_name);
+        }
+    }
+
      QLIST_FOREACH(d, &bdrv_drivers, list) {
          if (d->bdrv_probe) {
              score = d->bdrv_probe(buf, buf_size, filename);
@@ -2784,6 +2837,7 @@ void bdrv_iterate_format(void (*it)(void *opaque, const 
char *name),
      BlockDriver *drv;
      int count = 0;
      int i;
+    size_t n;
      const char **formats = NULL;
QLIST_FOREACH(drv, &bdrv_drivers, list) {
@@ -2801,6 +2855,22 @@ void bdrv_iterate_format(void (*it)(void *opaque, const 
char *name),
          }
      }
+ for (n = 0; n < ARRAY_SIZE(block_driver_modules); ++n) {
+        if (block_driver_modules[n].format_name) {
+            bool found = false;
+            int i = count;
+            while (formats && i && !found) {
+                found = !strcmp(formats[--i],
+                                block_driver_modules[n].format_name);
+            }
+
+            if (!found) {
+                formats = g_renew(const char *, formats, count + 1);
+                formats[count++] = block_driver_modules[n].format_name;
+            }
+        }
+    }
+
      qsort(formats, count, sizeof(formats[0]), qsort_strcmp);
for (i = 0; i < count; i++) {
diff --git a/configure b/configure
index d854936..72ac564 100755
--- a/configure
+++ b/configure
@@ -4984,7 +4984,7 @@ if test "$bzip2" = "yes" ; then
  fi
if test "$libiscsi" = "yes" ; then
-  echo "CONFIG_LIBISCSI=m" >> $config_host_mak
+  echo "CONFIG_LIBISCSI=y" >> $config_host_mak
    echo "LIBISCSI_CFLAGS=$libiscsi_cflags" >> $config_host_mak
    echo "LIBISCSI_LIBS=$libiscsi_libs" >> $config_host_mak
  fi
diff --git a/include/qemu/module.h b/include/qemu/module.h
index 72d9498..0ad4bb7 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -53,9 +53,12 @@ typedef enum {
  #define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
  #define type_init(function) module_init(function, MODULE_INIT_QOM)
+#define block_module_load_one(lib) module_load_one("block-", lib);
+
  void register_module_init(void (*fn)(void), module_init_type type);
  void register_dso_module_init(void (*fn)(void), module_init_type type);
void module_call_init(module_init_type type);
+void module_load_one(const char *prefix, const char *lib_name);
#endif
diff --git a/include/qemu/module_block.h b/include/qemu/module_block.h
new file mode 100644
index 0000000..d725db8
--- /dev/null
+++ b/include/qemu/module_block.h
@@ -0,0 +1,90 @@
+/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+/*
+ * QEMU Block Module Infrastructure
+ *
+ * Copyright Red Hat, Inc. 2015
+ *
+ * Authors:
+ *  Marc Mari       <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_MODULE_BLOCK_H
+#define QEMU_MODULE_BLOCK_H
+
+#include "qemu-common.h"
+
+static const struct {
+    const char *format_name;
+    const char *protocol_name;
+    const char *library_name;
+    bool has_probe;
+    bool has_probe_device;
+} block_driver_modules[] = {
+       {
+       .library_name = "curl",
+       .format_name = "http",
+       .protocol_name = "http",
+       },
+       {
+       .library_name = "curl",
+       .format_name = "https",
+       .protocol_name = "https",
+       },
+       {
+       .library_name = "curl",
+       .format_name = "ftp",
+       .protocol_name = "ftp",
+       },
+       {
+       .library_name = "curl",
+       .format_name = "ftps",
+       .protocol_name = "ftps",
+       },
+       {
+       .library_name = "curl",
+       .format_name = "tftp",
+       .protocol_name = "tftp",
+       },
+       {
+       .library_name = "rbd",
+       .format_name = "rbd",
+       .protocol_name = "rbd",
+       },
+       {
+       .library_name = "gluster",
+       .format_name = "gluster",
+       .protocol_name = "gluster",
+       },
+       {
+       .library_name = "gluster",
+       .format_name = "gluster",
+       .protocol_name = "gluster+tcp",
+       },
+       {
+       .library_name = "gluster",
+       .format_name = "gluster",
+       .protocol_name = "gluster+unix",
+       },
+       {
+       .library_name = "gluster",
+       .format_name = "gluster",
+       .protocol_name = "gluster+rdma",
+       },
+       {
+       .library_name = "ssh",
+       .format_name = "ssh",
+       .protocol_name = "ssh",
+       },
+       {
+       .library_name = "dmg",
+       .format_name = "dmg",
+       .has_probe = true,
+       },
+};
+
+#endif
+
diff --git a/util/module.c b/util/module.c
index 4bd4a94..992d317 100644
--- a/util/module.c
+++ b/util/module.c
@@ -91,14 +91,11 @@ void register_dso_module_init(void (*fn)(void), 
module_init_type type)
      QTAILQ_INSERT_TAIL(&dso_init_list, e, node);
  }
-static void module_load(module_init_type type);
-
  void module_call_init(module_init_type type)
  {
      ModuleTypeList *l;
      ModuleEntry *e;
- module_load(type);
      l = find_type(type);
QTAILQ_FOREACH(e, l, node) {
@@ -149,6 +146,7 @@ static int module_load_file(const char *fname)
          ret = -EINVAL;
      } else {
          QTAILQ_FOREACH(e, &dso_init_list, node) {
+            e->init();
              register_module_init(e->init, e->type);
          }
          ret = 0;
@@ -163,14 +161,10 @@ out:
  }
  #endif
-static void module_load(module_init_type type)
+void module_load_one(const char *prefix, const char *lib_name)
  {
  #ifdef CONFIG_MODULES
      char *fname = NULL;
-    const char **mp;
-    static const char *block_modules[] = {
-        CONFIG_BLOCK_MODULES
-    };
      char *exec_dir;
      char *dirs[3];
      int i = 0;
@@ -181,15 +175,6 @@ static void module_load(module_init_type type)
          return;
      }
- switch (type) {
-    case MODULE_INIT_BLOCK:
-        mp = block_modules;
-        break;
-    default:
-        /* no other types have dynamic modules for now*/
-        return;
-    }
-
      exec_dir = qemu_get_exec_dir();
      dirs[i++] = g_strdup_printf("%s", CONFIG_QEMU_MODDIR);
      dirs[i++] = g_strdup_printf("%s/..", exec_dir ? : "");
@@ -198,16 +183,15 @@ static void module_load(module_init_type type)
      g_free(exec_dir);
      exec_dir = NULL;
- for ( ; *mp; mp++) {
-        for (i = 0; i < ARRAY_SIZE(dirs); i++) {
-            fname = g_strdup_printf("%s/%s%s", dirs[i], *mp, HOST_DSOSUF);
-            ret = module_load_file(fname);
-            g_free(fname);
-            fname = NULL;
-            /* Try loading until loaded a module file */
-            if (!ret) {
-                break;
-            }
+    for (i = 0; i < ARRAY_SIZE(dirs); i++) {
+        fname = g_strdup_printf("%s/%s%s%s",
+                dirs[i], prefix, lib_name, HOST_DSOSUF);
+        ret = module_load_file(fname);
+        g_free(fname);
+        fname = NULL;
+        /* Try loading until loaded a module file */
+        if (!ret) {
+            break;
          }
      }
I think that the API will be more convenient if block_module_load_one
will return just loaded driver. Second loop will not be needed in this
case.

Den



reply via email to

[Prev in Thread] Current Thread [Next in Thread]