From 17b74b98676aee5bc470b173b1e528d2fce2cf18 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 4 May 2016 18:49:17 +0200 Subject: [PATCH 1/5] migration: Move qjson.[ch] to migration/ Type QJSON lets you build JSON text. Its interface mirrors (a subset of) abstract JSON syntax. QAPI output visitors also produce JSON text. They assert their preconditions and invariants, and therefore abort on incorrect use. Contrastingly, QJSON does *not* detect incorrect use. It happily produces invalid JSON then. This is what migration wants. QJSON was designed for migration, and migration is its only user. Move it to migration/ for proper coverage by MAINTAINERS, and to deter accidental use outside migration. [Pointed out by Eric: QJSON was added in commits 0457d07..b174257 -- Amit] Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Dr. David Alan Gilbert Message-Id: <1462380558-2030-2-git-send-email-armbru@redhat.com> Signed-off-by: Amit Shah --- Makefile.objs | 1 - include/{ => migration}/qjson.h | 0 include/migration/vmstate.h | 2 +- migration/Makefile.objs | 1 + qjson.c => migration/qjson.c | 23 +++++++++++++++++------ migration/vmstate.c | 1 - tests/Makefile | 2 +- 7 files changed, 20 insertions(+), 10 deletions(-) rename include/{ => migration}/qjson.h (100%) rename qjson.c => migration/qjson.c (83%) diff --git a/Makefile.objs b/Makefile.objs index 8f705f6202..da49b7159f 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -52,7 +52,6 @@ common-obj-$(CONFIG_LINUX) += fsdev/ common-obj-y += migration/ common-obj-y += qemu-char.o #aio.o common-obj-y += page_cache.o -common-obj-y += qjson.o common-obj-$(CONFIG_SPICE) += spice-qemu-char.o diff --git a/include/qjson.h b/include/migration/qjson.h similarity index 100% rename from include/qjson.h rename to include/migration/qjson.h diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index 84ee355ceb..30ecc441de 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -29,7 +29,7 @@ #ifndef CONFIG_USER_ONLY #include #endif -#include +#include "migration/qjson.h" typedef void SaveStateHandler(QEMUFile *f, void *opaque); typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); diff --git a/migration/Makefile.objs b/migration/Makefile.objs index 0cac6d707a..d25ff483eb 100644 --- a/migration/Makefile.objs +++ b/migration/Makefile.objs @@ -2,6 +2,7 @@ common-obj-y += migration.o tcp.o common-obj-y += vmstate.o common-obj-y += qemu-file.o qemu-file-buf.o qemu-file-unix.o qemu-file-stdio.o common-obj-y += xbzrle.o postcopy-ram.o +common-obj-y += qjson.o common-obj-$(CONFIG_RDMA) += rdma.o common-obj-$(CONFIG_POSIX) += exec.o unix.o fd.o diff --git a/qjson.c b/migration/qjson.c similarity index 83% rename from qjson.c rename to migration/qjson.c index b65ca6ee5e..cb479fe0eb 100644 --- a/qjson.c +++ b/migration/qjson.c @@ -1,5 +1,5 @@ /* - * QEMU JSON writer + * A simple JSON writer * * Copyright Alexander Graf * @@ -11,12 +11,23 @@ * */ +/* + * Type QJSON lets you build JSON text. Its interface mirrors (a + * subset of) abstract JSON syntax. + * + * It does *not* detect incorrect use. It happily produces invalid + * JSON then. This is what migration wants. + * + * QAPI output visitors also produce JSON text. However, they do + * assert their preconditions and invariants, and therefore abort on + * incorrect use. + */ + #include "qemu/osdep.h" -#include -#include -#include -#include -#include +#include "qapi/qmp/qstring.h" +#include "migration/qjson.h" +#include "qemu/module.h" +#include "qom/object.h" struct QJSON { Object obj; diff --git a/migration/vmstate.c b/migration/vmstate.c index bf3d5db301..46dc55ea40 100644 --- a/migration/vmstate.c +++ b/migration/vmstate.c @@ -6,7 +6,6 @@ #include "qemu/bitops.h" #include "qemu/error-report.h" #include "trace.h" -#include "qjson.h" static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, void *opaque, QJSON *vmdesc); diff --git a/tests/Makefile b/tests/Makefile index 9dddde6589..1bbd1ca463 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -439,7 +439,7 @@ tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \ $(test-qapi-obj-y) tests/test-vmstate$(EXESUF): tests/test-vmstate.o \ migration/vmstate.o migration/qemu-file.o migration/qemu-file-buf.o \ - migration/qemu-file-unix.o qjson.o \ + migration/qemu-file-unix.o migration/qjson.o \ $(test-qom-obj-y) tests/test-timed-average$(EXESUF): tests/test-timed-average.o qemu-timer.o \ $(test-util-obj-y) From b72fe9e690db5082fdd0476074230cf2c65508bf Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 4 May 2016 18:49:18 +0200 Subject: [PATCH 2/5] migration/qjson: Drop gratuitous use of QOM All the use of QOM buys us here is the ability to destroy the thing with object_unref(OBJECT(vmdesc)). Not worth the notational overhead. Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Reviewed-by: Dr. David Alan Gilbert Message-Id: <1462380558-2030-3-git-send-email-armbru@redhat.com> Signed-off-by: Amit Shah --- include/migration/qjson.h | 2 +- migration/qjson.c | 39 ++++++--------------------------------- migration/savevm.c | 2 +- 3 files changed, 8 insertions(+), 35 deletions(-) diff --git a/include/migration/qjson.h b/include/migration/qjson.h index 7c54fdf0ac..2978b5f371 100644 --- a/include/migration/qjson.h +++ b/include/migration/qjson.h @@ -13,10 +13,10 @@ #ifndef QEMU_QJSON_H #define QEMU_QJSON_H -#define TYPE_QJSON "QJSON" typedef struct QJSON QJSON; QJSON *qjson_new(void); +void qjson_destroy(QJSON *json); void json_prop_str(QJSON *json, const char *name, const char *str); void json_prop_int(QJSON *json, const char *name, int64_t val); void json_end_array(QJSON *json); diff --git a/migration/qjson.c b/migration/qjson.c index cb479fe0eb..5cae55af07 100644 --- a/migration/qjson.c +++ b/migration/qjson.c @@ -26,17 +26,12 @@ #include "qemu/osdep.h" #include "qapi/qmp/qstring.h" #include "migration/qjson.h" -#include "qemu/module.h" -#include "qom/object.h" struct QJSON { - Object obj; QString *str; bool omit_comma; }; -#define QJSON(obj) OBJECT_CHECK(QJSON, (obj), TYPE_QJSON) - static void json_emit_element(QJSON *json, const char *name) { /* Check whether we need to print a , before an element */ @@ -100,7 +95,10 @@ const char *qjson_get_str(QJSON *json) QJSON *qjson_new(void) { - QJSON *json = QJSON(object_new(TYPE_QJSON)); + QJSON *json = g_new0(QJSON, 1); + + json->str = qstring_from_str("{ "); + json->omit_comma = true; return json; } @@ -109,32 +107,7 @@ void qjson_finish(QJSON *json) json_end_object(json); } -static void qjson_initfn(Object *obj) +void qjson_destroy(QJSON *json) { - QJSON *json = QJSON(obj); - - json->str = qstring_from_str("{ "); - json->omit_comma = true; + g_free(json); } - -static void qjson_finalizefn(Object *obj) -{ - QJSON *json = QJSON(obj); - - qobject_decref(QOBJECT(json->str)); -} - -static const TypeInfo qjson_type_info = { - .name = TYPE_QJSON, - .parent = TYPE_OBJECT, - .instance_size = sizeof(QJSON), - .instance_init = qjson_initfn, - .instance_finalize = qjson_finalizefn, -}; - -static void qjson_register_types(void) -{ - type_register_static(&qjson_type_info); -} - -type_init(qjson_register_types) diff --git a/migration/savevm.c b/migration/savevm.c index bfb3d9178f..8546fdfae1 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1115,7 +1115,7 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only) qemu_put_be32(f, vmdesc_len); qemu_put_buffer(f, (uint8_t *)qjson_get_str(vmdesc), vmdesc_len); } - object_unref(OBJECT(vmdesc)); + qjson_destroy(vmdesc); qemu_fflush(f); } From d85a31d1f4d45462b7ca333190b5d14fad982f3e Mon Sep 17 00:00:00 2001 From: "Jason J. Herne" Date: Thu, 21 Apr 2016 14:07:18 -0400 Subject: [PATCH 3/5] migration: Promote improved autoconverge commands out of experimental state The new autoconverge throttling commands have been tested for a release now. It is time to move them out of the experimental state. Signed-off-by: Jason J. Herne Message-Id: <1461262038-8197-1-git-send-email-jjherne@linux.vnet.ibm.com> Signed-off-by: Amit Shah --- hmp.c | 28 +++++++++++----------- migration/migration.c | 56 +++++++++++++++++++++---------------------- migration/ram.c | 4 ++-- qapi-schema.json | 54 ++++++++++++++++++++--------------------- qmp-commands.hx | 22 ++++++++--------- 5 files changed, 82 insertions(+), 82 deletions(-) diff --git a/hmp.c b/hmp.c index d510236677..9f9bcf9d83 100644 --- a/hmp.c +++ b/hmp.c @@ -235,9 +235,9 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) info->xbzrle_cache->overflow); } - if (info->has_x_cpu_throttle_percentage) { + if (info->has_cpu_throttle_percentage) { monitor_printf(mon, "cpu throttle percentage: %" PRIu64 "\n", - info->x_cpu_throttle_percentage); + info->cpu_throttle_percentage); } qapi_free_MigrationInfo(info); @@ -281,11 +281,11 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict) MigrationParameter_lookup[MIGRATION_PARAMETER_DECOMPRESS_THREADS], params->decompress_threads); monitor_printf(mon, " %s: %" PRId64, - MigrationParameter_lookup[MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL], - params->x_cpu_throttle_initial); + MigrationParameter_lookup[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL], + params->cpu_throttle_initial); monitor_printf(mon, " %s: %" PRId64, - MigrationParameter_lookup[MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT], - params->x_cpu_throttle_increment); + MigrationParameter_lookup[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT], + params->cpu_throttle_increment); monitor_printf(mon, "\n"); } @@ -1240,8 +1240,8 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) bool has_compress_level = false; bool has_compress_threads = false; bool has_decompress_threads = false; - bool has_x_cpu_throttle_initial = false; - bool has_x_cpu_throttle_increment = false; + bool has_cpu_throttle_initial = false; + bool has_cpu_throttle_increment = false; int i; for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) { @@ -1256,18 +1256,18 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict) case MIGRATION_PARAMETER_DECOMPRESS_THREADS: has_decompress_threads = true; break; - case MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL: - has_x_cpu_throttle_initial = true; + case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL: + has_cpu_throttle_initial = true; break; - case MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT: - has_x_cpu_throttle_increment = true; + case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT: + has_cpu_throttle_increment = true; break; } qmp_migrate_set_parameters(has_compress_level, value, has_compress_threads, value, has_decompress_threads, value, - has_x_cpu_throttle_initial, value, - has_x_cpu_throttle_increment, value, + has_cpu_throttle_initial, value, + has_cpu_throttle_increment, value, &err); break; } diff --git a/migration/migration.c b/migration/migration.c index c08d9a69b0..12dbf5b343 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -50,8 +50,8 @@ /*0: means nocompress, 1: best speed, ... 9: best compress ratio */ #define DEFAULT_MIGRATE_COMPRESS_LEVEL 1 /* Define default autoconverge cpu throttle migration parameters */ -#define DEFAULT_MIGRATE_X_CPU_THROTTLE_INITIAL 20 -#define DEFAULT_MIGRATE_X_CPU_THROTTLE_INCREMENT 10 +#define DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL 20 +#define DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT 10 /* Migration XBZRLE default cache size */ #define DEFAULT_MIGRATE_CACHE_SIZE (64 * 1024 * 1024) @@ -87,10 +87,10 @@ MigrationState *migrate_get_current(void) DEFAULT_MIGRATE_COMPRESS_THREAD_COUNT, .parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS] = DEFAULT_MIGRATE_DECOMPRESS_THREAD_COUNT, - .parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL] = - DEFAULT_MIGRATE_X_CPU_THROTTLE_INITIAL, - .parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT] = - DEFAULT_MIGRATE_X_CPU_THROTTLE_INCREMENT, + .parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL] = + DEFAULT_MIGRATE_CPU_THROTTLE_INITIAL, + .parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT] = + DEFAULT_MIGRATE_CPU_THROTTLE_INCREMENT, }; if (!once) { @@ -521,10 +521,10 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp) s->parameters[MIGRATION_PARAMETER_COMPRESS_THREADS]; params->decompress_threads = s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS]; - params->x_cpu_throttle_initial = - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL]; - params->x_cpu_throttle_increment = - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT]; + params->cpu_throttle_initial = + s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL]; + params->cpu_throttle_increment = + s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT]; return params; } @@ -607,8 +607,8 @@ MigrationInfo *qmp_query_migrate(Error **errp) } if (cpu_throttle_active()) { - info->has_x_cpu_throttle_percentage = true; - info->x_cpu_throttle_percentage = cpu_throttle_get_percentage(); + info->has_cpu_throttle_percentage = true; + info->cpu_throttle_percentage = cpu_throttle_get_percentage(); } get_xbzrle_cache_stats(info); @@ -718,10 +718,10 @@ void qmp_migrate_set_parameters(bool has_compress_level, int64_t compress_threads, bool has_decompress_threads, int64_t decompress_threads, - bool has_x_cpu_throttle_initial, - int64_t x_cpu_throttle_initial, - bool has_x_cpu_throttle_increment, - int64_t x_cpu_throttle_increment, Error **errp) + bool has_cpu_throttle_initial, + int64_t cpu_throttle_initial, + bool has_cpu_throttle_increment, + int64_t cpu_throttle_increment, Error **errp) { MigrationState *s = migrate_get_current(); @@ -744,16 +744,16 @@ void qmp_migrate_set_parameters(bool has_compress_level, "is invalid, it should be in the range of 1 to 255"); return; } - if (has_x_cpu_throttle_initial && - (x_cpu_throttle_initial < 1 || x_cpu_throttle_initial > 99)) { + if (has_cpu_throttle_initial && + (cpu_throttle_initial < 1 || cpu_throttle_initial > 99)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - "x_cpu_throttle_initial", + "cpu_throttle_initial", "an integer in the range of 1 to 99"); } - if (has_x_cpu_throttle_increment && - (x_cpu_throttle_increment < 1 || x_cpu_throttle_increment > 99)) { + if (has_cpu_throttle_increment && + (cpu_throttle_increment < 1 || cpu_throttle_increment > 99)) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, - "x_cpu_throttle_increment", + "cpu_throttle_increment", "an integer in the range of 1 to 99"); } @@ -767,14 +767,14 @@ void qmp_migrate_set_parameters(bool has_compress_level, s->parameters[MIGRATION_PARAMETER_DECOMPRESS_THREADS] = decompress_threads; } - if (has_x_cpu_throttle_initial) { - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL] = - x_cpu_throttle_initial; + if (has_cpu_throttle_initial) { + s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL] = + cpu_throttle_initial; } - if (has_x_cpu_throttle_increment) { - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT] = - x_cpu_throttle_increment; + if (has_cpu_throttle_increment) { + s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT] = + cpu_throttle_increment; } } diff --git a/migration/ram.c b/migration/ram.c index 5e88080faf..d1ecb99961 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -430,9 +430,9 @@ static void mig_throttle_guest_down(void) { MigrationState *s = migrate_get_current(); uint64_t pct_initial = - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INITIAL]; + s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL]; uint64_t pct_icrement = - s->parameters[MIGRATION_PARAMETER_X_CPU_THROTTLE_INCREMENT]; + s->parameters[MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT]; /* We have not started throttling yet. Let's start it. */ if (!cpu_throttle_active()) { diff --git a/qapi-schema.json b/qapi-schema.json index 54634c473b..9a322d1836 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -480,9 +480,9 @@ # may be expensive, but do not actually occur during the iterative # migration rounds themselves. (since 1.6) # -# @x-cpu-throttle-percentage: #optional percentage of time guest cpus are being -# throttled during auto-converge. This is only present when auto-converge -# has started throttling guest cpus. (Since 2.5) +# @cpu-throttle-percentage: #optional percentage of time guest cpus are being +# throttled during auto-converge. This is only present when auto-converge +# has started throttling guest cpus. (Since 2.7) # # Since: 0.14.0 ## @@ -494,7 +494,7 @@ '*expected-downtime': 'int', '*downtime': 'int', '*setup-time': 'int', - '*x-cpu-throttle-percentage': 'int'} } + '*cpu-throttle-percentage': 'int'} } ## # @query-migrate @@ -605,18 +605,18 @@ # compression, so set the decompress-threads to the number about 1/4 # of compress-threads is adequate. # -# @x-cpu-throttle-initial: Initial percentage of time guest cpus are throttled -# when migration auto-converge is activated. The -# default value is 20. (Since 2.5) +# @cpu-throttle-initial: Initial percentage of time guest cpus are throttled +# when migration auto-converge is activated. The +# default value is 20. (Since 2.7) # -# @x-cpu-throttle-increment: throttle percentage increase each time -# auto-converge detects that migration is not making -# progress. The default value is 10. (Since 2.5) +# @cpu-throttle-increment: throttle percentage increase each time +# auto-converge detects that migration is not making +# progress. The default value is 10. (Since 2.7) # Since: 2.4 ## { 'enum': 'MigrationParameter', 'data': ['compress-level', 'compress-threads', 'decompress-threads', - 'x-cpu-throttle-initial', 'x-cpu-throttle-increment'] } + 'cpu-throttle-initial', 'cpu-throttle-increment'] } # # @migrate-set-parameters @@ -629,21 +629,21 @@ # # @decompress-threads: decompression thread count # -# @x-cpu-throttle-initial: Initial percentage of time guest cpus are throttled -# when migration auto-converge is activated. The -# default value is 20. (Since 2.5) +# @cpu-throttle-initial: Initial percentage of time guest cpus are throttled +# when migration auto-converge is activated. The +# default value is 20. (Since 2.7) # -# @x-cpu-throttle-increment: throttle percentage increase each time -# auto-converge detects that migration is not making -# progress. The default value is 10. (Since 2.5) +# @cpu-throttle-increment: throttle percentage increase each time +# auto-converge detects that migration is not making +# progress. The default value is 10. (Since 2.7) # Since: 2.4 ## { 'command': 'migrate-set-parameters', 'data': { '*compress-level': 'int', '*compress-threads': 'int', '*decompress-threads': 'int', - '*x-cpu-throttle-initial': 'int', - '*x-cpu-throttle-increment': 'int'} } + '*cpu-throttle-initial': 'int', + '*cpu-throttle-increment': 'int'} } # # @MigrationParameters @@ -654,13 +654,13 @@ # # @decompress-threads: decompression thread count # -# @x-cpu-throttle-initial: Initial percentage of time guest cpus are throttled -# when migration auto-converge is activated. The -# default value is 20. (Since 2.5) +# @cpu-throttle-initial: Initial percentage of time guest cpus are throttled +# when migration auto-converge is activated. The +# default value is 20. (Since 2.7) # -# @x-cpu-throttle-increment: throttle percentage increase each time -# auto-converge detects that migration is not making -# progress. The default value is 10. (Since 2.5) +# @cpu-throttle-increment: throttle percentage increase each time +# auto-converge detects that migration is not making +# progress. The default value is 10. (Since 2.7) # # Since: 2.4 ## @@ -668,8 +668,8 @@ 'data': { 'compress-level': 'int', 'compress-threads': 'int', 'decompress-threads': 'int', - 'x-cpu-throttle-initial': 'int', - 'x-cpu-throttle-increment': 'int'} } + 'cpu-throttle-initial': 'int', + 'cpu-throttle-increment': 'int'} } ## # @query-migrate-parameters # diff --git a/qmp-commands.hx b/qmp-commands.hx index 94847e5b48..28801a28fb 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3747,10 +3747,10 @@ Set migration parameters - "compress-level": set compression level during migration (json-int) - "compress-threads": set compression thread count for migration (json-int) - "decompress-threads": set decompression thread count for migration (json-int) -- "x-cpu-throttle-initial": set initial percentage of time guest cpus are - throttled for auto-converge (json-int) -- "x-cpu-throttle-increment": set throttle increasing percentage for - auto-converge (json-int) +- "cpu-throttle-initial": set initial percentage of time guest cpus are + throttled for auto-converge (json-int) +- "cpu-throttle-increment": set throttle increasing percentage for + auto-converge (json-int) Arguments: @@ -3764,7 +3764,7 @@ EQMP { .name = "migrate-set-parameters", .args_type = - "compress-level:i?,compress-threads:i?,decompress-threads:i?,x-cpu-throttle-initial:i?,x-cpu-throttle-increment:i?", + "compress-level:i?,compress-threads:i?,decompress-threads:i?,cpu-throttle-initial:i?,cpu-throttle-increment:i?", .mhandler.cmd_new = qmp_marshal_migrate_set_parameters, }, SQMP @@ -3777,10 +3777,10 @@ Query current migration parameters - "compress-level" : compression level value (json-int) - "compress-threads" : compression thread count value (json-int) - "decompress-threads" : decompression thread count value (json-int) - - "x-cpu-throttle-initial" : initial percentage of time guest cpus are - throttled (json-int) - - "x-cpu-throttle-increment" : throttle increasing percentage for - auto-converge (json-int) + - "cpu-throttle-initial" : initial percentage of time guest cpus are + throttled (json-int) + - "cpu-throttle-increment" : throttle increasing percentage for + auto-converge (json-int) Arguments: @@ -3790,10 +3790,10 @@ Example: <- { "return": { "decompress-threads": 2, - "x-cpu-throttle-increment": 10, + "cpu-throttle-increment": 10, "compress-threads": 8, "compress-level": 1, - "x-cpu-throttle-initial": 20 + "cpu-throttle-initial": 20 } } From 24f3902b088cd4f2dbebfd90527b5d81d6a050e9 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Wed, 4 May 2016 21:44:19 +0200 Subject: [PATCH 4/5] savevm: fail if migration blockers are present QEMU has currently two ways to prevent migration to occur: - migration blocker when it depends on runtime state - VMStateDescription.unmigratable when migration is not supported at all This patch gathers all the logic into a single function to be called from both the savevm and the migrate paths. This fixes a bug with 9p, at least, where savevm would succeed and the following would happen in the guest after loadvm: $ ls /host ls: cannot access /host: Protocol error With this patch: (qemu) savevm foo Migration is disabled when VirtFS export path '/' is mounted in the guest using mount_tag 'host' Signed-off-by: Greg Kurz Reviewed-by: Paolo Bonzini Message-Id: <146239057139.11271.9011797645454781543.stgit@bahia.huguette.org> [Update subject according to Paolo's suggestion - Amit] Signed-off-by: Amit Shah --- include/migration/migration.h | 1 + migration/migration.c | 21 +++++++++++++++------ migration/savevm.c | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/include/migration/migration.h b/include/migration/migration.h index ac2c12c2a5..9e36a97fc5 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -210,6 +210,7 @@ int migrate_fd_close(MigrationState *s); void add_migration_state_change_notifier(Notifier *notify); void remove_migration_state_change_notifier(Notifier *notify); MigrationState *migrate_init(const MigrationParams *params); +bool migration_is_blocked(Error **errp); bool migration_in_setup(MigrationState *); bool migration_has_finished(MigrationState *); bool migration_has_failed(MigrationState *); diff --git a/migration/migration.c b/migration/migration.c index 12dbf5b343..721d010fde 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -992,6 +992,20 @@ void qmp_migrate_incoming(const char *uri, Error **errp) once = false; } +bool migration_is_blocked(Error **errp) +{ + if (qemu_savevm_state_blocked(errp)) { + return true; + } + + if (migration_blockers) { + *errp = error_copy(migration_blockers->data); + return true; + } + + return false; +} + void qmp_migrate(const char *uri, bool has_blk, bool blk, bool has_inc, bool inc, bool has_detach, bool detach, Error **errp) @@ -1014,12 +1028,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, return; } - if (qemu_savevm_state_blocked(errp)) { - return; - } - - if (migration_blockers) { - *errp = error_copy(migration_blockers->data); + if (migration_is_blocked(errp)) { return; } diff --git a/migration/savevm.c b/migration/savevm.c index 8546fdfae1..f8450fd0e9 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1170,7 +1170,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) MigrationState *ms = migrate_init(¶ms); ms->to_dst_file = f; - if (qemu_savevm_state_blocked(errp)) { + if (migration_is_blocked(errp)) { return -EINVAL; } From fe904ea8242cbae2d7e69c052c754b8f5f1ba1d6 Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Wed, 18 May 2016 15:44:36 +0200 Subject: [PATCH 5/5] migration: regain control of images when migration fails to complete We currently have an error path during migration that can cause the source QEMU to abort: migration_thread() migration_completion() runstate_is_running() ----------------> true if guest is running bdrv_inactivate_all() ----------------> inactivate images qemu_savevm_state_complete_precopy() ... qemu_fflush() socket_writev_buffer() --------> error because destination fails qemu_fflush() -------------------> set error on migration stream migration_completion() -----------------> set migrate state to FAILED migration_thread() -----------------------> break migration loop vm_start() -----------------------------> restart guest with inactive images and you get: qemu-system-ppc64: socket_writev_buffer: Got err=104 for (32768/18446744073709551615) qemu-system-ppc64: /home/greg/Work/qemu/qemu-master/block/io.c:1342:bdrv_co_do_pwritev: Assertion `!(bs->open_flags & 0x0800)' failed. Aborted (core dumped) If we try postcopy with a similar scenario, we also get the writev error message but QEMU leaves the guest paused because entered_postcopy is true. We could possibly do the same with precopy and leave the guest paused. But since the historical default for migration errors is to restart the source, this patch adds a call to bdrv_invalidate_cache_all() instead. Signed-off-by: Greg Kurz Message-Id: <146357896785.6003.11983081732454362715.stgit@bahia.huguette.org> Signed-off-by: Amit Shah --- migration/migration.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index 721d010fde..f5327e8c0a 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -1606,19 +1606,32 @@ static void migration_completion(MigrationState *s, int current_active_state, rp_error = await_return_path_close_on_source(s); trace_migration_completion_postcopy_end_after_rp(rp_error); if (rp_error) { - goto fail; + goto fail_invalidate; } } if (qemu_file_get_error(s->to_dst_file)) { trace_migration_completion_file_err(); - goto fail; + goto fail_invalidate; } migrate_set_state(&s->state, current_active_state, MIGRATION_STATUS_COMPLETED); return; +fail_invalidate: + /* If not doing postcopy, vm_start() will be called: let's regain + * control on images. + */ + if (s->state == MIGRATION_STATUS_ACTIVE) { + Error *local_err = NULL; + + bdrv_invalidate_cache_all(&local_err); + if (local_err) { + error_report_err(local_err); + } + } + fail: migrate_set_state(&s->state, current_active_state, MIGRATION_STATUS_FAILED);