[libvirt] [PATCH 00/11] Add auto convergence migration parameters

This series adds support for a couple of migration parameters which can be used to tune the auto-convergence algorithm in QEMU. Jiri Denemark (11): qemu: Make qemuMonitorSetMigrationCompression saner qemu: Decouple migration parameters from compression settings qemu: Rename qemuMonitorMigrationCompression qemu: Rework qemuMonitorJSONGetMigrationParams qemu: Rework qemuMonitorJSONSetMigrationParams test: Rework qemuMonitorJSONGetMigrationParams test Add auto convergence migration parameters qemu: Introduce qemuMigrationSetParams qemu: Add support for cpu throttling parameters qemu: Implement auto convergence migration parameters Report auto convergence throttle rate in migration stats include/libvirt/libvirt-domain.h | 27 ++++++ src/qemu/qemu_domain.c | 6 ++ src/qemu/qemu_driver.c | 13 ++- src/qemu/qemu_migration.c | 195 ++++++++++++++++++++++++++++++--------- src/qemu/qemu_migration.h | 17 +++- src/qemu/qemu_monitor.c | 29 ++++-- src/qemu/qemu_monitor.h | 37 +++++--- src/qemu/qemu_monitor_json.c | 74 +++++++-------- src/qemu/qemu_monitor_json.h | 8 +- tests/qemumonitorjsontest.c | 60 ++++++------ tools/virsh-domain.c | 35 +++++++ tools/virsh.pod | 16 ++-- 12 files changed, 364 insertions(+), 153 deletions(-) -- 2.9.0

Checking whether the function has anything to do is better done in the function rather then requiring callers to do that. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_migration.c | 3 +-- src/qemu/qemu_monitor.c | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index a1ce84e..575d367 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3455,8 +3455,7 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver, if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0) return -1; - if ((params->level_set || params->threads_set || params->dthreads_set) && - qemuMonitorSetMigrationCompression(priv->mon, params) < 0) + if (qemuMonitorSetMigrationCompression(priv->mon, params) < 0) goto cleanup; if (compression->xbzrle_cache_set && diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index d8e33a98..f7609e9 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2177,6 +2177,11 @@ qemuMonitorSetMigrationCompression(qemuMonitorPtr mon, QEMU_CHECK_MONITOR_JSON(mon); + if (!compress->level_set && + !compress->threads_set && + !compress->dthreads_set) + return 0; + return qemuMonitorJSONSetMigrationCompression(mon, compress); } -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:07PM +0200, Jiri Denemark wrote:
Checking whether the function has anything to do is better done in the function rather then requiring callers to do that.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_migration.c | 3 +-- src/qemu/qemu_monitor.c | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-)
ACK Jan

