diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-05-24 12:21:07 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-05-24 12:21:07 +0100 |
commit | 99694362ee563c5bbfad92bcc6bd578c0d4f7ce7 (patch) | |
tree | bf6e256235405492bab498e558fe34118abba429 /migration | |
parent | b0f6ef8915247f3230ffd9b71af9c3dadb6082c7 (diff) | |
parent | fe904ea8242cbae2d7e69c052c754b8f5f1ba1d6 (diff) |
Merge remote-tracking branch 'remotes/amit-migration/tags/migration-2.7-1' into staging
migration fixes:
- ensure src block devices continue fine after a failed migration
- fail on migration blockers; helps 9p savevm/loadvm
- move autoconverge commands out of experimental state
- move the migration-specific qjson in migration/
# gpg: Signature made Mon 23 May 2016 18:15:09 BST using RSA key ID 657EF670
# gpg: Good signature from "Amit Shah <amit@amitshah.net>"
# gpg: aka "Amit Shah <amit@kernel.org>"
# gpg: aka "Amit Shah <amitshah@gmx.net>"
* remotes/amit-migration/tags/migration-2.7-1:
migration: regain control of images when migration fails to complete
savevm: fail if migration blockers are present
migration: Promote improved autoconverge commands out of experimental state
migration/qjson: Drop gratuitous use of QOM
migration: Move qjson.[ch] to migration/
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'migration')
-rw-r--r-- | migration/Makefile.objs | 1 | ||||
-rw-r--r-- | migration/migration.c | 94 | ||||
-rw-r--r-- | migration/qjson.c | 113 | ||||
-rw-r--r-- | migration/ram.c | 4 | ||||
-rw-r--r-- | migration/savevm.c | 4 | ||||
-rw-r--r-- | migration/vmstate.c | 1 |
6 files changed, 176 insertions, 41 deletions
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/migration/migration.c b/migration/migration.c index c08d9a69b0..f5327e8c0a 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; } } @@ -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; } @@ -1597,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); diff --git a/migration/qjson.c b/migration/qjson.c new file mode 100644 index 0000000000..5cae55af07 --- /dev/null +++ b/migration/qjson.c @@ -0,0 +1,113 @@ +/* + * A simple JSON writer + * + * Copyright Alexander Graf + * + * Authors: + * Alexander Graf <agraf@suse.de> + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +/* + * 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 "qapi/qmp/qstring.h" +#include "migration/qjson.h" + +struct QJSON { + QString *str; + bool omit_comma; +}; + +static void json_emit_element(QJSON *json, const char *name) +{ + /* Check whether we need to print a , before an element */ + if (json->omit_comma) { + json->omit_comma = false; + } else { + qstring_append(json->str, ", "); + } + + if (name) { + qstring_append(json->str, "\""); + qstring_append(json->str, name); + qstring_append(json->str, "\" : "); + } +} + +void json_start_object(QJSON *json, const char *name) +{ + json_emit_element(json, name); + qstring_append(json->str, "{ "); + json->omit_comma = true; +} + +void json_end_object(QJSON *json) +{ + qstring_append(json->str, " }"); + json->omit_comma = false; +} + +void json_start_array(QJSON *json, const char *name) +{ + json_emit_element(json, name); + qstring_append(json->str, "[ "); + json->omit_comma = true; +} + +void json_end_array(QJSON *json) +{ + qstring_append(json->str, " ]"); + json->omit_comma = false; +} + +void json_prop_int(QJSON *json, const char *name, int64_t val) +{ + json_emit_element(json, name); + qstring_append_int(json->str, val); +} + +void json_prop_str(QJSON *json, const char *name, const char *str) +{ + json_emit_element(json, name); + qstring_append_chr(json->str, '"'); + qstring_append(json->str, str); + qstring_append_chr(json->str, '"'); +} + +const char *qjson_get_str(QJSON *json) +{ + return qstring_get_str(json->str); +} + +QJSON *qjson_new(void) +{ + QJSON *json = g_new0(QJSON, 1); + + json->str = qstring_from_str("{ "); + json->omit_comma = true; + return json; +} + +void qjson_finish(QJSON *json) +{ + json_end_object(json); +} + +void qjson_destroy(QJSON *json) +{ + g_free(json); +} diff --git a/migration/ram.c b/migration/ram.c index 6b6900e4c1..54e215128c 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/migration/savevm.c b/migration/savevm.c index 9bc362a1d3..65ce0c61a3 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); } @@ -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; } 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); |