Add new compress methods zlib and zstd for parallel migration,
these method should be used with migration option --comp-methods
and will be processed in 'qemuMigrationParamsSetCompression'.
Note that only one compress method could be chosen for parallel
migration and they cann't be used in compress migration.
Signed-off-by: Jiang Jiacheng <jiangjiacheng@huawei.com>
---
src/qemu/qemu_migration.h | 2 +
src/qemu/qemu_migration_params.c | 80 +++++++++++++++++++++++++++++++-
src/qemu/qemu_migration_params.h | 3 ++
3 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_migration.h b/src/qemu/qemu_migration.h
index d21b6f67e8..ed62fd4a91 100644
--- a/src/qemu/qemu_migration.h
+++ b/src/qemu/qemu_migration.h
@@ -86,6 +86,8 @@
VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT, VIR_TYPED_PARAM_INT, \
VIR_MIGRATE_PARAM_BANDWIDTH_POSTCOPY, VIR_TYPED_PARAM_ULLONG, \
VIR_MIGRATE_PARAM_PARALLEL_CONNECTIONS, VIR_TYPED_PARAM_INT, \
+ VIR_MIGRATE_PARAM_COMPRESSION_ZLIB_LEVEL, VIR_TYPED_PARAM_INT, \
+ VIR_MIGRATE_PARAM_COMPRESSION_ZSTD_LEVEL, VIR_TYPED_PARAM_INT, \
VIR_MIGRATE_PARAM_TLS_DESTINATION, VIR_TYPED_PARAM_STRING, \
VIR_MIGRATE_PARAM_DISKS_URI, VIR_TYPED_PARAM_STRING, \
NULL
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
index bd09dcfb23..3c224131c5 100644
--- a/src/qemu/qemu_migration_params.c
+++ b/src/qemu/qemu_migration_params.c
@@ -71,6 +71,8 @@ struct _qemuMigrationParams {
typedef enum {
QEMU_MIGRATION_COMPRESS_XBZRLE = 0,
QEMU_MIGRATION_COMPRESS_MT,
+ QEMU_MIGRATION_COMPRESS_ZLIB,
+ QEMU_MIGRATION_COMPRESS_ZSTD,
QEMU_MIGRATION_COMPRESS_LAST
} qemuMigrationCompressMethod;
@@ -79,6 +81,8 @@ VIR_ENUM_IMPL(qemuMigrationCompressMethod,
QEMU_MIGRATION_COMPRESS_LAST,
"xbzrle",
"mt",
+ "zlib",
+ "zstd",
);
VIR_ENUM_IMPL(qemuMigrationCapability,
@@ -114,6 +118,9 @@ VIR_ENUM_IMPL(qemuMigrationParam,
"xbzrle-cache-size",
"max-postcopy-bandwidth",
"multifd-channels",
+ "multifd-compression",
+ "multifd-zlib-level",
+ "multifd-zstd-level",
);
typedef struct _qemuMigrationParamsAlwaysOnItem qemuMigrationParamsAlwaysOnItem;
@@ -225,6 +232,14 @@ static const qemuMigrationParamsTPMapItem qemuMigrationParamsTPMap[] = {
.param = QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS,
.party = QEMU_MIGRATION_SOURCE | QEMU_MIGRATION_DESTINATION},
+ {.typedParam = VIR_MIGRATE_PARAM_COMPRESSION_ZLIB_LEVEL,
+ .param = QEMU_MIGRATION_PARAM_MULTIFD_ZLIB_LEVEL,
+ .party = QEMU_MIGRATION_SOURCE | QEMU_MIGRATION_DESTINATION},
+
+ {.typedParam = VIR_MIGRATE_PARAM_COMPRESSION_ZSTD_LEVEL,
+ .param = QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL,
+ .party = QEMU_MIGRATION_SOURCE | QEMU_MIGRATION_DESTINATION},
+
{.typedParam = VIR_MIGRATE_PARAM_TLS_DESTINATION,
.param = QEMU_MIGRATION_PARAM_TLS_HOSTNAME,
.party = QEMU_MIGRATION_SOURCE},
@@ -271,6 +286,15 @@ static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = {
[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS] = {
.type = QEMU_MIGRATION_PARAM_TYPE_INT,
},
+ [QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION] = {
+ .type = QEMU_MIGRATION_PARAM_TYPE_STRING,
+ },
+ [QEMU_MIGRATION_PARAM_MULTIFD_ZLIB_LEVEL] = {
+ .type = QEMU_MIGRATION_PARAM_TYPE_INT,
+ },
+ [QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL] = {
+ .type = QEMU_MIGRATION_PARAM_TYPE_INT,
+ },
};
G_STATIC_ASSERT(G_N_ELEMENTS(qemuMigrationParamInfo) == QEMU_MIGRATION_PARAM_LAST);
@@ -504,8 +528,6 @@ qemuMigrationParamsSetTPString(qemuMigrationParams *migParams,
migParams->params[param].value.s);
}
-
-
static int
qemuMigrationParamsSetCompression(virTypedParameterPtr params,
int nparams,
@@ -520,6 +542,13 @@ qemuMigrationParamsSetCompression(virTypedParameterPtr params,
if (STRNEQ(params[i].field, VIR_MIGRATE_PARAM_COMPRESSION))
continue;
+ if (migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].set) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Only one compression method could be specified with "
+ "parallel compression"));
+ return -1;
+ }
+
method = qemuMigrationCompressMethodTypeFromString(params[i].value.s);
if (method < 0) {
virReportError(VIR_ERR_INVALID_ARG,
@@ -535,15 +564,43 @@ qemuMigrationParamsSetCompression(virTypedParameterPtr params,
return -1;
}
+ if ((method == QEMU_MIGRATION_COMPRESS_MT ||
+ method == QEMU_MIGRATION_COMPRESS_XBZRLE) &&
+ flags & VIR_MIGRATE_PARALLEL) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("Compression method '%s' isn't supported with parallel migration"),
+ params[i].value.s);
+ return -1;
+ }
+
+ if ((method == QEMU_MIGRATION_COMPRESS_ZLIB ||
+ method == QEMU_MIGRATION_COMPRESS_ZSTD) &&
+ flags & VIR_MIGRATE_COMPRESSED) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("Compression method '%s' isn't supported with compress migration"),
+ params[i].value.s);
+ return -1;
+ }
+
migParams->compMethods |= 1ULL << method;
switch ((qemuMigrationCompressMethod) method) {
case QEMU_MIGRATION_COMPRESS_XBZRLE:
cap = QEMU_MIGRATION_CAP_XBZRLE;
+ flags |= VIR_MIGRATE_COMPRESSED;
break;
case QEMU_MIGRATION_COMPRESS_MT:
cap = QEMU_MIGRATION_CAP_COMPRESS;
+ flags |= VIR_MIGRATE_COMPRESSED;
+ break;
+
+ case QEMU_MIGRATION_COMPRESS_ZLIB:
+ case QEMU_MIGRATION_COMPRESS_ZSTD:
+ flags |= VIR_MIGRATE_PARALLEL;
+ cap = QEMU_MIGRATION_CAP_MULTIFD;
+ migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].value.s = g_strdup(params[i].value.s);
+ migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].set = true;
break;
case QEMU_MIGRATION_COMPRESS_LAST:
@@ -569,6 +626,20 @@ qemuMigrationParamsSetCompression(virTypedParameterPtr params,
return -1;
}
+ if (migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_ZLIB_LEVEL].set &&
+ !(migParams->compMethods & (1ULL << QEMU_MIGRATION_COMPRESS_ZLIB))) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Turn zlib compression on to tune it"));
+ return -1;
+ }
+
+ if (migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL].set &&
+ !(migParams->compMethods & (1ULL << QEMU_MIGRATION_COMPRESS_ZSTD))) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Turn zstd compression on to tune it"));
+ return -1;
+ }
+
if (!migParams->compMethods && (flags & VIR_MIGRATE_COMPRESSED)) {
migParams->compMethods = 1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE;
ignore_value(virBitmapSetBit(migParams->caps,
@@ -690,6 +761,11 @@ qemuMigrationParamsDump(qemuMigrationParams *migParams,
*flags |= VIR_MIGRATE_COMPRESSED;
}
+ if (migParams->compMethods == 1ULL << QEMU_MIGRATION_COMPRESS_ZLIB ||
+ migParams->compMethods == 1ULL << QEMU_MIGRATION_COMPRESS_ZSTD) {
+ *flags |= VIR_MIGRATE_PARALLEL;
+ }
+
for (i = 0; i < QEMU_MIGRATION_COMPRESS_LAST; ++i) {
if ((migParams->compMethods & (1ULL << i)) &&
virTypedParamsAddString(params, nparams, maxparams,
diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h
index e7c65f6a21..5857673227 100644
--- a/src/qemu/qemu_migration_params.h
+++ b/src/qemu/qemu_migration_params.h
@@ -59,6 +59,9 @@ typedef enum {
QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE,
QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH,
QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS,
+ QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION,
+ QEMU_MIGRATION_PARAM_MULTIFD_ZLIB_LEVEL,
+ QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL,
QEMU_MIGRATION_PARAM_LAST
} qemuMigrationParam;
--
2.33.0
On Fri, Feb 24, 2023 at 17:27:12 +0800, Jiang Jiacheng wrote:
> Add new compress methods zlib and zstd for parallel migration,
> these method should be used with migration option --comp-methods
> and will be processed in 'qemuMigrationParamsSetCompression'.
> Note that only one compress method could be chosen for parallel
> migration and they cann't be used in compress migration.
>
> Signed-off-by: Jiang Jiacheng <jiangjiacheng@huawei.com>
> ---
> src/qemu/qemu_migration.h | 2 +
> src/qemu/qemu_migration_params.c | 80 +++++++++++++++++++++++++++++++-
> src/qemu/qemu_migration_params.h | 3 ++
> 3 files changed, 83 insertions(+), 2 deletions(-)
>
...
> diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
> index bd09dcfb23..3c224131c5 100644
> --- a/src/qemu/qemu_migration_params.c
> +++ b/src/qemu/qemu_migration_params.c
...
> @@ -504,8 +528,6 @@ qemuMigrationParamsSetTPString(qemuMigrationParams *migParams,
> migParams->params[param].value.s);
> }
>
> -
> -
Spurious whitespace change.
> static int
> qemuMigrationParamsSetCompression(virTypedParameterPtr params,
> int nparams,
> @@ -520,6 +542,13 @@ qemuMigrationParamsSetCompression(virTypedParameterPtr params,
> if (STRNEQ(params[i].field, VIR_MIGRATE_PARAM_COMPRESSION))
> continue;
>
> + if (migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].set) {
> + virReportError(VIR_ERR_INVALID_ARG, "%s",
> + _("Only one compression method could be specified with "
> + "parallel compression"));
The error message should all be on a single line. And I'd move this
check a bit further below the two new compatibility checks: [1].
> + return -1;
> + }
> +
> method = qemuMigrationCompressMethodTypeFromString(params[i].value.s);
> if (method < 0) {
> virReportError(VIR_ERR_INVALID_ARG,
> @@ -535,15 +564,43 @@ qemuMigrationParamsSetCompression(virTypedParameterPtr params,
> return -1;
> }
>
> + if ((method == QEMU_MIGRATION_COMPRESS_MT ||
> + method == QEMU_MIGRATION_COMPRESS_XBZRLE) &&
> + flags & VIR_MIGRATE_PARALLEL) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("Compression method '%s' isn't supported with parallel migration"),
Recent changes (made after you sent this patch) require %1$s format
string to be used instead of %s
> + params[i].value.s);
> + return -1;
> + }
> +
> + if ((method == QEMU_MIGRATION_COMPRESS_ZLIB ||
> + method == QEMU_MIGRATION_COMPRESS_ZSTD) &&
> + flags & VIR_MIGRATE_COMPRESSED) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("Compression method '%s' isn't supported with compress migration"),
> + params[i].value.s);
> + return -1;
> + }
> +
[1]
> migParams->compMethods |= 1ULL << method;
>
> switch ((qemuMigrationCompressMethod) method) {
> case QEMU_MIGRATION_COMPRESS_XBZRLE:
> cap = QEMU_MIGRATION_CAP_XBZRLE;
> + flags |= VIR_MIGRATE_COMPRESSED;
We do not magically enable flags based on other flags. We just report an
error if the required flag is not set.
> break;
>
> case QEMU_MIGRATION_COMPRESS_MT:
> cap = QEMU_MIGRATION_CAP_COMPRESS;
> + flags |= VIR_MIGRATE_COMPRESSED;
The same here.
> + break;
> +
> + case QEMU_MIGRATION_COMPRESS_ZLIB:
> + case QEMU_MIGRATION_COMPRESS_ZSTD:
> + flags |= VIR_MIGRATE_PARALLEL;
> + cap = QEMU_MIGRATION_CAP_MULTIFD;
And same here (for both flags and cap);
> + migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].value.s = g_strdup(params[i].value.s);
> + migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].set = true;
> break;
>
> case QEMU_MIGRATION_COMPRESS_LAST:
> @@ -569,6 +626,20 @@ qemuMigrationParamsSetCompression(virTypedParameterPtr params,
> return -1;
> }
>
> + if (migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_ZLIB_LEVEL].set &&
> + !(migParams->compMethods & (1ULL << QEMU_MIGRATION_COMPRESS_ZLIB))) {
> + virReportError(VIR_ERR_INVALID_ARG, "%s",
> + _("Turn zlib compression on to tune it"));
> + return -1;
> + }
> +
> + if (migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL].set &&
> + !(migParams->compMethods & (1ULL << QEMU_MIGRATION_COMPRESS_ZSTD))) {
> + virReportError(VIR_ERR_INVALID_ARG, "%s",
> + _("Turn zstd compression on to tune it"));
> + return -1;
> + }
> +
The idea was to consistently use
--compressed --comp-method=... --comp-...-...
regardless on selected compression method or whether parallel migration
is turned on or not. Specifically,
--parallel --compressed --comp-method=zlib --comp-zlib-...
--parallel --compressed --comp-method=zstd --comp-zstd-...
--compressed --comp-method=mt --comp-mt-...
--compressed --comp-method=xbzrle,mt --comp-xbzrle-... --comp-mt-...
--compressed
are all ok, while
--compressed --comp-method=zlib
--compressed --comp-method=zstd
should report an error about missing --parallel option and
--parallel --compressed --comp-method=xbzrle
--parallel --compressed --comp-method=mt
should report an error saying the selected method cannot be used with
parallel migration.
Actually looking at the current code (confirmed also by an experiment)
the --compressed parameter is not required. It's mostly a shortcut for a
default method, which is xbzrle for non-parallel migration. The default
for parallel migration is documented as "no compression", which would
mean
--parallel --compressed
is equivalent to
--parallel
I think it would be better to just forbid --compressed with --parallel
unless there is a compression method specified with --comp-method to
avoid a strange semantics of --compressed not providing any compression
at all.
> if (!migParams->compMethods && (flags & VIR_MIGRATE_COMPRESSED)) {
> migParams->compMethods = 1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE;
> ignore_value(virBitmapSetBit(migParams->caps,
> @@ -690,6 +761,11 @@ qemuMigrationParamsDump(qemuMigrationParams *migParams,
> *flags |= VIR_MIGRATE_COMPRESSED;
> }
>
> + if (migParams->compMethods == 1ULL << QEMU_MIGRATION_COMPRESS_ZLIB ||
> + migParams->compMethods == 1ULL << QEMU_MIGRATION_COMPRESS_ZSTD) {
> + *flags |= VIR_MIGRATE_PARALLEL;
> + }
> +
This is not needed as the VIR_MIGRATE_PARALLEL flag has to be set
explicitly.
> for (i = 0; i < QEMU_MIGRATION_COMPRESS_LAST; ++i) {
> if ((migParams->compMethods & (1ULL << i)) &&
> virTypedParamsAddString(params, nparams, maxparams,
> diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h
> index e7c65f6a21..5857673227 100644
> --- a/src/qemu/qemu_migration_params.h
> +++ b/src/qemu/qemu_migration_params.h
> @@ -59,6 +59,9 @@ typedef enum {
> QEMU_MIGRATION_PARAM_XBZRLE_CACHE_SIZE,
> QEMU_MIGRATION_PARAM_MAX_POSTCOPY_BANDWIDTH,
> QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS,
> + QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION,
> + QEMU_MIGRATION_PARAM_MULTIFD_ZLIB_LEVEL,
> + QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL,
>
> QEMU_MIGRATION_PARAM_LAST
> } qemuMigrationParam;
With the following suggested changes
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
index ee23cec23d..807cccd86e 100644
--- a/src/qemu/qemu_migration_params.c
+++ b/src/qemu/qemu_migration_params.c
@@ -528,6 +528,8 @@ qemuMigrationParamsSetTPString(qemuMigrationParams *migParams,
migParams->params[param].value.s);
}
+
+
static int
qemuMigrationParamsSetCompression(virTypedParameterPtr params,
int nparams,
@@ -536,19 +538,11 @@ qemuMigrationParamsSetCompression(virTypedParameterPtr params,
{
size_t i;
int method;
- qemuMigrationCapability cap;
for (i = 0; i < nparams; i++) {
if (STRNEQ(params[i].field, VIR_MIGRATE_PARAM_COMPRESSION))
continue;
- if (migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].set) {
- virReportError(VIR_ERR_INVALID_ARG, "%s",
- _("Only one compression method could be specified with "
- "parallel compression"));
- return -1;
- }
-
method = qemuMigrationCompressMethodTypeFromString(params[i].value.s);
if (method < 0) {
virReportError(VIR_ERR_INVALID_ARG,
@@ -568,46 +562,47 @@ qemuMigrationParamsSetCompression(virTypedParameterPtr params,
method == QEMU_MIGRATION_COMPRESS_XBZRLE) &&
flags & VIR_MIGRATE_PARALLEL) {
virReportError(VIR_ERR_INVALID_ARG,
- _("Compression method '%s' isn't supported with parallel migration"),
+ _("Compression method '%1$s' isn't supported with parallel migration"),
params[i].value.s);
return -1;
}
if ((method == QEMU_MIGRATION_COMPRESS_ZLIB ||
method == QEMU_MIGRATION_COMPRESS_ZSTD) &&
- flags & VIR_MIGRATE_COMPRESSED) {
+ !(flags & VIR_MIGRATE_PARALLEL)) {
virReportError(VIR_ERR_INVALID_ARG,
- _("Compression method '%s' isn't supported with compress migration"),
+ _("Compression method '%1$s' is only supported with parallel migration"),
params[i].value.s);
return -1;
}
+ if (migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].set) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Only one compression method could be specified with parallel compression"));
+ return -1;
+ }
+
migParams->compMethods |= 1ULL << method;
switch ((qemuMigrationCompressMethod) method) {
case QEMU_MIGRATION_COMPRESS_XBZRLE:
- cap = QEMU_MIGRATION_CAP_XBZRLE;
- flags |= VIR_MIGRATE_COMPRESSED;
+ ignore_value(virBitmapSetBit(migParams->caps, QEMU_MIGRATION_CAP_XBZRLE));
break;
case QEMU_MIGRATION_COMPRESS_MT:
- cap = QEMU_MIGRATION_CAP_COMPRESS;
- flags |= VIR_MIGRATE_COMPRESSED;
+ ignore_value(virBitmapSetBit(migParams->caps, QEMU_MIGRATION_CAP_COMPRESS));
break;
case QEMU_MIGRATION_COMPRESS_ZLIB:
case QEMU_MIGRATION_COMPRESS_ZSTD:
- flags |= VIR_MIGRATE_PARALLEL;
- cap = QEMU_MIGRATION_CAP_MULTIFD;
migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].value.s = g_strdup(params[i].value.s);
migParams->params[QEMU_MIGRATION_PARAM_MULTIFD_COMPRESSION].set = true;
break;
case QEMU_MIGRATION_COMPRESS_LAST:
default:
- continue;
+ break;
}
- ignore_value(virBitmapSetBit(migParams->caps, cap));
}
if ((migParams->params[QEMU_MIGRATION_PARAM_COMPRESS_LEVEL].set ||
@@ -641,6 +636,12 @@ qemuMigrationParamsSetCompression(virTypedParameterPtr params,
}
if (!migParams->compMethods && (flags & VIR_MIGRATE_COMPRESSED)) {
+ if (flags & VIR_MIGRATE_PARALLEL) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("No compression algorithm selected for parallel migration"));
+ return -1;
+ }
+
migParams->compMethods = 1ULL << QEMU_MIGRATION_COMPRESS_XBZRLE;
ignore_value(virBitmapSetBit(migParams->caps,
QEMU_MIGRATION_CAP_XBZRLE));
@@ -761,11 +762,6 @@ qemuMigrationParamsDump(qemuMigrationParams *migParams,
*flags |= VIR_MIGRATE_COMPRESSED;
}
- if (migParams->compMethods == 1ULL << QEMU_MIGRATION_COMPRESS_ZLIB ||
- migParams->compMethods == 1ULL << QEMU_MIGRATION_COMPRESS_ZSTD) {
- *flags |= VIR_MIGRATE_PARALLEL;
- }
-
for (i = 0; i < QEMU_MIGRATION_COMPRESS_LAST; ++i) {
if ((migParams->compMethods & (1ULL << i)) &&
virTypedParamsAddString(params, nparams, maxparams,
© 2016 - 2026 Red Hat, Inc.