Compression parameters are not the only migration parameters. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_migration.c | 52 +++++++++++++++++++++++++---------------------- src/qemu/qemu_migration.h | 9 +++++++- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 575d367..ec2b3dd 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3436,7 +3436,7 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver, { int ret = -1; qemuDomainObjPrivatePtr priv = vm->privateData; - qemuMonitorMigrationCompressionPtr params = &compression->params; + qemuMonitorMigrationCompression params = { 0 }; if (qemuMigrationSetOption(driver, vm, QEMU_MONITOR_MIGRATION_CAPS_XBZRLE, @@ -3455,7 +3455,16 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver, if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0) return -1; - if (qemuMonitorSetMigrationCompression(priv->mon, params) < 0) + params.level_set = compression->level_set; + params.level = compression->level; + + params.threads_set = compression->threads_set; + params.threads = compression->threads; + + params.dthreads_set = compression->dthreads_set; + params.dthreads = compression->dthreads; + + if (qemuMonitorSetMigrationCompression(priv->mon, ¶ms) < 0) goto cleanup; if (compression->xbzrle_cache_set && @@ -6684,7 +6693,6 @@ qemuMigrationCompressionParse(virTypedParameterPtr params, { size_t i; qemuMigrationCompressionPtr compression = NULL; - qemuMonitorMigrationCompressionPtr cparams; if (VIR_ALLOC(compression) < 0) return NULL; @@ -6713,34 +6721,31 @@ qemuMigrationCompressionParse(virTypedParameterPtr params, compression->methods |= 1ULL << method; } -#define GET_PARAM(PARAM, TYPE, PARENT, VALUE) \ +#define GET_PARAM(PARAM, TYPE, VALUE) \ do { \ int rc; \ + const char *par = VIR_MIGRATE_PARAM_COMPRESSION_ ## PARAM; \ \ if ((rc = virTypedParamsGet ## TYPE(params, nparams, \ - PARAM, &PARENT->VALUE)) < 0) \ + par, &compression->VALUE)) < 0) \ goto error; \ \ if (rc == 1) \ - PARENT->VALUE ## _set = true; \ + compression->VALUE ## _set = true; \ } while (0) - cparams = &compression->params; - if (params) { - GET_PARAM(VIR_MIGRATE_PARAM_COMPRESSION_MT_LEVEL, Int, - cparams, level); - GET_PARAM(VIR_MIGRATE_PARAM_COMPRESSION_MT_THREADS, Int, - cparams, threads); - GET_PARAM(VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADS, Int, - cparams, dthreads); - GET_PARAM(VIR_MIGRATE_PARAM_COMPRESSION_XBZRLE_CACHE, ULLong, - compression, xbzrle_cache); + GET_PARAM(MT_LEVEL, Int, level); + GET_PARAM(MT_THREADS, Int, threads); + GET_PARAM(MT_DTHREADS, Int, dthreads); + GET_PARAM(XBZRLE_CACHE, ULLong, xbzrle_cache); } #undef GET_PARAM - if ((cparams->level_set || cparams->threads_set || cparams->dthreads_set) && + if ((compression->level_set || + compression->threads_set || + compression->dthreads_set) && !(compression->methods & (1ULL << QEMU_MIGRATION_COMPRESS_MT))) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("Turn multithread compression on to tune it")); @@ -6772,7 +6777,6 @@ qemuMigrationCompressionDump(qemuMigrationCompressionPtr compression, unsigned long *flags) { size_t i; - qemuMonitorMigrationCompressionPtr cparams = &compression->params; if (compression->methods == 1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE && !compression->xbzrle_cache_set) { @@ -6788,22 +6792,22 @@ qemuMigrationCompressionDump(qemuMigrationCompressionPtr compression, return -1; } - if (cparams->level_set && + if (compression->level_set && virTypedParamsAddInt(params, nparams, maxparams, VIR_MIGRATE_PARAM_COMPRESSION_MT_LEVEL, - cparams->level) < 0) + compression->level) < 0) return -1; - if (cparams->threads_set && + if (compression->threads_set && virTypedParamsAddInt(params, nparams, maxparams, VIR_MIGRATE_PARAM_COMPRESSION_MT_THREADS, - cparams->threads) < 0) + compression->threads) < 0) return -1; - if (cparams->dthreads_set && + if (compression->dthreads_set && virTypedParamsAddInt(params, nparams, maxparams, VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADS, - cparams->dthreads) < 0) + compression->dthreads) < 0) return -1; if (compression->xbzrle_cache_set && diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index d57e825..8b66275 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -95,7 +95,14 @@ VIR_ENUM_DECL(qemuMigrationCompressMethod) struct _qemuMigrationCompression { unsigned long long methods; - qemuMonitorMigrationCompression params; + bool level_set; + int level; + + bool threads_set; + int threads; + + bool dthreads_set; + int dthreads; bool xbzrle_cache_set; unsigned long long xbzrle_cache; -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:08PM +0200, Jiri Denemark wrote:
Compression parameters are not the only migration parameters.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_migration.c | 52 +++++++++++++++++++++++++---------------------- src/qemu/qemu_migration.h | 9 +++++++- 2 files changed, 36 insertions(+), 25 deletions(-)
ACK Jan

qemuMonitorMigrationParams is a better name for a structure which contains various migration parameters. While doing that, we should use full names for individual parameters. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_migration.c | 16 ++++++++-------- src/qemu/qemu_monitor.c | 25 ++++++++++++++----------- src/qemu/qemu_monitor.h | 27 ++++++++++++++------------- src/qemu/qemu_monitor_json.c | 32 ++++++++++++++++---------------- src/qemu/qemu_monitor_json.h | 8 ++++---- tests/qemumonitorjsontest.c | 28 ++++++++++++++-------------- 6 files changed, 70 insertions(+), 66 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index ec2b3dd..433c00c 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3436,7 +3436,7 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver, { int ret = -1; qemuDomainObjPrivatePtr priv = vm->privateData; - qemuMonitorMigrationCompression params = { 0 }; + qemuMonitorMigrationParams migParams = { 0 }; if (qemuMigrationSetOption(driver, vm, QEMU_MONITOR_MIGRATION_CAPS_XBZRLE, @@ -3455,16 +3455,16 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver, if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0) return -1; - params.level_set = compression->level_set; - params.level = compression->level; + migParams.compressLevel_set = compression->level_set; + migParams.compressLevel = compression->level; - params.threads_set = compression->threads_set; - params.threads = compression->threads; + migParams.compressThreads_set = compression->threads_set; + migParams.compressThreads = compression->threads; - params.dthreads_set = compression->dthreads_set; - params.dthreads = compression->dthreads; + migParams.decompressThreads_set = compression->dthreads_set; + migParams.decompressThreads = compression->dthreads; - if (qemuMonitorSetMigrationCompression(priv->mon, ¶ms) < 0) + if (qemuMonitorSetMigrationParams(priv->mon, &migParams) < 0) goto cleanup; if (compression->xbzrle_cache_set && diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index f7609e9..2862cbc 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2160,29 +2160,32 @@ qemuMonitorSetMigrationCacheSize(qemuMonitorPtr mon, int -qemuMonitorGetMigrationCompression(qemuMonitorPtr mon, - qemuMonitorMigrationCompressionPtr compress) +qemuMonitorGetMigrationParams(qemuMonitorPtr mon, + qemuMonitorMigrationParamsPtr params) { QEMU_CHECK_MONITOR_JSON(mon); - return qemuMonitorJSONGetMigrationCompression(mon, compress); + return qemuMonitorJSONGetMigrationParams(mon, params); } int -qemuMonitorSetMigrationCompression(qemuMonitorPtr mon, - qemuMonitorMigrationCompressionPtr compress) +qemuMonitorSetMigrationParams(qemuMonitorPtr mon, + qemuMonitorMigrationParamsPtr params) { - VIR_DEBUG("level=%d threads=%d dthreads=%d", - compress->level, compress->threads, compress->dthreads); + VIR_DEBUG("compressLevel=%d:%d compressThreads=%d:%d " + "decompressThreads=%d:%d", + params->compressLevel_set, params->compressLevel, + params->compressThreads_set, params->compressThreads, + params->decompressThreads_set, params->decompressThreads); QEMU_CHECK_MONITOR_JSON(mon); - if (!compress->level_set && - !compress->threads_set && - !compress->dthreads_set) + if (!params->compressLevel_set && + !params->compressThreads_set && + !params->decompressThreads_set) return 0; - return qemuMonitorJSONSetMigrationCompression(mon, compress); + return qemuMonitorJSONSetMigrationParams(mon, params); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index dd3587f..28cffc9 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -485,22 +485,23 @@ int qemuMonitorGetMigrationCacheSize(qemuMonitorPtr mon, int qemuMonitorSetMigrationCacheSize(qemuMonitorPtr mon, unsigned long long cacheSize); -typedef struct _qemuMonitorMigrationCompression qemuMonitorMigrationCompression; -typedef qemuMonitorMigrationCompression *qemuMonitorMigrationCompressionPtr; -struct _qemuMonitorMigrationCompression { - bool level_set; - bool threads_set; - bool dthreads_set; +typedef struct _qemuMonitorMigrationParams qemuMonitorMigrationParams; +typedef qemuMonitorMigrationParams *qemuMonitorMigrationParamsPtr; +struct _qemuMonitorMigrationParams { + bool compressLevel_set; + int compressLevel; - int level; - int threads; - int dthreads; + bool compressThreads_set; + int compressThreads; + + bool decompressThreads_set; + int decompressThreads; }; -int qemuMonitorGetMigrationCompression(qemuMonitorPtr mon, - qemuMonitorMigrationCompressionPtr compress); -int qemuMonitorSetMigrationCompression(qemuMonitorPtr mon, - qemuMonitorMigrationCompressionPtr compress); +int qemuMonitorGetMigrationParams(qemuMonitorPtr mon, + qemuMonitorMigrationParamsPtr params); +int qemuMonitorSetMigrationParams(qemuMonitorPtr mon, + qemuMonitorMigrationParamsPtr params); typedef enum { QEMU_MONITOR_MIGRATION_STATUS_INACTIVE, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 380ddab..eea32ab 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2529,8 +2529,8 @@ qemuMonitorJSONSetMigrationCacheSize(qemuMonitorPtr mon, int -qemuMonitorJSONGetMigrationCompression(qemuMonitorPtr mon, - qemuMonitorMigrationCompressionPtr compress) +qemuMonitorJSONGetMigrationParams(qemuMonitorPtr mon, + qemuMonitorMigrationParamsPtr params) { int ret = -1; virJSONValuePtr result; @@ -2549,31 +2549,31 @@ qemuMonitorJSONGetMigrationCompression(qemuMonitorPtr mon, result = virJSONValueObjectGet(reply, "return"); if (virJSONValueObjectGetNumberInt(result, "compress-level", - &compress->level) < 0) { + ¶ms->compressLevel) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed/missing compress-level " "in migrate parameters")); goto cleanup; } - compress->level_set = true; + params->compressLevel_set = true; if (virJSONValueObjectGetNumberInt(result, "compress-threads", - &compress->threads) < 0) { + ¶ms->compressThreads) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed/missing compress-threads " "in migrate parameters")); goto cleanup; } - compress->threads_set = true; + params->compressThreads_set = true; if (virJSONValueObjectGetNumberInt(result, "decompress-threads", - &compress->dthreads) < 0) { + ¶ms->decompressThreads) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("malformed/missing decompress-threads " "in migrate parameters")); goto cleanup; } - compress->dthreads_set = true; + params->decompressThreads_set = true; ret = 0; cleanup: @@ -2583,8 +2583,8 @@ qemuMonitorJSONGetMigrationCompression(qemuMonitorPtr mon, } int -qemuMonitorJSONSetMigrationCompression(qemuMonitorPtr mon, - qemuMonitorMigrationCompressionPtr compress) +qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, + qemuMonitorMigrationParamsPtr params) { int ret = -1; virJSONValuePtr cmd = NULL; @@ -2601,19 +2601,19 @@ qemuMonitorJSONSetMigrationCompression(qemuMonitorPtr mon, if (!(args = virJSONValueNewObject())) goto cleanup; - if (compress->level_set && + if (params->compressLevel_set && virJSONValueObjectAppendNumberInt(args, "compress-level", - compress->level) < 0) + params->compressLevel) < 0) goto cleanup; - if (compress->threads_set && + if (params->compressThreads_set && virJSONValueObjectAppendNumberInt(args, "compress-threads", - compress->threads) < 0) + params->compressThreads) < 0) goto cleanup; - if (compress->dthreads_set && + if (params->decompressThreads_set && virJSONValueObjectAppendNumberInt(args, "decompress-threads", - compress->dthreads) < 0) + params->decompressThreads) < 0) goto cleanup; if (virJSONValueObjectAppend(cmd, "arguments", args) < 0) diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 586a363..37a739e 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -131,10 +131,10 @@ int qemuMonitorJSONGetMigrationCacheSize(qemuMonitorPtr mon, int qemuMonitorJSONSetMigrationCacheSize(qemuMonitorPtr mon, unsigned long long cacheSize); -int qemuMonitorJSONGetMigrationCompression(qemuMonitorPtr mon, - qemuMonitorMigrationCompressionPtr compress); -int qemuMonitorJSONSetMigrationCompression(qemuMonitorPtr mon, - qemuMonitorMigrationCompressionPtr compress); +int qemuMonitorJSONGetMigrationParams(qemuMonitorPtr mon, + qemuMonitorMigrationParamsPtr params); +int qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, + qemuMonitorMigrationParamsPtr params); int qemuMonitorJSONGetMigrationStats(qemuMonitorPtr mon, qemuMonitorMigrationStatsPtr stats); diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 0bcf62a..d0b5d9e 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1616,11 +1616,11 @@ testQemuMonitorJSONqemuMonitorJSONGetBlockStatsInfo(const void *data) } static int -testQemuMonitorJSONqemuMonitorJSONGetMigrationCompression(const void *data) +testQemuMonitorJSONqemuMonitorJSONGetMigrationParams(const void *data) { virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data; qemuMonitorTestPtr test = qemuMonitorTestNewSimple(true, xmlopt); - qemuMonitorMigrationCompression compress; + qemuMonitorMigrationParams params; int ret = -1; if (!test) @@ -1637,34 +1637,34 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationCompression(const void *data) goto cleanup; } - if (qemuMonitorJSONGetMigrationCompression(qemuMonitorTestGetMonitor(test), - &compress) < 0) + if (qemuMonitorJSONGetMigrationParams(qemuMonitorTestGetMonitor(test), + ¶ms) < 0) goto cleanup; - if (!compress.level_set || - !compress.threads_set || - !compress.dthreads_set) { + if (!params.compressLevel_set || + !params.compressThreads_set || + !params.decompressThreads_set) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", "One of level, threads or dthreads flags is not set"); return -1; } - if (compress.level != 1) { + if (params.compressLevel != 1) { virReportError(VIR_ERR_INTERNAL_ERROR, "Invalid decompress-threads: %d, expected 1", - compress.level); + params.compressLevel); goto cleanup; } - if (compress.threads != 8) { + if (params.compressThreads != 8) { virReportError(VIR_ERR_INTERNAL_ERROR, "Invalid decompress-threads: %d, expected 8", - compress.threads); + params.compressThreads); goto cleanup; } - if (compress.dthreads != 2) { + if (params.decompressThreads != 2) { virReportError(VIR_ERR_INTERNAL_ERROR, "Invalid decompress-threads: %d, expected 2", - compress.dthreads); + params.decompressThreads); goto cleanup; } ret = 0; @@ -2416,7 +2416,7 @@ mymain(void) DO_TEST(qemuMonitorJSONGetBlockInfo); DO_TEST(qemuMonitorJSONGetBlockStatsInfo); DO_TEST(qemuMonitorJSONGetMigrationCacheSize); - DO_TEST(qemuMonitorJSONGetMigrationCompression); + DO_TEST(qemuMonitorJSONGetMigrationParams); DO_TEST(qemuMonitorJSONGetMigrationStats); DO_TEST(qemuMonitorJSONGetChardevInfo); DO_TEST(qemuMonitorJSONSetBlockIoThrottle); -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:09PM +0200, Jiri Denemark wrote:
qemuMonitorMigrationParams is a better name for a structure which contains various migration parameters. While doing that, we should use full names for individual parameters.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_migration.c | 16 ++++++++-------- src/qemu/qemu_monitor.c | 25 ++++++++++++++----------- src/qemu/qemu_monitor.h | 27 ++++++++++++++------------- src/qemu/qemu_monitor_json.c | 32 ++++++++++++++++---------------- src/qemu/qemu_monitor_json.h | 8 ++++---- tests/qemumonitorjsontest.c | 28 ++++++++++++++-------------- 6 files changed, 70 insertions(+), 66 deletions(-)
ACK Jan

We should not require any parameters to be present. After all we have the *_set bools to express that some parameters were not set. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_monitor_json.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index eea32ab..99678c1 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2537,6 +2537,8 @@ qemuMonitorJSONGetMigrationParams(qemuMonitorPtr mon, virJSONValuePtr cmd = NULL; virJSONValuePtr reply = NULL; + memset(params, 0, sizeof(*params)); + if (!(cmd = qemuMonitorJSONMakeCommand("query-migrate-parameters", NULL))) return -1; @@ -2548,32 +2550,18 @@ qemuMonitorJSONGetMigrationParams(qemuMonitorPtr mon, result = virJSONValueObjectGet(reply, "return"); - if (virJSONValueObjectGetNumberInt(result, "compress-level", - ¶ms->compressLevel) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed/missing compress-level " - "in migrate parameters")); - goto cleanup; - } - params->compressLevel_set = true; +#define PARSE(VAR, FIELD) \ + do { \ + if (virJSONValueObjectGetNumberInt(result, FIELD, \ + ¶ms->VAR) == 0) \ + params->VAR ## _set = true; \ + } while (0) - if (virJSONValueObjectGetNumberInt(result, "compress-threads", - ¶ms->compressThreads) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed/missing compress-threads " - "in migrate parameters")); - goto cleanup; - } - params->compressThreads_set = true; + PARSE(compressLevel, "compress-level"); + PARSE(compressThreads, "compress-threads"); + PARSE(decompressThreads, "decompress-threads"); - if (virJSONValueObjectGetNumberInt(result, "decompress-threads", - ¶ms->decompressThreads) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("malformed/missing decompress-threads " - "in migrate parameters")); - goto cleanup; - } - params->decompressThreads_set = true; +#undef PARSE ret = 0; cleanup: -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:10PM +0200, Jiri Denemark wrote:
We should not require any parameters to be present. After all we have the *_set bools to express that some parameters were not set.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_monitor_json.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-)
ACK, there is no caller that would require us to error out if one of them is missing. Jan

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_monitor_json.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 99678c1..0434522 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2589,20 +2589,19 @@ qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, if (!(args = virJSONValueNewObject())) goto cleanup; - if (params->compressLevel_set && - virJSONValueObjectAppendNumberInt(args, "compress-level", - params->compressLevel) < 0) - goto cleanup; +#define APPEND(VAR, FIELD) \ + do { \ + if (params->VAR ## _set && \ + virJSONValueObjectAppendNumberInt(args, FIELD, \ + params->VAR) < 0) \ + goto cleanup; \ + } while (0) - if (params->compressThreads_set && - virJSONValueObjectAppendNumberInt(args, "compress-threads", - params->compressThreads) < 0) - goto cleanup; + APPEND(compressLevel, "compress-level"); + APPEND(compressThreads, "compress-threads"); + APPEND(decompressThreads, "decompress-threads"); - if (params->decompressThreads_set && - virJSONValueObjectAppendNumberInt(args, "decompress-threads", - params->decompressThreads) < 0) - goto cleanup; +#undef APPEND if (virJSONValueObjectAppend(cmd, "arguments", args) < 0) goto cleanup; -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:11PM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_monitor_json.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-)
ACK Jan

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/qemumonitorjsontest.c | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index d0b5d9e..a0079dd 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1641,32 +1641,26 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationParams(const void *data) ¶ms) < 0) goto cleanup; - if (!params.compressLevel_set || - !params.compressThreads_set || - !params.decompressThreads_set) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - "One of level, threads or dthreads flags is not set"); - return -1; - } +#define CHECK(VAR, FIELD, VALUE) \ + do { \ + if (!params.VAR ## _set) { \ + virReportError(VIR_ERR_INTERNAL_ERROR, "%s is not set", FIELD); \ + goto cleanup; \ + } \ + if (params.VAR != VALUE) { \ + virReportError(VIR_ERR_INTERNAL_ERROR, \ + "Invalid %s: %d, expected %d", \ + FIELD, params.VAR, VALUE); \ + goto cleanup; \ + } \ + } while (0) + + CHECK(compressLevel, "compress-level", 1); + CHECK(compressThreads, "compress-threads", 8); + CHECK(decompressThreads, "decompress-threads", 2); + +#undef CHECK - if (params.compressLevel != 1) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "Invalid decompress-threads: %d, expected 1", - params.compressLevel); - goto cleanup; - } - if (params.compressThreads != 8) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "Invalid decompress-threads: %d, expected 8", - params.compressThreads); - goto cleanup; - } - if (params.decompressThreads != 2) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "Invalid decompress-threads: %d, expected 2", - params.decompressThreads); - goto cleanup; - } ret = 0; cleanup: -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:12PM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/qemumonitorjsontest.c | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-)
ACK Jan

They can be used to tune auto-convergence algorithm (which is enabled with VIR_MIGRATE_AUTO_CONVERGE). Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- include/libvirt/libvirt-domain.h | 19 +++++++++++++++++++ tools/virsh-domain.c | 26 ++++++++++++++++++++++++++ tools/virsh.pod | 16 ++++++++++------ 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index cba4fa5..0ca621b 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -845,6 +845,25 @@ typedef enum { */ # define VIR_MIGRATE_PARAM_COMPRESSION_XBZRLE_CACHE "compression.xbzrle.cache" +/** + * VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL: + * + * virDomainMigrate* params field: the initial percentage guest CPUs are + * throttled to when auto-convergence decides migration is not converging. + * As VIR_TYPED_PARAM_INT. + */ +# define VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL "auto_converge.initial" + +/** + * VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT: + * + * virDomainMigrate* params field: the increment added to + * VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL whenever the hypervisor decides + * the current rate is not enough to ensure convergence of the migration. + * As VIR_TYPED_PARAM_INT. + */ +# define VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT "auto_converge.increment" + /* Domain migration. */ virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn, unsigned long flags, const char *dname, diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 7c3fc86..f4d1156 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -9873,6 +9873,14 @@ static const vshCmdOptDef opts_migrate[] = { .type = VSH_OT_INT, .help = N_("page cache size for xbzrle compression") }, + {.name = "auto-converge-initial", + .type = VSH_OT_INT, + .help = N_("initial CPU throttling rate for auto-convergence") + }, + {.name = "auto-converge-increment", + .type = VSH_OT_INT, + .help = N_("CPU throttling rate increment for auto-convergence") + }, {.name = NULL} }; @@ -10033,6 +10041,24 @@ doMigrate(void *opaque) VIR_FREE(xml); } + if ((rv = vshCommandOptInt(ctl, cmd, "auto-converge-initial", &intOpt)) < 0) { + goto out; + } else if (rv > 0) { + if (virTypedParamsAddInt(¶ms, &nparams, &maxparams, + VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL, + intOpt) < 0) + goto save_error; + } + + if ((rv = vshCommandOptInt(ctl, cmd, "auto-converge-increment", &intOpt)) < 0) { + goto out; + } else if (rv > 0) { + if (virTypedParamsAddInt(¶ms, &nparams, &maxparams, + VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT, + intOpt) < 0) + goto save_error; + } + if (vshCommandOptBool(cmd, "live")) flags |= VIR_MIGRATE_LIVE; if (vshCommandOptBool(cmd, "p2p")) diff --git a/tools/virsh.pod b/tools/virsh.pod index 8e3ba69..73edd82 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -1550,14 +1550,14 @@ to the I<uri> namespace is displayed instead of being modified. =item B<migrate> [I<--live>] [I<--offline>] [I<--direct>] [I<--p2p> [I<--tunnelled>]] [I<--persistent>] [I<--undefinesource>] [I<--suspend>] [I<--copy-storage-all>] [I<--copy-storage-inc>] [I<--change-protection>] [I<--unsafe>] [I<--verbose>] -[I<--abort-on-error>] [I<--auto-converge>] [I<--postcopy>] -[I<--postcopy-after-precopy>] I<domain> I<desturi> [I<migrateuri>] -[I<graphicsuri>] [I<listen-address>] [I<dname>] +[I<--abort-on-error>] [I<--postcopy>] [I<--postcopy-after-precopy>] +I<domain> I<desturi> [I<migrateuri>] [I<graphicsuri>] [I<listen-address>] [I<dname>] [I<--timeout> B<seconds> [I<--timeout-suspend> | I<--timeout-postcopy>]] [I<--xml> B<file>] [I<--migrate-disks> B<disk-list>] [I<--disks-port> B<port>] [I<--compressed>] [I<--comp-methods> B<method-list>] [I<--comp-mt-level>] [I<--comp-mt-threads>] [I<--comp-mt-dthreads>] -[I<--comp-xbzrle-cache>] +[I<--comp-xbzrle-cache>] [I<--auto-converge>] [I<auto-converge-initial>] +[I<auto-converge-increment>] Migrate domain to another host. Add I<--live> for live migration; <--p2p> for peer-2-peer migration; I<--direct> for direct migration; or I<--tunnelled> @@ -1582,14 +1582,18 @@ by the hypervisor, but can be explicitly used to reject the migration if the hypervisor lacks change protection support. I<--verbose> displays the progress of migration. I<--abort-on-error> cancels the migration if a soft error (for example I/O error) happens during the -migration. I<--auto-converge> forces convergence during live migration. -I<--postcopy> enables post-copy logic in migration, but does not +migration. I<--postcopy> enables post-copy logic in migration, but does not actually start post-copy, i.e., migration is started in pre-copy mode. Once migration is running, the user may switch to post-copy using the B<migrate-postcopy> command sent from another virsh instance or use I<--postcopy-after-precopy> to let libvirt automatically switch to post-copy after the first pass of pre-copy is finished. +I<--auto-converge> forces convergence during live migration. The initial +guest CPU throttling rate can be set with I<auto-converge-initial>. If the +initial throttling rate is not enough to ensure convergence, the rate is +periodically increased by I<auto-converge-increment>. + B<Note>: Individual hypervisors usually do not support all possible types of migration. For example, QEMU does not support direct migration. -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:13PM +0200, Jiri Denemark wrote:
They can be used to tune auto-convergence algorithm (which is enabled with VIR_MIGRATE_AUTO_CONVERGE).
There is a public bug filed for this feature: https://bugzilla.redhat.com/show_bug.cgi?id=1289288 You could add the link to the commit message.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- include/libvirt/libvirt-domain.h | 19 +++++++++++++++++++ tools/virsh-domain.c | 26 ++++++++++++++++++++++++++ tools/virsh.pod | 16 ++++++++++------ 3 files changed, 55 insertions(+), 6 deletions(-)
ACK Jan

Several places in the code update qemuMonitorMigrationParams structure and qemuMigrationSetParams is then used to set them all at once. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_migration.c | 59 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 433c00c..8cfbb9f 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3432,11 +3432,11 @@ static int qemuMigrationSetCompression(virQEMUDriverPtr driver, virDomainObjPtr vm, qemuDomainAsyncJob job, - qemuMigrationCompressionPtr compression) + qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams) { int ret = -1; qemuDomainObjPrivatePtr priv = vm->privateData; - qemuMonitorMigrationParams migParams = { 0 }; if (qemuMigrationSetOption(driver, vm, QEMU_MONITOR_MIGRATION_CAPS_XBZRLE, @@ -3455,17 +3455,14 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver, if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0) return -1; - migParams.compressLevel_set = compression->level_set; - migParams.compressLevel = compression->level; + migParams->compressLevel_set = compression->level_set; + migParams->compressLevel = compression->level; - migParams.compressThreads_set = compression->threads_set; - migParams.compressThreads = compression->threads; + migParams->compressThreads_set = compression->threads_set; + migParams->compressThreads = compression->threads; - migParams.decompressThreads_set = compression->dthreads_set; - migParams.decompressThreads = compression->dthreads; - - if (qemuMonitorSetMigrationParams(priv->mon, &migParams) < 0) - goto cleanup; + migParams->decompressThreads_set = compression->dthreads_set; + migParams->decompressThreads = compression->dthreads; if (compression->xbzrle_cache_set && qemuMonitorSetMigrationCacheSize(priv->mon, @@ -3481,6 +3478,32 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver, return ret; } + +static int +qemuMigrationSetParams(virQEMUDriverPtr driver, + virDomainObjPtr vm, + qemuDomainAsyncJob job, + qemuMonitorMigrationParamsPtr migParams) +{ + qemuDomainObjPrivatePtr priv = vm->privateData; + int ret = -1; + + if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0) + return -1; + + if (qemuMonitorSetMigrationParams(priv->mon, migParams) < 0) + goto cleanup; + + ret = 0; + + cleanup: + if (qemuDomainObjExitMonitor(driver, vm) < 0) + ret = -1; + + return ret; +} + + static int qemuMigrationPrepareAny(virQEMUDriverPtr driver, virConnectPtr dconn, @@ -3516,6 +3539,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, bool stopProcess = false; bool relabel = false; int rv; + qemuMonitorMigrationParams migParams = { 0 }; virNWFilterReadLockFilterUpdates(); @@ -3698,7 +3722,7 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, } if (qemuMigrationSetCompression(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN, - compression) < 0) + compression, &migParams) < 0) goto stopjob; if (STREQ_NULLABLE(protocol, "rdma") && @@ -3717,6 +3741,10 @@ qemuMigrationPrepareAny(virQEMUDriverPtr driver, QEMU_ASYNC_JOB_MIGRATION_IN) < 0) goto stopjob; + if (qemuMigrationSetParams(driver, vm, QEMU_ASYNC_JOB_MIGRATION_IN, + &migParams) < 0) + goto stopjob; + if (mig->nbd && flags & (VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC) && virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NBD_SERVER)) { @@ -4554,6 +4582,7 @@ qemuMigrationRun(virQEMUDriverPtr driver, virDomainDefPtr persistDef = NULL; char *timestamp; int rc; + qemuMonitorMigrationParams migParams = { 0 }; VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, " "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, " @@ -4634,7 +4663,7 @@ qemuMigrationRun(virQEMUDriverPtr driver, } if (qemuMigrationSetCompression(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, - compression) < 0) + compression, &migParams) < 0) goto cleanup; if (qemuMigrationSetOption(driver, vm, @@ -4654,6 +4683,10 @@ qemuMigrationRun(virQEMUDriverPtr driver, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0) goto cleanup; + if (qemuMigrationSetParams(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, + &migParams) < 0) + goto cleanup; + if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0) goto cleanup; -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:14PM +0200, Jiri Denemark wrote:
Several places in the code update qemuMonitorMigrationParams structure and qemuMigrationSetParams is then used to set them all at once.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_migration.c | 59 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 13 deletions(-)
@@ -3455,17 +3455,14 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver, if (qemuDomainObjEnterMonitorAsync(driver, vm, job) < 0) return -1;
- migParams.compressLevel_set = compression->level_set; - migParams.compressLevel = compression->level; + migParams->compressLevel_set = compression->level_set; + migParams->compressLevel = compression->level;
- migParams.compressThreads_set = compression->threads_set; - migParams.compressThreads = compression->threads; + migParams->compressThreads_set = compression->threads_set; + migParams->compressThreads = compression->threads;
- migParams.decompressThreads_set = compression->dthreads_set; - migParams.decompressThreads = compression->dthreads; - - if (qemuMonitorSetMigrationParams(priv->mon, &migParams) < 0) - goto cleanup; + migParams->decompressThreads_set = compression->dthreads_set; + migParams->decompressThreads = compression->dthreads;
This would look nicer in a separate function. ACK regardless. Jan

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_monitor.c | 11 ++++++++--- src/qemu/qemu_monitor.h | 6 ++++++ src/qemu/qemu_monitor_json.c | 4 ++++ tests/qemumonitorjsontest.c | 6 +++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2862cbc..098e654 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2173,16 +2173,21 @@ qemuMonitorSetMigrationParams(qemuMonitorPtr mon, qemuMonitorMigrationParamsPtr params) { VIR_DEBUG("compressLevel=%d:%d compressThreads=%d:%d " - "decompressThreads=%d:%d", + "decompressThreads=%d:%d cpuThrottleInitial=%d:%d " + "cpuThrottleIncrement=%d:%d", params->compressLevel_set, params->compressLevel, params->compressThreads_set, params->compressThreads, - params->decompressThreads_set, params->decompressThreads); + params->decompressThreads_set, params->decompressThreads, + params->cpuThrottleInitial_set, params->cpuThrottleInitial, + params->cpuThrottleIncrement_set, params->cpuThrottleIncrement); QEMU_CHECK_MONITOR_JSON(mon); if (!params->compressLevel_set && !params->compressThreads_set && - !params->decompressThreads_set) + !params->decompressThreads_set && + !params->cpuThrottleInitial_set && + !params->cpuThrottleIncrement_set) return 0; return qemuMonitorJSONSetMigrationParams(mon, params); diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 28cffc9..6fecca7 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -496,6 +496,12 @@ struct _qemuMonitorMigrationParams { bool decompressThreads_set; int decompressThreads; + + bool cpuThrottleInitial_set; + int cpuThrottleInitial; + + bool cpuThrottleIncrement_set; + int cpuThrottleIncrement; }; int qemuMonitorGetMigrationParams(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 0434522..66b9c4c 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2560,6 +2560,8 @@ qemuMonitorJSONGetMigrationParams(qemuMonitorPtr mon, PARSE(compressLevel, "compress-level"); PARSE(compressThreads, "compress-threads"); PARSE(decompressThreads, "decompress-threads"); + PARSE(cpuThrottleInitial, "cpu-throttle-initial"); + PARSE(cpuThrottleIncrement, "cpu-throttle-increment"); #undef PARSE @@ -2600,6 +2602,8 @@ qemuMonitorJSONSetMigrationParams(qemuMonitorPtr mon, APPEND(compressLevel, "compress-level"); APPEND(compressThreads, "compress-threads"); APPEND(decompressThreads, "decompress-threads"); + APPEND(cpuThrottleInitial, "cpu-throttle-initial"); + APPEND(cpuThrottleIncrement, "cpu-throttle-increment"); #undef APPEND diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index a0079dd..f698c14 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -1630,8 +1630,10 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationParams(const void *data) "{" " \"return\": {" " \"decompress-threads\": 2," + " \"cpu-throttle-increment\": 10," " \"compress-threads\": 8," - " \"compress-level\": 1" + " \"compress-level\": 1," + " \"cpu-throttle-initial\": 20" " }" "}") < 0) { goto cleanup; @@ -1658,6 +1660,8 @@ testQemuMonitorJSONqemuMonitorJSONGetMigrationParams(const void *data) CHECK(compressLevel, "compress-level", 1); CHECK(compressThreads, "compress-threads", 8); CHECK(decompressThreads, "decompress-threads", 2); + CHECK(cpuThrottleInitial, "cpu-throttle-initial", 20); + CHECK(cpuThrottleIncrement, "cpu-throttle-increment", 10); #undef CHECK -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:15PM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_monitor.c | 11 ++++++++--- src/qemu/qemu_monitor.h | 6 ++++++ src/qemu/qemu_monitor_json.c | 4 ++++ tests/qemumonitorjsontest.c | 6 +++++- 4 files changed, 23 insertions(+), 4 deletions(-)
ACK Jan

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_driver.c | 13 ++++-- src/qemu/qemu_migration.c | 101 +++++++++++++++++++++++++++++++++++++--------- src/qemu/qemu_migration.h | 8 ++++ 3 files changed, 99 insertions(+), 23 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d065e45..2f2eecb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -11775,6 +11775,7 @@ qemuDomainMigratePerform(virDomainPtr dom, int ret = -1; const char *dconnuri = NULL; qemuMigrationCompressionPtr compression = NULL; + qemuMonitorMigrationParams migParams = { 0 }; virCheckFlags(QEMU_MIGRATION_FLAGS, -1); @@ -11809,7 +11810,7 @@ qemuDomainMigratePerform(virDomainPtr dom, */ ret = qemuMigrationPerform(driver, dom->conn, vm, NULL, NULL, dconnuri, uri, NULL, NULL, 0, NULL, 0, - compression, cookie, cookielen, + compression, &migParams, cookie, cookielen, NULL, NULL, /* No output cookies in v2 */ flags, dname, resource, false); @@ -12198,6 +12199,7 @@ qemuDomainMigratePerform3(virDomainPtr dom, virQEMUDriverPtr driver = dom->conn->privateData; virDomainObjPtr vm; qemuMigrationCompressionPtr compression = NULL; + qemuMonitorMigrationParams migParams = { 0 }; int ret = -1; virCheckFlags(QEMU_MIGRATION_FLAGS, -1); @@ -12215,7 +12217,7 @@ qemuDomainMigratePerform3(virDomainPtr dom, ret = qemuMigrationPerform(driver, dom->conn, vm, xmlin, NULL, dconnuri, uri, NULL, NULL, 0, NULL, 0, - compression, + compression, &migParams, cookiein, cookieinlen, cookieout, cookieoutlen, flags, dname, resource, true); @@ -12249,6 +12251,7 @@ qemuDomainMigratePerform3Params(virDomainPtr dom, unsigned long long bandwidth = 0; int nbdPort = 0; qemuMigrationCompressionPtr compression = NULL; + qemuMonitorMigrationParamsPtr migParams = NULL; int ret = -1; virCheckFlags(QEMU_MIGRATION_FLAGS, -1); @@ -12288,6 +12291,9 @@ qemuDomainMigratePerform3Params(virDomainPtr dom, if (nmigrate_disks < 0) goto cleanup; + if (!(migParams = qemuMigrationParams(params, nparams, flags))) + goto cleanup; + if (!(compression = qemuMigrationCompressionParse(params, nparams, flags))) goto cleanup; @@ -12302,11 +12308,12 @@ qemuDomainMigratePerform3Params(virDomainPtr dom, ret = qemuMigrationPerform(driver, dom->conn, vm, dom_xml, persist_xml, dconnuri, uri, graphicsuri, listenAddress, nmigrate_disks, migrate_disks, nbdPort, - compression, + compression, migParams, cookiein, cookieinlen, cookieout, cookieoutlen, flags, dname, bandwidth, true); cleanup: VIR_FREE(compression); + VIR_FREE(migParams); VIR_FREE(migrate_disks); return ret; } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 8cfbb9f..b26f363 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -3479,6 +3479,52 @@ qemuMigrationSetCompression(virQEMUDriverPtr driver, } +qemuMonitorMigrationParamsPtr +qemuMigrationParams(virTypedParameterPtr params, + int nparams, + unsigned long flags) +{ + qemuMonitorMigrationParamsPtr migParams; + + if (VIR_ALLOC(migParams) < 0) + return NULL; + + if (!params) + return migParams; + +#define GET(PARAM, VAR) \ + do { \ + int rc; \ + if ((rc = virTypedParamsGetInt(params, nparams, \ + VIR_MIGRATE_PARAM_ ## PARAM, \ + &migParams->VAR)) < 0) \ + goto error; \ + \ + if (rc == 1) \ + migParams->VAR ## _set = true; \ + } while (0) + + GET(AUTO_CONVERGE_INITIAL, cpuThrottleInitial); + GET(AUTO_CONVERGE_INCREMENT, cpuThrottleIncrement); + +#undef GET + + if ((migParams->cpuThrottleInitial_set || + migParams->cpuThrottleIncrement_set) && + !(flags & VIR_MIGRATE_AUTO_CONVERGE)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Turn auto convergence on to tune it")); + goto error; + } + + return migParams; + + error: + VIR_FREE(migParams); + return NULL; +} + + static int qemuMigrationSetParams(virQEMUDriverPtr driver, virDomainObjPtr vm, @@ -4564,7 +4610,8 @@ qemuMigrationRun(virQEMUDriverPtr driver, const char *graphicsuri, size_t nmigrate_disks, const char **migrate_disks, - qemuMigrationCompressionPtr compression) + qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams) { int ret = -1; unsigned int migrate_flags = QEMU_MONITOR_MIGRATE_BACKGROUND; @@ -4582,7 +4629,6 @@ qemuMigrationRun(virQEMUDriverPtr driver, virDomainDefPtr persistDef = NULL; char *timestamp; int rc; - qemuMonitorMigrationParams migParams = { 0 }; VIR_DEBUG("driver=%p, vm=%p, cookiein=%s, cookieinlen=%d, " "cookieout=%p, cookieoutlen=%p, flags=%lx, resource=%lu, " @@ -4663,7 +4709,7 @@ qemuMigrationRun(virQEMUDriverPtr driver, } if (qemuMigrationSetCompression(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, - compression, &migParams) < 0) + compression, migParams) < 0) goto cleanup; if (qemuMigrationSetOption(driver, vm, @@ -4684,7 +4730,7 @@ qemuMigrationRun(virQEMUDriverPtr driver, goto cleanup; if (qemuMigrationSetParams(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT, - &migParams) < 0) + migParams) < 0) goto cleanup; if (qemuDomainObjEnterMonitorAsync(driver, vm, @@ -4918,7 +4964,8 @@ static int doNativeMigrate(virQEMUDriverPtr driver, const char *graphicsuri, size_t nmigrate_disks, const char **migrate_disks, - qemuMigrationCompressionPtr compression) + qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams) { qemuDomainObjPrivatePtr priv = vm->privateData; virURIPtr uribits = NULL; @@ -4969,7 +5016,7 @@ static int doNativeMigrate(virQEMUDriverPtr driver, ret = qemuMigrationRun(driver, vm, persist_xml, cookiein, cookieinlen, cookieout, cookieoutlen, flags, resource, &spec, dconn, graphicsuri, nmigrate_disks, migrate_disks, - compression); + compression, migParams); if (spec.destType == MIGRATION_DEST_FD) VIR_FORCE_CLOSE(spec.dest.fd.qemu); @@ -4995,7 +5042,8 @@ static int doTunnelMigrate(virQEMUDriverPtr driver, const char *graphicsuri, size_t nmigrate_disks, const char **migrate_disks, - qemuMigrationCompressionPtr compression) + qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams) { virNetSocketPtr sock = NULL; int ret = -1; @@ -5033,7 +5081,7 @@ static int doTunnelMigrate(virQEMUDriverPtr driver, ret = qemuMigrationRun(driver, vm, persist_xml, cookiein, cookieinlen, cookieout, cookieoutlen, flags, resource, &spec, dconn, graphicsuri, nmigrate_disks, migrate_disks, - compression); + compression, migParams); cleanup: if (spec.destType == MIGRATION_DEST_FD) { @@ -5072,6 +5120,7 @@ static int doPeer2PeerMigrate2(virQEMUDriverPtr driver, virStreamPtr st = NULL; unsigned long destflags; qemuMigrationCompressionPtr compression = NULL; + qemuMonitorMigrationParams migParams = { 0 }; VIR_DEBUG("driver=%p, sconn=%p, dconn=%p, vm=%p, dconnuri=%s, " "flags=%lx, dname=%s, resource=%lu", @@ -5148,12 +5197,13 @@ static int doPeer2PeerMigrate2(virQEMUDriverPtr driver, ret = doTunnelMigrate(driver, vm, st, NULL, NULL, 0, NULL, NULL, flags, resource, dconn, - NULL, 0, NULL, compression); + NULL, 0, NULL, compression, &migParams); else ret = doNativeMigrate(driver, vm, NULL, uri_out, cookie, cookielen, NULL, NULL, /* No out cookie with v2 migration */ - flags, resource, dconn, NULL, 0, NULL, compression); + flags, resource, dconn, NULL, 0, NULL, + compression, &migParams); /* Perform failed. Make sure Finish doesn't overwrite the error */ if (ret < 0) @@ -5221,6 +5271,7 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver, const char **migrate_disks, int nbdPort, qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams, unsigned long long bandwidth, bool useParams, unsigned long flags) @@ -5392,13 +5443,15 @@ doPeer2PeerMigrate3(virQEMUDriverPtr driver, cookiein, cookieinlen, &cookieout, &cookieoutlen, flags, bandwidth, dconn, graphicsuri, - nmigrate_disks, migrate_disks, compression); + nmigrate_disks, migrate_disks, compression, + migParams); } else { ret = doNativeMigrate(driver, vm, persist_xml, uri, cookiein, cookieinlen, &cookieout, &cookieoutlen, flags, bandwidth, dconn, graphicsuri, - nmigrate_disks, migrate_disks, compression); + nmigrate_disks, migrate_disks, compression, + migParams); } /* Perform failed. Make sure Finish doesn't overwrite the error */ @@ -5576,6 +5629,7 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver, const char **migrate_disks, int nbdPort, qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams, unsigned long flags, const char *dname, unsigned long resource, @@ -5699,8 +5753,8 @@ static int doPeer2PeerMigrate(virQEMUDriverPtr driver, ret = doPeer2PeerMigrate3(driver, sconn, dconn, dconnuri, vm, xmlin, persist_xml, dname, uri, graphicsuri, listenAddress, nmigrate_disks, migrate_disks, - nbdPort, compression, resource, useParams, - flags); + nbdPort, compression, migParams, resource, + useParams, flags); } else { ret = doPeer2PeerMigrate2(driver, sconn, dconn, vm, dconnuri, flags, dname, resource); @@ -5740,6 +5794,7 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver, const char **migrate_disks, int nbdPort, qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams, const char *cookiein, int cookieinlen, char **cookieout, @@ -5776,13 +5831,14 @@ qemuMigrationPerformJob(virQEMUDriverPtr driver, ret = doPeer2PeerMigrate(driver, conn, vm, xmlin, persist_xml, dconnuri, uri, graphicsuri, listenAddress, nmigrate_disks, migrate_disks, nbdPort, - compression, flags, dname, resource, &v3proto); + compression, migParams, flags, dname, resource, + &v3proto); } else { qemuMigrationJobSetPhase(driver, vm, QEMU_MIGRATION_PHASE_PERFORM2); ret = doNativeMigrate(driver, vm, persist_xml, uri, cookiein, cookieinlen, cookieout, cookieoutlen, flags, resource, NULL, NULL, 0, NULL, - compression); + compression, migParams); } if (ret < 0) goto endjob; @@ -5845,6 +5901,7 @@ qemuMigrationPerformPhase(virQEMUDriverPtr driver, size_t nmigrate_disks, const char **migrate_disks, qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams, const char *cookiein, int cookieinlen, char **cookieout, @@ -5870,7 +5927,7 @@ qemuMigrationPerformPhase(virQEMUDriverPtr driver, ret = doNativeMigrate(driver, vm, persist_xml, uri, cookiein, cookieinlen, cookieout, cookieoutlen, flags, resource, NULL, graphicsuri, - nmigrate_disks, migrate_disks, compression); + nmigrate_disks, migrate_disks, compression, migParams); if (ret < 0) { if (qemuMigrationRestoreDomainState(conn, vm)) { @@ -5915,6 +5972,7 @@ qemuMigrationPerform(virQEMUDriverPtr driver, const char **migrate_disks, int nbdPort, qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams, const char *cookiein, int cookieinlen, char **cookieout, @@ -5945,7 +6003,8 @@ qemuMigrationPerform(virQEMUDriverPtr driver, return qemuMigrationPerformJob(driver, conn, vm, xmlin, persist_xml, dconnuri, uri, graphicsuri, listenAddress, nmigrate_disks, migrate_disks, nbdPort, - compression, cookiein, cookieinlen, + compression, migParams, + cookiein, cookieinlen, cookieout, cookieoutlen, flags, dname, resource, v3proto); } else { @@ -5959,14 +6018,16 @@ qemuMigrationPerform(virQEMUDriverPtr driver, return qemuMigrationPerformPhase(driver, conn, vm, persist_xml, uri, graphicsuri, nmigrate_disks, migrate_disks, - compression, cookiein, cookieinlen, + compression, migParams, + cookiein, cookieinlen, cookieout, cookieoutlen, flags, resource); } else { return qemuMigrationPerformJob(driver, conn, vm, xmlin, persist_xml, NULL, uri, graphicsuri, listenAddress, nmigrate_disks, migrate_disks, nbdPort, - compression, cookiein, cookieinlen, + compression, migParams, + cookiein, cookieinlen, cookieout, cookieoutlen, flags, dname, resource, v3proto); } diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h index 8b66275..14c6178 100644 --- a/src/qemu/qemu_migration.h +++ b/src/qemu/qemu_migration.h @@ -65,6 +65,8 @@ typedef qemuMigrationCompression *qemuMigrationCompressionPtr; VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADS, VIR_TYPED_PARAM_INT, \ VIR_MIGRATE_PARAM_COMPRESSION_XBZRLE_CACHE, VIR_TYPED_PARAM_ULLONG, \ VIR_MIGRATE_PARAM_PERSIST_XML, VIR_TYPED_PARAM_STRING, \ + VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL, VIR_TYPED_PARAM_INT, \ + VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT, VIR_TYPED_PARAM_INT, \ NULL @@ -118,6 +120,11 @@ int qemuMigrationCompressionDump(qemuMigrationCompressionPtr compression, int *maxparams, unsigned long *flags); +qemuMonitorMigrationParamsPtr +qemuMigrationParams(virTypedParameterPtr params, + int nparams, + unsigned long flags); + int qemuMigrationJobStart(virQEMUDriverPtr driver, virDomainObjPtr vm, qemuDomainAsyncJob job) @@ -197,6 +204,7 @@ int qemuMigrationPerform(virQEMUDriverPtr driver, const char **migrate_disks, int nbdPort, qemuMigrationCompressionPtr compression, + qemuMonitorMigrationParamsPtr migParams, const char *cookiein, int cookieinlen, char **cookieout, -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:16PM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_driver.c | 13 ++++-- src/qemu/qemu_migration.c | 101 +++++++++++++++++++++++++++++++++++++--------- src/qemu/qemu_migration.h | 8 ++++ 3 files changed, 99 insertions(+), 23 deletions(-)
ACK Jan

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- include/libvirt/libvirt-domain.h | 8 ++++++++ src/qemu/qemu_domain.c | 6 ++++++ src/qemu/qemu_migration.c | 6 ++++++ src/qemu/qemu_monitor.h | 2 ++ src/qemu/qemu_monitor_json.c | 3 +++ tools/virsh-domain.c | 9 +++++++++ 6 files changed, 34 insertions(+) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 0ca621b..5f41602 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -2985,6 +2985,14 @@ int virDomainAbortJob(virDomainPtr dom); */ # define VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW "compression_overflow" +/** + * VIR_DOMAIN_JOB_AUTO_CONVERGE_THROTTLE: + * + * virDomainGetJobStats field: current percentage guest CPUs are throttled + * to when auto-convergence decided migration was not converging, as + * VIR_TYPED_PARAM_INT. + */ +# define VIR_DOMAIN_JOB_AUTO_CONVERGE_THROTTLE "auto_converge_throttle" /** diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 29f6b93..ab20e52 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -458,6 +458,12 @@ qemuDomainJobInfoToParams(qemuDomainJobInfoPtr jobInfo, goto error; } + if (stats->cpu_throttle_percentage && + virTypedParamsAddInt(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_AUTO_CONVERGE_THROTTLE, + stats->cpu_throttle_percentage) < 0) + goto error; + *type = jobInfo->type; *params = par; *nparams = npar; diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index b26f363..c411dab 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -807,6 +807,10 @@ qemuMigrationCookieStatisticsXMLFormat(virBufferPtr buf, stats->xbzrle_overflow); } + virBufferAsprintf(buf, "<%1$s>%2$d</%1$s>\n", + VIR_DOMAIN_JOB_AUTO_CONVERGE_THROTTLE, + stats->cpu_throttle_percentage); + virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</statistics>\n"); } @@ -1152,6 +1156,8 @@ qemuMigrationCookieStatisticsXMLParse(xmlXPathContextPtr ctxt) virXPathULongLong("string(./" VIR_DOMAIN_JOB_COMPRESSION_OVERFLOW "[1])", ctxt, &stats->xbzrle_overflow); + virXPathInt("string(./" VIR_DOMAIN_JOB_AUTO_CONVERGE_THROTTLE "[1])", + ctxt, &stats->cpu_throttle_percentage); cleanup: ctxt->node = save_ctxt; return jobInfo; diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 6fecca7..cb4cca8 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -562,6 +562,8 @@ struct _qemuMonitorMigrationStats { unsigned long long xbzrle_pages; unsigned long long xbzrle_cache_miss; unsigned long long xbzrle_overflow; + + int cpu_throttle_percentage; }; int qemuMonitorGetMigrationStats(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 66b9c4c..bb426dc 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2673,6 +2673,9 @@ qemuMonitorJSONGetMigrationStatsReply(virJSONValuePtr reply, &stats->setup_time) == 0) stats->setup_time_set = true; + ignore_value(virJSONValueObjectGetNumberInt(ret, "cpu-throttle-percentage", + &stats->cpu_throttle_percentage)); + switch ((qemuMonitorMigrationStatus) stats->status) { case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: case QEMU_MONITOR_MIGRATION_STATUS_SETUP: diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index f4d1156..81b1956 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -5759,6 +5759,7 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) int nparams = 0; unsigned long long value; unsigned int flags = 0; + int ivalue; int rc; if (!(dom = virshCommandOptDomain(ctl, cmd, NULL))) @@ -5994,6 +5995,14 @@ cmdDomjobinfo(vshControl *ctl, const vshCmd *cmd) vshPrint(ctl, "%-17s %-13llu\n", _("Compression overflows:"), value); } + if ((rc = virTypedParamsGetInt(params, nparams, + VIR_DOMAIN_JOB_AUTO_CONVERGE_THROTTLE, + &ivalue)) < 0) { + goto save_error; + } else if (rc) { + vshPrint(ctl, "%-17s %-13d\n", _("Auto converge throttle:"), ivalue); + } + ret = true; cleanup: -- 2.9.0

On Tue, Jun 21, 2016 at 01:47:17PM +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- include/libvirt/libvirt-domain.h | 8 ++++++++ src/qemu/qemu_domain.c | 6 ++++++ src/qemu/qemu_migration.c | 6 ++++++ src/qemu/qemu_monitor.h | 2 ++ src/qemu/qemu_monitor_json.c | 3 +++ tools/virsh-domain.c | 9 +++++++++ 6 files changed, 34 insertions(+)
ACK Jan
participants (2)
-
Jiri Denemark
-
Ján Tomko