@@ -26,6 +26,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/qbool.h"
@@ -252,11 +253,30 @@ BlockDriverState *bdrv_new(void)
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;
}
@@ -457,8 +477,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);
@@ -480,6 +507,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 */
@@ -506,6 +534,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)) {
@@ -513,6 +542,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;
}
@@ -535,8 +581,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);
@@ -2794,6 +2847,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) {
@@ -2811,6 +2865,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++) {
@@ -5261,7 +5261,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
@@ -52,9 +52,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
new file mode 100644
@@ -0,0 +1,90 @@
+/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+/*
+ * QEMU Block Module Infrastructure
+ *
+ * Copyright Red Hat, Inc. 2015
+ *
+ * Authors:
+ * Marc Mari <markmb@redhat.com>
+ *
+ * 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
+
@@ -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;
}
}