* [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers @ 2015-08-17 8:09 Marc Marí 2015-08-17 8:09 ` [Qemu-devel] [PATCH 1/2] Add dynamic module loading " Marc Marí ` (3 more replies) 0 siblings, 4 replies; 14+ messages in thread From: Marc Marí @ 2015-08-17 8:09 UTC (permalink / raw) To: qemu-devel; +Cc: Marc Marí The current module infrastructure has been improved to enable dynamic module loading. This reduces the load time for very simple guests. For the following configuration (very loaded) ./configure --enable-sdl --enable-gtk --enable-vte --enable-curses \ --enable-vnc --enable-vnc-{jpeg,tls,sasl,png} --enable-virtfs \ --enable-brlapi --enable-curl --enable-fdt --enable-bluez \ --enable-kvm --enable-rdma --enable-uuid --enable-vde \ --enable-linux-aio --enable-cap-ng --enable-attr --enable-vhost-net \ --enable-vhost-scsi --enable-spice --enable-rbd --enable-libiscsi \ --enable-smartcard-nss --enable-guest-agent --enable-libusb \ --enable-usb-redir --enable-lzo --enable-snappy --enable-bzip2 \ --enable-seccomp --enable-coroutine-pool --enable-glusterfs \ --enable-tpm --enable-libssh2 --enable-vhdx --enable-numa \ --enable-tcmalloc --target-list=x86_64-softmmu With modules disabled, there are 142 libraries loaded at startup. Time is the following: LD time: 0.065 seconds QEMU time: 0.02 seconds Total time: 0.085 seconds With this patch series and modules enabled, there are 128 libraries loaded at startup. Time is the following: LD time: 0.02 seconds QEMU time: 0.02 seconds Total time: 0.04 seconds Where LD time is the time between the program startup and the jump to main, and QEMU time is the time between the start of main and the first kvm_entry. These results are just with a few block drivers, that were already a module. Adding more modules (block or not block) should be easy, and will reduce the load time even more. Marc Marí (2): Add dynamic module loading for block drivers Add dynamic generation of module_block.h .gitignore | 1 + Makefile | 10 ++- block.c | 73 +++++++++++++++++++++- configure | 2 +- include/qemu/module.h | 3 + include/qemu/module_block.h | 89 +++++++++++++++++++++++++++ scripts/modules/module_block.py | 132 ++++++++++++++++++++++++++++++++++++++++ util/module.c | 38 ++++-------- 8 files changed, 314 insertions(+), 34 deletions(-) create mode 100644 include/qemu/module_block.h create mode 100755 scripts/modules/module_block.py -- 2.4.3 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 1/2] Add dynamic module loading for block drivers 2015-08-17 8:09 [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers Marc Marí @ 2015-08-17 8:09 ` Marc Marí 2015-08-27 9:19 ` Daniel P. Berrange 2015-09-03 16:33 ` Stefan Hajnoczi 2015-08-17 8:09 ` [Qemu-devel] [PATCH 2/2] Add dynamic generation of module_block.h Marc Marí ` (2 subsequent siblings) 3 siblings, 2 replies; 14+ messages in thread From: Marc Marí @ 2015-08-17 8:09 UTC (permalink / raw) To: qemu-devel; +Cc: Marc Marí 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í <markmb@redhat.com> --- block.c | 73 +++++++++++++++++++++++++++++++++++-- configure | 2 +- include/qemu/module.h | 3 ++ include/qemu/module_block.h | 89 +++++++++++++++++++++++++++++++++++++++++++++ util/module.c | 38 ++++++------------- 5 files changed, 174 insertions(+), 31 deletions(-) create mode 100644 include/qemu/module_block.h diff --git a/block.c b/block.c index d088ee0..f24a624 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; + int i; + QLIST_FOREACH(drv1, &bdrv_drivers, list) { if (!strcmp(drv1->format_name, format_name)) { return drv1; } } + + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { + if (!strcmp(block_driver_module[i].format_name, format_name)) { + block_module_load_one(block_driver_module[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; } @@ -483,9 +503,15 @@ int get_tmp_filename(char *filename, int size) */ static BlockDriver *find_hdev_driver(const char *filename) { - int score_max = 0, score; + int score_max = 0, score, i; BlockDriver *drv = NULL, *d; + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { + if (block_driver_module[i].has_probe_device) { + block_module_load_one(block_driver_module[i].library_name); + } + } + QLIST_FOREACH(d, &bdrv_drivers, list) { if (d->bdrv_probe_device) { score = d->bdrv_probe_device(filename); @@ -507,6 +533,7 @@ BlockDriver *bdrv_find_protocol(const char *filename, char protocol[128]; int len; const char *p; + int i; /* TODO Drivers without bdrv_file_open must be specified explicitly */ @@ -533,6 +560,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 +568,23 @@ BlockDriver *bdrv_find_protocol(const char *filename, } } + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { + if (block_driver_module[i].protocol_name && + !strcmp(block_driver_module[i].protocol_name, protocol)) { + block_module_load_one(block_driver_module[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; } @@ -561,9 +606,15 @@ BlockDriver *bdrv_find_protocol(const char *filename, BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, const char *filename) { - int score_max = 0, score; + int score_max = 0, score, i; BlockDriver *drv = NULL, *d; + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { + if (block_driver_module[i].has_probe) { + block_module_load_one(block_driver_module[i].library_name); + } + } + QLIST_FOREACH(d, &bdrv_drivers, list) { if (d->bdrv_probe) { score = d->bdrv_probe(buf, buf_size, filename); @@ -2783,7 +2834,7 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), { BlockDriver *drv; int count = 0; - int i; + int i, n; const char **formats = NULL; QLIST_FOREACH(drv, &bdrv_drivers, list) { @@ -2801,6 +2852,22 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), } } + for (n = 0; n < ARRAY_SIZE(block_driver_module); ++n) { + if (block_driver_module[n].format_name) { + bool found = false; + int i = count; + while (formats && i && !found) { + found = !strcmp(formats[--i], + block_driver_module[n].format_name); + } + + if (!found) { + formats = g_renew(const char *, formats, count + 1); + formats[count++] = block_driver_module[n].format_name; + } + } + } + qsort(formats, count, sizeof(formats[0]), qsort_strcmp); for (i = 0; i < count; i++) { diff --git a/configure b/configure index cd219d8..9fca9ee 100755 --- a/configure +++ b/configure @@ -4971,7 +4971,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..f1d389c --- /dev/null +++ b/include/qemu/module_block.h @@ -0,0 +1,88 @@ +/* + * 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_module[] = { + { + .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 \ No newline at end of file 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; } } -- 2.4.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] Add dynamic module loading for block drivers 2015-08-17 8:09 ` [Qemu-devel] [PATCH 1/2] Add dynamic module loading " Marc Marí @ 2015-08-27 9:19 ` Daniel P. Berrange 2015-08-27 9:35 ` Marc Marí 2015-09-03 16:33 ` Stefan Hajnoczi 1 sibling, 1 reply; 14+ messages in thread From: Daniel P. Berrange @ 2015-08-27 9:19 UTC (permalink / raw) To: Marc Marí; +Cc: qemu-devel On Mon, Aug 17, 2015 at 10:09:34AM +0200, 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. Seems like we would just need to split the iscsi opts registration out into a separate file that is permanently linked. > All the necessary module information is located in a new structure found in > include/qemu/module_block.h > > Signed-off-by: Marc Marí <markmb@redhat.com> > --- > block.c | 73 +++++++++++++++++++++++++++++++++++-- > configure | 2 +- > include/qemu/module.h | 3 ++ > include/qemu/module_block.h | 89 +++++++++++++++++++++++++++++++++++++++++++++ > util/module.c | 38 ++++++------------- > 5 files changed, 174 insertions(+), 31 deletions(-) > create mode 100644 include/qemu/module_block.h > > diff --git a/block.c b/block.c > index d088ee0..f24a624 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; > + int i; Nit-pick 'size_t' is a better type for loop iterators, especially when combined with a sizeof() comparison. Some comment in later functions too. > + > QLIST_FOREACH(drv1, &bdrv_drivers, list) { > if (!strcmp(drv1->format_name, format_name)) { > return drv1; > } > } > + > + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { > + if (!strcmp(block_driver_module[i].format_name, format_name)) { > + block_module_load_one(block_driver_module[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. > + */ Can you explaiin what you mean here about "if the library has been deleted" ? Are you referring to possibilty of dlclose()ing the previously loaded library, or about possibility of the module on disk having been deleted or something else ? > @@ -483,9 +503,15 @@ int get_tmp_filename(char *filename, int size) > */ > static BlockDriver *find_hdev_driver(const char *filename) > { > - int score_max = 0, score; > + int score_max = 0, score, i; > BlockDriver *drv = NULL, *d; > > + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { > + if (block_driver_module[i].has_probe_device) { > + block_module_load_one(block_driver_module[i].library_name); > + } > + } If we have multiuple disks of the same type given to QEMU, it seems like we might end up calling block_module_load_one() multiple times for the same module & end up loading the same .so multiple times as a result. Should module_load() keep a record of everything it has loaded and short-circuit itself to a no-op, so that callers of module_load() don't have to worry about avoiding multiple calls. > + > QLIST_FOREACH(d, &bdrv_drivers, list) { > if (d->bdrv_probe_device) { > score = d->bdrv_probe_device(filename); > @@ -507,6 +533,7 @@ BlockDriver *bdrv_find_protocol(const char *filename, > char protocol[128]; > int len; > const char *p; > + int i; > > /* TODO Drivers without bdrv_file_open must be specified explicitly */ > > @@ -533,6 +560,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 +568,23 @@ BlockDriver *bdrv_find_protocol(const char *filename, > } > } > > + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { > + if (block_driver_module[i].protocol_name && > + !strcmp(block_driver_module[i].protocol_name, protocol)) { > + block_module_load_one(block_driver_module[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; > } > @@ -561,9 +606,15 @@ BlockDriver *bdrv_find_protocol(const char *filename, > BlockDriver *bdrv_probe_all(const uint8_t *buf, int buf_size, > const char *filename) > { > - int score_max = 0, score; > + int score_max = 0, score, i; > BlockDriver *drv = NULL, *d; > > + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { > + if (block_driver_module[i].has_probe) { > + block_module_load_one(block_driver_module[i].library_name); > + } > + } > + > QLIST_FOREACH(d, &bdrv_drivers, list) { > if (d->bdrv_probe) { > score = d->bdrv_probe(buf, buf_size, filename); > @@ -2783,7 +2834,7 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), > { > BlockDriver *drv; > int count = 0; > - int i; > + int i, n; > const char **formats = NULL; > > QLIST_FOREACH(drv, &bdrv_drivers, list) { > @@ -2801,6 +2852,22 @@ void bdrv_iterate_format(void (*it)(void *opaque, const char *name), > } > } > > + for (n = 0; n < ARRAY_SIZE(block_driver_module); ++n) { > + if (block_driver_module[n].format_name) { > + bool found = false; > + int i = count; > + while (formats && i && !found) { > + found = !strcmp(formats[--i], > + block_driver_module[n].format_name); > + } > + > + if (!found) { > + formats = g_renew(const char *, formats, count + 1); > + formats[count++] = block_driver_module[n].format_name; > + } > + } > + } > + > qsort(formats, count, sizeof(formats[0]), qsort_strcmp); > > for (i = 0; i < count; i++) { > diff --git a/configure b/configure > index cd219d8..9fca9ee 100755 > --- a/configure > +++ b/configure > @@ -4971,7 +4971,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..f1d389c > --- /dev/null > +++ b/include/qemu/module_block.h > @@ -0,0 +1,88 @@ > +/* > + * 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. > + * > + */ [snip] > + > +#endif > \ No newline at end of file Missing newline at end of file :-) > 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) { Isn't the entire of module_call_init() a no-op now that you removed the module_load() call. IIUC, the find_type() method should return an empty list at that point, so the rest of the method doesn't nothing. IOW, I would think module_call_init() and its supporting functions can be deleted now. > @@ -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; > } > } > > -- > 2.4.3 > > Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] Add dynamic module loading for block drivers 2015-08-27 9:19 ` Daniel P. Berrange @ 2015-08-27 9:35 ` Marc Marí 2015-08-27 9:40 ` Daniel P. Berrange 0 siblings, 1 reply; 14+ messages in thread From: Marc Marí @ 2015-08-27 9:35 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: qemu-devel On Thu, 27 Aug 2015 10:19:35 +0100 "Daniel P. Berrange" <berrange@redhat.com> wrote: > On Mon, Aug 17, 2015 at 10:09:34AM +0200, 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. > > Seems like we would just need to split the iscsi opts registration out > into a separate file that is permanently linked. > > > All the necessary module information is located in a new structure > > found in include/qemu/module_block.h > > > > Signed-off-by: Marc Marí <markmb@redhat.com> > > --- > > block.c | 73 > > +++++++++++++++++++++++++++++++++++-- configure > > | 2 +- include/qemu/module.h | 3 ++ > > include/qemu/module_block.h | 89 > > +++++++++++++++++++++++++++++++++++++++++++++ > > util/module.c | 38 ++++++------------- 5 files > > changed, 174 insertions(+), 31 deletions(-) create mode 100644 > > include/qemu/module_block.h > > > > diff --git a/block.c b/block.c > > index d088ee0..f24a624 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; > > + int i; > > Nit-pick 'size_t' is a better type for loop iterators, especially > when combined with a sizeof() comparison. Some comment in later > functions too. > > > + > > QLIST_FOREACH(drv1, &bdrv_drivers, list) { > > if (!strcmp(drv1->format_name, format_name)) { > > return drv1; > > } > > } > > + > > + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { > > + if (!strcmp(block_driver_module[i].format_name, > > format_name)) { > > + > > block_module_load_one(block_driver_module[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. > > + */ > > Can you explaiin what you mean here about "if the library has been > deleted" ? > > Are you referring to possibilty of dlclose()ing the previously loaded > library, or about possibility of the module on disk having been > deleted or something else ? I was thinking of relaunching the search by calling recursively the function. But this would loop infinitely if somebody, manually, deleted the library file. > > @@ -483,9 +503,15 @@ int get_tmp_filename(char *filename, int size) > > */ > > static BlockDriver *find_hdev_driver(const char *filename) > > { > > - int score_max = 0, score; > > + int score_max = 0, score, i; > > BlockDriver *drv = NULL, *d; > > > > + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { > > + if (block_driver_module[i].has_probe_device) { > > + > > block_module_load_one(block_driver_module[i].library_name); > > + } > > + } > > If we have multiuple disks of the same type given to QEMU, it > seems like we might end up calling block_module_load_one() > multiple times for the same module & end up loading the same > .so multiple times as a result. Should module_load() keep a > record of everything it has loaded and short-circuit itself > to a no-op, so that callers of module_load() don't have to > worry about avoiding multiple calls. I avoided that because glib already has it. It just increments the reference count. Which is not important unless we want to dlclose it. https://developer.gnome.org/glib/stable/glib-Dynamic-Loading-of-Modules.html#g-module-open > > + > > QLIST_FOREACH(d, &bdrv_drivers, list) { > > if (d->bdrv_probe_device) { > > score = d->bdrv_probe_device(filename); > > @@ -507,6 +533,7 @@ BlockDriver *bdrv_find_protocol(const char > > *filename, char protocol[128]; > > int len; > > const char *p; > > + int i; > > > > /* TODO Drivers without bdrv_file_open must be specified > > explicitly */ > > @@ -533,6 +560,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 +568,23 @@ BlockDriver *bdrv_find_protocol(const char > > *filename, } > > } > > > > + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { > > + if (block_driver_module[i].protocol_name && > > + !strcmp(block_driver_module[i].protocol_name, > > protocol)) { > > + > > block_module_load_one(block_driver_module[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; > > } > > @@ -561,9 +606,15 @@ BlockDriver *bdrv_find_protocol(const char > > *filename, BlockDriver *bdrv_probe_all(const uint8_t *buf, int > > buf_size, const char *filename) > > { > > - int score_max = 0, score; > > + int score_max = 0, score, i; > > BlockDriver *drv = NULL, *d; > > > > + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { > > + if (block_driver_module[i].has_probe) { > > + > > block_module_load_one(block_driver_module[i].library_name); > > + } > > + } > > + > > QLIST_FOREACH(d, &bdrv_drivers, list) { > > if (d->bdrv_probe) { > > score = d->bdrv_probe(buf, buf_size, filename); > > @@ -2783,7 +2834,7 @@ void bdrv_iterate_format(void (*it)(void > > *opaque, const char *name), { > > BlockDriver *drv; > > int count = 0; > > - int i; > > + int i, n; > > const char **formats = NULL; > > > > QLIST_FOREACH(drv, &bdrv_drivers, list) { > > @@ -2801,6 +2852,22 @@ void bdrv_iterate_format(void (*it)(void > > *opaque, const char *name), } > > } > > > > + for (n = 0; n < ARRAY_SIZE(block_driver_module); ++n) { > > + if (block_driver_module[n].format_name) { > > + bool found = false; > > + int i = count; > > + while (formats && i && !found) { > > + found = !strcmp(formats[--i], > > + > > block_driver_module[n].format_name); > > + } > > + > > + if (!found) { > > + formats = g_renew(const char *, formats, count + > > 1); > > + formats[count++] = > > block_driver_module[n].format_name; > > + } > > + } > > + } > > + > > qsort(formats, count, sizeof(formats[0]), qsort_strcmp); > > > > for (i = 0; i < count; i++) { > > diff --git a/configure b/configure > > index cd219d8..9fca9ee 100755 > > --- a/configure > > +++ b/configure > > @@ -4971,7 +4971,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..f1d389c > > --- /dev/null > > +++ b/include/qemu/module_block.h > > @@ -0,0 +1,88 @@ > > +/* > > + * 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. > > + * > > + */ > > [snip] > > > + > > +#endif > > \ No newline at end of file > > Missing newline at end of file :-) Oops :). Anyway, this is deleted in the other patch :) > > 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) { > > Isn't the entire of module_call_init() a no-op now that you removed > the module_load() call. IIUC, the find_type() method should return > an empty list at that point, so the rest of the method doesn't > nothing. IOW, I would think module_call_init() and its supporting > functions can be deleted now. The module interface is no just for dynamic library loading but for loading all the devices into the system. Devices that are inside the monolithic QEMU still use this interface. So, it cannot be removed. Thanks Marc > > @@ -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; > > } > > } > > > > -- > > 2.4.3 > > > > > > Regards, > Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] Add dynamic module loading for block drivers 2015-08-27 9:35 ` Marc Marí @ 2015-08-27 9:40 ` Daniel P. Berrange 0 siblings, 0 replies; 14+ messages in thread From: Daniel P. Berrange @ 2015-08-27 9:40 UTC (permalink / raw) To: Marc Marí; +Cc: qemu-devel On Thu, Aug 27, 2015 at 11:35:41AM +0200, Marc Marí wrote: > On Thu, 27 Aug 2015 10:19:35 +0100 > "Daniel P. Berrange" <berrange@redhat.com> wrote: > > > On Mon, Aug 17, 2015 at 10:09:34AM +0200, 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. > > > > Seems like we would just need to split the iscsi opts registration out > > into a separate file that is permanently linked. > > > > > All the necessary module information is located in a new structure > > > found in include/qemu/module_block.h > > > > > > Signed-off-by: Marc Marí <markmb@redhat.com> > > > --- > > > block.c | 73 > > > +++++++++++++++++++++++++++++++++++-- configure > > > | 2 +- include/qemu/module.h | 3 ++ > > > include/qemu/module_block.h | 89 > > > +++++++++++++++++++++++++++++++++++++++++++++ > > > util/module.c | 38 ++++++------------- 5 files > > > changed, 174 insertions(+), 31 deletions(-) create mode 100644 > > > include/qemu/module_block.h > > > > > > diff --git a/block.c b/block.c > > > index d088ee0..f24a624 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; > > > + int i; > > > > Nit-pick 'size_t' is a better type for loop iterators, especially > > when combined with a sizeof() comparison. Some comment in later > > functions too. > > > > > + > > > QLIST_FOREACH(drv1, &bdrv_drivers, list) { > > > if (!strcmp(drv1->format_name, format_name)) { > > > return drv1; > > > } > > > } > > > + > > > + for (i = 0; i < ARRAY_SIZE(block_driver_module); ++i) { > > > + if (!strcmp(block_driver_module[i].format_name, > > > format_name)) { > > > + > > > block_module_load_one(block_driver_module[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. > > > + */ > > > > Can you explaiin what you mean here about "if the library has been > > deleted" ? > > > > Are you referring to possibilty of dlclose()ing the previously loaded > > library, or about possibility of the module on disk having been > > deleted or something else ? > > I was thinking of relaunching the search by calling recursively the > function. But this would loop infinitely if somebody, manually, deleted > the library file. Ok, yea, that makes sense. > If we have multiuple disks of the same type given to QEMU, it > > seems like we might end up calling block_module_load_one() > > multiple times for the same module & end up loading the same > > .so multiple times as a result. Should module_load() keep a > > record of everything it has loaded and short-circuit itself > > to a no-op, so that callers of module_load() don't have to > > worry about avoiding multiple calls. > > I avoided that because glib already has it. It just increments the > reference count. Which is not important unless we want to dlclose it. > > https://developer.gnome.org/glib/stable/glib-Dynamic-Loading-of-Modules.html#g-module-open Ah good. NB, it is almost never safe to use dlclose() in a multi-threaded application. A module may have created a thread-local variable with a destructor function registered. There's no way to clean these up prior to dlclose(), so the app would crash if you dlclose() and a thread then exits. Since it is impractical to audit all linked library code for use of thread locals, it is safest to just avoid any use of dlclose(). Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] Add dynamic module loading for block drivers 2015-08-17 8:09 ` [Qemu-devel] [PATCH 1/2] Add dynamic module loading " Marc Marí 2015-08-27 9:19 ` Daniel P. Berrange @ 2015-09-03 16:33 ` Stefan Hajnoczi 2015-09-03 18:01 ` Marc Marí 1 sibling, 1 reply; 14+ messages in thread From: Stefan Hajnoczi @ 2015-09-03 16:33 UTC (permalink / raw) To: Marc Marí; +Cc: qemu-devel On Mon, Aug 17, 2015 at 10:09:34AM +0200, Marc Marí wrote: > +static const struct { > + const char *format_name; > + const char *protocol_name; > + const char *library_name; > + bool has_probe; > + bool has_probe_device; > +} block_driver_module[] = { Why is this list incomplete? It doesn't cover all block drivers. Perhaps these are the only modular block drivers. Also, it ignores CONFIG_CURL and friends. Perhaps it doesn't matter because the module loading code will just see that there is no file there, but maybe conditional compilation should be used? A plural name would more consistent (i.e. you deleted the plural block_modules[] variable and introduced a singular block_driver_module[] variable). ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 1/2] Add dynamic module loading for block drivers 2015-09-03 16:33 ` Stefan Hajnoczi @ 2015-09-03 18:01 ` Marc Marí 0 siblings, 0 replies; 14+ messages in thread From: Marc Marí @ 2015-09-03 18:01 UTC (permalink / raw) To: Stefan Hajnoczi; +Cc: qemu-devel On Thu, 3 Sep 2015 17:33:16 +0100 Stefan Hajnoczi <stefanha@gmail.com> wrote: > On Mon, Aug 17, 2015 at 10:09:34AM +0200, Marc Marí wrote: > > +static const struct { > > + const char *format_name; > > + const char *protocol_name; > > + const char *library_name; > > + bool has_probe; > > + bool has_probe_device; > > +} block_driver_module[] = { > > Why is this list incomplete? It doesn't cover all block drivers. > Perhaps these are the only modular block drivers. I think we can decide on a protocol first (these patches), and then apply the changes to all (possible) drivers. At least, that was what I had in mind. > Also, it ignores CONFIG_CURL and friends. Perhaps it doesn't matter > because the module loading code will just see that there is no file > there, but maybe conditional compilation should be used? It's true that this patch doesn't look at the CONFIG options. But the next one does (it takes block-obj-m from the Makefile), and also replaces this file. Thanks Marc > A plural name would more consistent (i.e. you deleted the > plural block_modules[] variable and introduced a singular > block_driver_module[] variable). ^ permalink raw reply [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH 2/2] Add dynamic generation of module_block.h 2015-08-17 8:09 [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers Marc Marí 2015-08-17 8:09 ` [Qemu-devel] [PATCH 1/2] Add dynamic module loading " Marc Marí @ 2015-08-17 8:09 ` Marc Marí 2015-08-27 9:23 ` Daniel P. Berrange 2015-08-27 8:51 ` [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers Marc Marí 2015-09-03 16:12 ` Stefan Hajnoczi 3 siblings, 1 reply; 14+ messages in thread From: Marc Marí @ 2015-08-17 8:09 UTC (permalink / raw) To: qemu-devel; +Cc: Marc Marí To simplify the addition of new block modules, add a script that generates include/qemu/module_block.h automatically from the modules' source code. This script assumes that the QEMU coding style rules are followed. Signed-off-by: Marc Marí <markmb@redhat.com> --- .gitignore | 1 + Makefile | 10 ++- scripts/modules/module_block.py | 132 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 insertions(+), 3 deletions(-) create mode 100755 scripts/modules/module_block.py diff --git a/.gitignore b/.gitignore index 61bc492..8a37067 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,4 @@ cscope.* tags TAGS *~ +/include/qemu/module_block.h diff --git a/Makefile b/Makefile index 340d9c8..47d593e 100644 --- a/Makefile +++ b/Makefile @@ -73,6 +73,8 @@ GENERATED_HEADERS += trace/generated-ust-provider.h GENERATED_SOURCES += trace/generated-ust.c endif +GENERATED_HEADERS += include/qemu/module_block.h + # Don't try to regenerate Makefile or configure # We don't generate any of them Makefile: ; @@ -219,9 +221,6 @@ Makefile: $(version-obj-y) $(version-lobj-y) libqemustub.a: $(stub-obj-y) libqemuutil.a: $(util-obj-y) -block-modules = $(foreach o,$(block-obj-m),"$(basename $(subst /,-,$o))",) NULL -util/module.o-cflags = -D'CONFIG_BLOCK_MODULES=$(block-modules)' - ###################################################################### qemu-img.o: qemu-img-cmds.h @@ -313,6 +312,11 @@ msi: @echo MSI build not configured or dependency resolution failed (reconfigure with --enable-guest-agent-msi option) endif +include/qemu/module_block.h: $(SRC_PATH)/scripts/modules/module_block.py + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/modules/module_block.py \ + "./include/qemu/" $(patsubst %.mo,%.c,$(block-obj-m)), \ + " GEN $@") + clean: # avoid old build problems by removing potentially incorrect old files rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h diff --git a/scripts/modules/module_block.py b/scripts/modules/module_block.py new file mode 100755 index 0000000..a9a9412 --- /dev/null +++ b/scripts/modules/module_block.py @@ -0,0 +1,132 @@ +#!/usr/bin/python +# +# Module information generator +# +# 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. + +import sys +import os + +def get_string_struct(line): + data = line.split() + + # data[0] -> struct element name + # data[1] -> = + # data[2] -> value + + return data[2].replace('"', '')[:-1] + +def add_module(fhader, library, format_name, protocol_name, + probe, probe_device): + lines = [] + lines.append('.library_name = "' + library + '",') + if format_name != "": + lines.append('.format_name = "' + format_name + '",') + if protocol_name != "": + lines.append('.protocol_name = "' + protocol_name + '",') + if probe: + lines.append('.has_probe = true,') + if probe_device: + lines.append('.has_probe_device = true,') + + text = '\n\t'.join(lines) + fheader.write('\n\t{\n\t' + text + '\n\t},') + +def process_file(fheader, filename): + # This parser assumes the coding style rules are being followed + with open(filename, "r") as cfile: + found_something = False + found_start = False + library, _ = os.path.splitext(os.path.basename(filename)) + for line in cfile: + if found_start: + line = line.replace('\n', '') + if line.find(".format_name") != -1: + format_name = get_string_struct(line) + elif line.find(".protocol_name") != -1: + protocol_name = get_string_struct(line) + elif line.find(".bdrv_probe") != -1: + probe = True + elif line.find(".bdrv_probe_device") != -1: + probe_device = True + elif line == "};": + add_module(fheader, library, format_name, protocol_name, + probe, probe_device) + found_start = False + elif line.find("static BlockDriver") != -1: + found_something = True + found_start = True + format_name = "" + protocol_name = "" + probe = False + probe_device = False + + if not found_something: + print("No BlockDriver struct found in " + filename + ". \ + Is this really a module?") + sys.exit(1) + +def print_top(fheader): + fheader.write('''/* 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. + * + */ + +''') + + fheader.write('''#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_module[] = {''') + +def print_bottom(fheader): + fheader.write(''' +}; + +#endif''') + +# First argument: output folder +# All other arguments: modules source files (.c) +output_dir = sys.argv[1] +if not os.path.isdir(output_dir): + print("Folder " + output_dir + " does not exist") + sys.exit(1) + +path = output_dir + 'module_block.h' + +with open(path, 'w') as fheader: + print_top(fheader) + + for filename in sys.argv[2:]: + if os.path.isfile(filename): + process_file(fheader, filename) + else: + print("File " + filename + " does not exist.") + sys.exit(1) + + print_bottom(fheader) + +sys.exit(0) -- 2.4.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] Add dynamic generation of module_block.h 2015-08-17 8:09 ` [Qemu-devel] [PATCH 2/2] Add dynamic generation of module_block.h Marc Marí @ 2015-08-27 9:23 ` Daniel P. Berrange 2015-08-27 9:37 ` Marc Marí 0 siblings, 1 reply; 14+ messages in thread From: Daniel P. Berrange @ 2015-08-27 9:23 UTC (permalink / raw) To: Marc Marí; +Cc: qemu-devel On Mon, Aug 17, 2015 at 10:09:35AM +0200, Marc Marí wrote: > To simplify the addition of new block modules, add a script that generates > include/qemu/module_block.h automatically from the modules' source code. > > This script assumes that the QEMU coding style rules are followed. > > Signed-off-by: Marc Marí <markmb@redhat.com> > --- > .gitignore | 1 + > Makefile | 10 ++- > scripts/modules/module_block.py | 132 ++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 140 insertions(+), 3 deletions(-) > create mode 100755 scripts/modules/module_block.py I'd expect to see module_block.h deleted in this commit, otherwise you're re-generating a file stored in git each time someone runs make. > diff --git a/scripts/modules/module_block.py b/scripts/modules/module_block.py > new file mode 100755 > index 0000000..a9a9412 > --- /dev/null > +++ b/scripts/modules/module_block.py > @@ -0,0 +1,132 @@ > +#!/usr/bin/python > +# > +# Module information generator > +# > +# 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. > + > +import sys > +import os > + > +def get_string_struct(line): > + data = line.split() > + > + # data[0] -> struct element name > + # data[1] -> = > + # data[2] -> value > + > + return data[2].replace('"', '')[:-1] > + > +def add_module(fhader, library, format_name, protocol_name, > + probe, probe_device): > + lines = [] > + lines.append('.library_name = "' + library + '",') > + if format_name != "": > + lines.append('.format_name = "' + format_name + '",') > + if protocol_name != "": > + lines.append('.protocol_name = "' + protocol_name + '",') > + if probe: > + lines.append('.has_probe = true,') > + if probe_device: > + lines.append('.has_probe_device = true,') > + > + text = '\n\t'.join(lines) > + fheader.write('\n\t{\n\t' + text + '\n\t},') > + > +def process_file(fheader, filename): > + # This parser assumes the coding style rules are being followed > + with open(filename, "r") as cfile: > + found_something = False > + found_start = False > + library, _ = os.path.splitext(os.path.basename(filename)) > + for line in cfile: > + if found_start: > + line = line.replace('\n', '') > + if line.find(".format_name") != -1: > + format_name = get_string_struct(line) > + elif line.find(".protocol_name") != -1: > + protocol_name = get_string_struct(line) > + elif line.find(".bdrv_probe") != -1: > + probe = True > + elif line.find(".bdrv_probe_device") != -1: > + probe_device = True > + elif line == "};": > + add_module(fheader, library, format_name, protocol_name, > + probe, probe_device) > + found_start = False > + elif line.find("static BlockDriver") != -1: > + found_something = True > + found_start = True > + format_name = "" > + protocol_name = "" > + probe = False > + probe_device = False > + > + if not found_something: > + print("No BlockDriver struct found in " + filename + ". \ > + Is this really a module?") > + sys.exit(1) Errors ought to go to sys.stderr rather than stdout. > + > +def print_top(fheader): > + fheader.write('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ > +/* > + * QEMU Block Module Infrastructure > + * > + * Copyright Red Hat, Inc. 2015 > + * > + * Authors: > + * Marc Mari <markmb@redhat.com> When the file is auto-generated, I'm not sure it is right to claim copyright / authorship on it - if anything the copyright comes from the files that you're using as the source for auto-generation. > + * > + * This work is licensed under the terms of the GNU GPL, version 2. See > + * the COPYING file in the top-level directory. > + * > + */ > +# First argument: output folder > +# All other arguments: modules source files (.c) > +output_dir = sys.argv[1] > +if not os.path.isdir(output_dir): > + print("Folder " + output_dir + " does not exist") Again about stderr > + sys.exit(1) > + > +path = output_dir + 'module_block.h' > + > +with open(path, 'w') as fheader: > + print_top(fheader) > + > + for filename in sys.argv[2:]: > + if os.path.isfile(filename): > + process_file(fheader, filename) > + else: > + print("File " + filename + " does not exist.") Again here. > + sys.exit(1) > + > + print_bottom(fheader) > + > +sys.exit(0) Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 2/2] Add dynamic generation of module_block.h 2015-08-27 9:23 ` Daniel P. Berrange @ 2015-08-27 9:37 ` Marc Marí 0 siblings, 0 replies; 14+ messages in thread From: Marc Marí @ 2015-08-27 9:37 UTC (permalink / raw) To: Daniel P. Berrange; +Cc: qemu-devel On Thu, 27 Aug 2015 10:23:32 +0100 "Daniel P. Berrange" <berrange@redhat.com> wrote: > On Mon, Aug 17, 2015 at 10:09:35AM +0200, Marc Marí wrote: > > To simplify the addition of new block modules, add a script that > > generates include/qemu/module_block.h automatically from the > > modules' source code. > > > > This script assumes that the QEMU coding style rules are followed. > > > > Signed-off-by: Marc Marí <markmb@redhat.com> > > --- > > .gitignore | 1 + > > Makefile | 10 ++- > > scripts/modules/module_block.py | 132 > > ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 140 > > insertions(+), 3 deletions(-) create mode 100755 > > scripts/modules/module_block.py > > I'd expect to see module_block.h deleted in this commit, otherwise > you're re-generating a file stored in git each time someone runs > make. > > > diff --git a/scripts/modules/module_block.py > > b/scripts/modules/module_block.py new file mode 100755 > > index 0000000..a9a9412 > > --- /dev/null > > +++ b/scripts/modules/module_block.py > > @@ -0,0 +1,132 @@ > > +#!/usr/bin/python > > +# > > +# Module information generator > > +# > > +# 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. > > + > > +import sys > > +import os > > + > > +def get_string_struct(line): > > + data = line.split() > > + > > + # data[0] -> struct element name > > + # data[1] -> = > > + # data[2] -> value > > + > > + return data[2].replace('"', '')[:-1] > > + > > +def add_module(fhader, library, format_name, protocol_name, > > + probe, probe_device): > > + lines = [] > > + lines.append('.library_name = "' + library + '",') > > + if format_name != "": > > + lines.append('.format_name = "' + format_name + '",') > > + if protocol_name != "": > > + lines.append('.protocol_name = "' + protocol_name + '",') > > + if probe: > > + lines.append('.has_probe = true,') > > + if probe_device: > > + lines.append('.has_probe_device = true,') > > + > > + text = '\n\t'.join(lines) > > + fheader.write('\n\t{\n\t' + text + '\n\t},') > > + > > +def process_file(fheader, filename): > > + # This parser assumes the coding style rules are being followed > > + with open(filename, "r") as cfile: > > + found_something = False > > + found_start = False > > + library, _ = os.path.splitext(os.path.basename(filename)) > > + for line in cfile: > > + if found_start: > > + line = line.replace('\n', '') > > + if line.find(".format_name") != -1: > > + format_name = get_string_struct(line) > > + elif line.find(".protocol_name") != -1: > > + protocol_name = get_string_struct(line) > > + elif line.find(".bdrv_probe") != -1: > > + probe = True > > + elif line.find(".bdrv_probe_device") != -1: > > + probe_device = True > > + elif line == "};": > > + add_module(fheader, library, format_name, > > protocol_name, > > + probe, probe_device) > > + found_start = False > > + elif line.find("static BlockDriver") != -1: > > + found_something = True > > + found_start = True > > + format_name = "" > > + protocol_name = "" > > + probe = False > > + probe_device = False > > + > > + if not found_something: > > + print("No BlockDriver struct found in " + filename + > > ". \ > > + Is this really a module?") > > + sys.exit(1) > > > Errors ought to go to sys.stderr rather than stdout. > > > > > + > > +def print_top(fheader): > > + fheader.write('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ > > +/* > > + * QEMU Block Module Infrastructure > > + * > > + * Copyright Red Hat, Inc. 2015 > > + * > > + * Authors: > > + * Marc Mari <markmb@redhat.com> > > When the file is auto-generated, I'm not sure it is right to claim > copyright / authorship on it - if anything the copyright comes from > the files that you're using as the source for auto-generation. I just looked at other autogenerated files, and copied the template. Thanks Marc > > + * > > + * This work is licensed under the terms of the GNU GPL, version > > 2. See > > + * the COPYING file in the top-level directory. > > + * > > + */ > > > +# First argument: output folder > > +# All other arguments: modules source files (.c) > > +output_dir = sys.argv[1] > > +if not os.path.isdir(output_dir): > > + print("Folder " + output_dir + " does not exist") > > Again about stderr > > > + sys.exit(1) > > + > > +path = output_dir + 'module_block.h' > > + > > +with open(path, 'w') as fheader: > > + print_top(fheader) > > + > > + for filename in sys.argv[2:]: > > + if os.path.isfile(filename): > > + process_file(fheader, filename) > > + else: > > + print("File " + filename + " does not exist.") > > Again here. > > > + sys.exit(1) > > + > > + print_bottom(fheader) > > + > > +sys.exit(0) > > Regards, > Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers 2015-08-17 8:09 [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers Marc Marí 2015-08-17 8:09 ` [Qemu-devel] [PATCH 1/2] Add dynamic module loading " Marc Marí 2015-08-17 8:09 ` [Qemu-devel] [PATCH 2/2] Add dynamic generation of module_block.h Marc Marí @ 2015-08-27 8:51 ` Marc Marí 2015-09-03 16:12 ` Stefan Hajnoczi 3 siblings, 0 replies; 14+ messages in thread From: Marc Marí @ 2015-08-27 8:51 UTC (permalink / raw) To: qemu-devel, Fam Zheng, Paolo, Stefan Hajnoczi, Daniel P. Berrange Ping >On Mon, 17 Aug 2015 10:09:33 +0200 >Marc Marí <markmb@redhat.com> wrote: > > The current module infrastructure has been improved to enable dynamic > module loading. > > This reduces the load time for very simple guests. For the following > configuration (very loaded) > > ./configure --enable-sdl --enable-gtk --enable-vte --enable-curses \ > --enable-vnc --enable-vnc-{jpeg,tls,sasl,png} --enable-virtfs \ > --enable-brlapi --enable-curl --enable-fdt --enable-bluez \ > --enable-kvm --enable-rdma --enable-uuid --enable-vde \ > --enable-linux-aio --enable-cap-ng --enable-attr > --enable-vhost-net \ --enable-vhost-scsi --enable-spice --enable-rbd > --enable-libiscsi \ --enable-smartcard-nss --enable-guest-agent > --enable-libusb \ --enable-usb-redir --enable-lzo --enable-snappy > --enable-bzip2 \ --enable-seccomp --enable-coroutine-pool > --enable-glusterfs \ --enable-tpm --enable-libssh2 --enable-vhdx > --enable-numa \ --enable-tcmalloc --target-list=x86_64-softmmu > > With modules disabled, there are 142 libraries loaded at startup. > Time is the following: > LD time: 0.065 seconds > QEMU time: 0.02 seconds > Total time: 0.085 seconds > > With this patch series and modules enabled, there are 128 libraries > loaded at startup. Time is the following: > LD time: 0.02 seconds > QEMU time: 0.02 seconds > Total time: 0.04 seconds > > Where LD time is the time between the program startup and the jump to > main, and QEMU time is the time between the start of main and the > first kvm_entry. > > These results are just with a few block drivers, that were already a > module. Adding more modules (block or not block) should be easy, and > will reduce the load time even more. > > Marc Marí (2): > Add dynamic module loading for block drivers > Add dynamic generation of module_block.h > > .gitignore | 1 + > Makefile | 10 ++- > block.c | 73 +++++++++++++++++++++- > configure | 2 +- > include/qemu/module.h | 3 + > include/qemu/module_block.h | 89 +++++++++++++++++++++++++++ > scripts/modules/module_block.py | 132 > ++++++++++++++++++++++++++++++++++++++++ > util/module.c | 38 ++++-------- 8 files changed, > 314 insertions(+), 34 deletions(-) create mode 100644 > include/qemu/module_block.h create mode 100755 > scripts/modules/module_block.py > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers 2015-08-17 8:09 [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers Marc Marí ` (2 preceding siblings ...) 2015-08-27 8:51 ` [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers Marc Marí @ 2015-09-03 16:12 ` Stefan Hajnoczi 2015-09-03 18:07 ` Marc Marí 3 siblings, 1 reply; 14+ messages in thread From: Stefan Hajnoczi @ 2015-09-03 16:12 UTC (permalink / raw) To: Marc Marí; +Cc: qemu-devel On Mon, Aug 17, 2015 at 10:09:33AM +0200, Marc Marí wrote: > The current module infrastructure has been improved to enable dynamic module > loading. > > This reduces the load time for very simple guests. For the following > configuration (very loaded) > > ./configure --enable-sdl --enable-gtk --enable-vte --enable-curses \ > --enable-vnc --enable-vnc-{jpeg,tls,sasl,png} --enable-virtfs \ > --enable-brlapi --enable-curl --enable-fdt --enable-bluez \ > --enable-kvm --enable-rdma --enable-uuid --enable-vde \ > --enable-linux-aio --enable-cap-ng --enable-attr --enable-vhost-net \ > --enable-vhost-scsi --enable-spice --enable-rbd --enable-libiscsi \ > --enable-smartcard-nss --enable-guest-agent --enable-libusb \ > --enable-usb-redir --enable-lzo --enable-snappy --enable-bzip2 \ > --enable-seccomp --enable-coroutine-pool --enable-glusterfs \ > --enable-tpm --enable-libssh2 --enable-vhdx --enable-numa \ > --enable-tcmalloc --target-list=x86_64-softmmu > > With modules disabled, there are 142 libraries loaded at startup. Time is > the following: > LD time: 0.065 seconds > QEMU time: 0.02 seconds > Total time: 0.085 seconds > > With this patch series and modules enabled, there are 128 libraries loaded > at startup. Time is the following: > LD time: 0.02 seconds > QEMU time: 0.02 seconds > Total time: 0.04 seconds > > Where LD time is the time between the program startup and the jump to main, > and QEMU time is the time between the start of main and the first kvm_entry. > > These results are just with a few block drivers, that were already a module. > Adding more modules (block or not block) should be easy, and will reduce > the load time even more. Which QEMU command-line did you benchmark? Did you have a UI enabled (SDL/GTK/VNC)? ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers 2015-09-03 16:12 ` Stefan Hajnoczi @ 2015-09-03 18:07 ` Marc Marí 2015-09-07 13:09 ` Stefan Hajnoczi 0 siblings, 1 reply; 14+ messages in thread From: Marc Marí @ 2015-09-03 18:07 UTC (permalink / raw) To: Stefan Hajnoczi; +Cc: qemu-devel On Thu, 3 Sep 2015 17:12:29 +0100 Stefan Hajnoczi <stefanha@gmail.com> wrote: > On Mon, Aug 17, 2015 at 10:09:33AM +0200, Marc Marí wrote: > > The current module infrastructure has been improved to enable > > dynamic module loading. > > > > This reduces the load time for very simple guests. For the following > > configuration (very loaded) > > > > ./configure --enable-sdl --enable-gtk --enable-vte --enable-curses \ > > --enable-vnc --enable-vnc-{jpeg,tls,sasl,png} --enable-virtfs \ > > --enable-brlapi --enable-curl --enable-fdt --enable-bluez \ > > --enable-kvm --enable-rdma --enable-uuid --enable-vde \ > > --enable-linux-aio --enable-cap-ng --enable-attr > > --enable-vhost-net \ --enable-vhost-scsi --enable-spice > > --enable-rbd --enable-libiscsi \ --enable-smartcard-nss > > --enable-guest-agent --enable-libusb \ --enable-usb-redir > > --enable-lzo --enable-snappy --enable-bzip2 \ --enable-seccomp > > --enable-coroutine-pool --enable-glusterfs \ --enable-tpm > > --enable-libssh2 --enable-vhdx --enable-numa \ --enable-tcmalloc > > --target-list=x86_64-softmmu > > > > With modules disabled, there are 142 libraries loaded at startup. > > Time is the following: > > LD time: 0.065 seconds > > QEMU time: 0.02 seconds > > Total time: 0.085 seconds > > > > With this patch series and modules enabled, there are 128 libraries > > loaded at startup. Time is the following: > > LD time: 0.02 seconds > > QEMU time: 0.02 seconds > > Total time: 0.04 seconds > > > > Where LD time is the time between the program startup and the jump > > to main, and QEMU time is the time between the start of main and > > the first kvm_entry. > > > > These results are just with a few block drivers, that were already > > a module. Adding more modules (block or not block) should be easy, > > and will reduce the load time even more. > > Which QEMU command-line did you benchmark? > > Did you have a UI enabled (SDL/GTK/VNC)? x86_64-softmmu/qemu-system-x86_64 --enable-kvm \ -kernel /boot/vmlinuz-4.1.4-200.fc22.x86_64 -nographic Thanks Marc ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers 2015-09-03 18:07 ` Marc Marí @ 2015-09-07 13:09 ` Stefan Hajnoczi 0 siblings, 0 replies; 14+ messages in thread From: Stefan Hajnoczi @ 2015-09-07 13:09 UTC (permalink / raw) To: Marc Marí; +Cc: qemu-devel On Thu, Sep 03, 2015 at 08:07:40PM +0200, Marc Marí wrote: > On Thu, 3 Sep 2015 17:12:29 +0100 > Stefan Hajnoczi <stefanha@gmail.com> wrote: > > > On Mon, Aug 17, 2015 at 10:09:33AM +0200, Marc Marí wrote: > > > The current module infrastructure has been improved to enable > > > dynamic module loading. > > > > > > This reduces the load time for very simple guests. For the following > > > configuration (very loaded) > > > > > > ./configure --enable-sdl --enable-gtk --enable-vte --enable-curses \ > > > --enable-vnc --enable-vnc-{jpeg,tls,sasl,png} --enable-virtfs \ > > > --enable-brlapi --enable-curl --enable-fdt --enable-bluez \ > > > --enable-kvm --enable-rdma --enable-uuid --enable-vde \ > > > --enable-linux-aio --enable-cap-ng --enable-attr > > > --enable-vhost-net \ --enable-vhost-scsi --enable-spice > > > --enable-rbd --enable-libiscsi \ --enable-smartcard-nss > > > --enable-guest-agent --enable-libusb \ --enable-usb-redir > > > --enable-lzo --enable-snappy --enable-bzip2 \ --enable-seccomp > > > --enable-coroutine-pool --enable-glusterfs \ --enable-tpm > > > --enable-libssh2 --enable-vhdx --enable-numa \ --enable-tcmalloc > > > --target-list=x86_64-softmmu > > > > > > With modules disabled, there are 142 libraries loaded at startup. > > > Time is the following: > > > LD time: 0.065 seconds > > > QEMU time: 0.02 seconds > > > Total time: 0.085 seconds > > > > > > With this patch series and modules enabled, there are 128 libraries > > > loaded at startup. Time is the following: > > > LD time: 0.02 seconds > > > QEMU time: 0.02 seconds > > > Total time: 0.04 seconds > > > > > > Where LD time is the time between the program startup and the jump > > > to main, and QEMU time is the time between the start of main and > > > the first kvm_entry. > > > > > > These results are just with a few block drivers, that were already > > > a module. Adding more modules (block or not block) should be easy, > > > and will reduce the load time even more. > > > > Which QEMU command-line did you benchmark? > > > > Did you have a UI enabled (SDL/GTK/VNC)? > > x86_64-softmmu/qemu-system-x86_64 --enable-kvm \ > -kernel /boot/vmlinuz-4.1.4-200.fc22.x86_64 -nographic Nice, these times are very good. Stefan ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2015-09-07 13:09 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-08-17 8:09 [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers Marc Marí 2015-08-17 8:09 ` [Qemu-devel] [PATCH 1/2] Add dynamic module loading " Marc Marí 2015-08-27 9:19 ` Daniel P. Berrange 2015-08-27 9:35 ` Marc Marí 2015-08-27 9:40 ` Daniel P. Berrange 2015-09-03 16:33 ` Stefan Hajnoczi 2015-09-03 18:01 ` Marc Marí 2015-08-17 8:09 ` [Qemu-devel] [PATCH 2/2] Add dynamic generation of module_block.h Marc Marí 2015-08-27 9:23 ` Daniel P. Berrange 2015-08-27 9:37 ` Marc Marí 2015-08-27 8:51 ` [Qemu-devel] [PATCH 0/2] Dynamic module support for block drivers Marc Marí 2015-09-03 16:12 ` Stefan Hajnoczi 2015-09-03 18:07 ` Marc Marí 2015-09-07 13:09 ` Stefan Hajnoczi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).