Add support for parallel save and restore by mapping libvirt's
"parallel-connections" parameter to QEMU's "multifd-channels"
migration parameter.
Signed-off-by: Jim Fehlig <jfehlig(a)suse.com>
---
src/qemu/qemu_driver.c | 32 +++++++++++++++++++++-----------
src/qemu/qemu_migration_params.c | 31 +++++++++++++++++++++++++++++--
src/qemu/qemu_migration_params.h | 5 ++++-
3 files changed, 54 insertions(+), 14 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 803c7be3f7..4d8f5f08c3 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2611,6 +2611,8 @@ qemuDomainSaveInternal(virQEMUDriver *driver,
int format,
virCommand *compressor,
const char *xmlin,
+ virTypedParameterPtr params,
+ int nparams,
unsigned int flags)
{
g_autofree char *xml = NULL;
@@ -2700,7 +2702,8 @@ qemuDomainSaveInternal(virQEMUDriver *driver,
goto endjob;
xml = NULL;
- if (!(saveParams = qemuMigrationParamsForSave(format == QEMU_SAVE_FORMAT_SPARSE,
+ if (!(saveParams = qemuMigrationParamsForSave(params, nparams,
+ format == QEMU_SAVE_FORMAT_SPARSE,
flags)))
goto endjob;
@@ -2787,7 +2790,7 @@ qemuDomainManagedSaveHelper(virQEMUDriver *driver,
VIR_INFO("Saving state of domain '%s' to '%s'",
vm->def->name, path);
if (qemuDomainSaveInternal(driver, vm, path, format,
- compressor, dxml, flags) < 0)
+ compressor, dxml, NULL, 0, flags) < 0)
return -1;
vm->hasManagedSave = true;
@@ -2826,7 +2829,7 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char
*dxml,
goto cleanup;
ret = qemuDomainSaveInternal(driver, vm, path, format,
- compressor, dxml, flags);
+ compressor, dxml, NULL, 0, flags);
cleanup:
virDomainObjEndAPI(&vm);
@@ -2856,13 +2859,16 @@ qemuDomainSaveParams(virDomainPtr dom,
virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
VIR_DOMAIN_SAVE_RUNNING |
- VIR_DOMAIN_SAVE_PAUSED, -1);
+ VIR_DOMAIN_SAVE_PAUSED |
+ VIR_DOMAIN_SAVE_PARALLEL, -1);
if (virTypedParamsValidate(params, nparams,
VIR_DOMAIN_SAVE_PARAM_FILE,
VIR_TYPED_PARAM_STRING,
VIR_DOMAIN_SAVE_PARAM_DXML,
VIR_TYPED_PARAM_STRING,
+ VIR_DOMAIN_SAVE_PARAM_PARALLEL_CHANNELS,
+ VIR_TYPED_PARAM_INT,
NULL) < 0)
return -1;
@@ -2894,7 +2900,7 @@ qemuDomainSaveParams(virDomainPtr dom,
goto cleanup;
ret = qemuDomainSaveInternal(driver, vm, to, format,
- compressor, dxml, flags);
+ compressor, dxml, params, nparams, flags);
cleanup:
virDomainObjEndAPI(&vm);
@@ -5769,6 +5775,8 @@ static int
qemuDomainRestoreInternal(virConnectPtr conn,
const char *path,
const char *dxml,
+ virTypedParameterPtr params,
+ int nparams,
unsigned int flags,
int (*ensureACL)(virConnectPtr, virDomainDef *))
{
@@ -5790,7 +5798,8 @@ qemuDomainRestoreInternal(virConnectPtr conn,
virCheckFlags(VIR_DOMAIN_SAVE_BYPASS_CACHE |
VIR_DOMAIN_SAVE_RUNNING |
VIR_DOMAIN_SAVE_PAUSED |
- VIR_DOMAIN_SAVE_RESET_NVRAM, -1);
+ VIR_DOMAIN_SAVE_RESET_NVRAM |
+ VIR_DOMAIN_SAVE_PARALLEL, -1);
if (flags & VIR_DOMAIN_SAVE_RESET_NVRAM)
reset_nvram = true;
@@ -5799,7 +5808,7 @@ qemuDomainRestoreInternal(virConnectPtr conn,
goto cleanup;
sparse = data->header.format == QEMU_SAVE_FORMAT_SPARSE;
- if (!(restoreParams = qemuMigrationParamsForSave(sparse, flags)))
+ if (!(restoreParams = qemuMigrationParamsForSave(params, nparams, sparse, flags)))
goto cleanup;
fd = qemuSaveImageOpen(driver, path,
@@ -5881,7 +5890,7 @@ qemuDomainRestoreFlags(virConnectPtr conn,
const char *dxml,
unsigned int flags)
{
- return qemuDomainRestoreInternal(conn, path, dxml, flags,
+ return qemuDomainRestoreInternal(conn, path, dxml, NULL, 0, flags,
virDomainRestoreFlagsEnsureACL);
}
@@ -5889,7 +5898,7 @@ static int
qemuDomainRestore(virConnectPtr conn,
const char *path)
{
- return qemuDomainRestoreInternal(conn, path, NULL, 0,
+ return qemuDomainRestoreInternal(conn, path, NULL, NULL, 0, 0,
virDomainRestoreEnsureACL);
}
@@ -5905,6 +5914,7 @@ qemuDomainRestoreParams(virConnectPtr conn,
if (virTypedParamsValidate(params, nparams,
VIR_DOMAIN_SAVE_PARAM_FILE, VIR_TYPED_PARAM_STRING,
VIR_DOMAIN_SAVE_PARAM_DXML, VIR_TYPED_PARAM_STRING,
+ VIR_DOMAIN_SAVE_PARAM_PARALLEL_CHANNELS,
VIR_TYPED_PARAM_INT,
NULL) < 0)
return -1;
@@ -5921,7 +5931,7 @@ qemuDomainRestoreParams(virConnectPtr conn,
return -1;
}
- ret = qemuDomainRestoreInternal(conn, path, dxml, flags,
+ ret = qemuDomainRestoreInternal(conn, path, dxml, params, nparams, flags,
virDomainRestoreParamsEnsureACL);
return ret;
}
@@ -6125,7 +6135,7 @@ qemuDomainObjRestore(virConnectPtr conn,
}
sparse = data->header.format == QEMU_SAVE_FORMAT_SPARSE;
- if (!(restoreParams = qemuMigrationParamsForSave(sparse,
+ if (!(restoreParams = qemuMigrationParamsForSave(NULL, 0, sparse,
bypass_cache ?
VIR_DOMAIN_SAVE_BYPASS_CACHE : 0)))
return -1;
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c
index 79b47333f9..420bf2fdbe 100644
--- a/src/qemu/qemu_migration_params.c
+++ b/src/qemu/qemu_migration_params.c
@@ -788,10 +788,19 @@ qemuMigrationParamsFromFlags(virTypedParameterPtr params,
qemuMigrationParams *
-qemuMigrationParamsForSave(bool sparse, unsigned int flags)
+qemuMigrationParamsForSave(virTypedParameterPtr params,
+ int nparams,
+ bool sparse,
+ unsigned int flags)
{
g_autoptr(qemuMigrationParams) saveParams = NULL;
+ if (flags & VIR_DOMAIN_SAVE_PARALLEL && !sparse) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("Parallel save is only supported with the 'sparse'
save image format"));
+ return NULL;
+ }
+
if (!(saveParams = qemuMigrationParamsNew()))
return NULL;
@@ -800,7 +809,25 @@ qemuMigrationParamsForSave(bool sparse, unsigned int flags)
return NULL;
if (virBitmapSetBit(saveParams->caps, QEMU_MIGRATION_CAP_MULTIFD) < 0)
return NULL;
- saveParams->params[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS].value.i = 1;
+
+ if (flags & VIR_DOMAIN_SAVE_PARALLEL) {
+ int nchannels;
+
+ if (params && virTypedParamsGetInt(params, nparams,
+ VIR_DOMAIN_SAVE_PARAM_PARALLEL_CHANNELS,
+ &nchannels) < 0)
+ return NULL;
+
+ if (nchannels < 1) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("number of parallel save channels cannot be less
than 1"));
+ return NULL;
+ }
+
+ saveParams->params[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS].value.i =
nchannels;
+ } else {
+ saveParams->params[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS].value.i = 1;
+ }
saveParams->params[QEMU_MIGRATION_PARAM_MULTIFD_CHANNELS].set = true;
if (flags & VIR_DOMAIN_SAVE_BYPASS_CACHE) {
diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h
index b326aa5bc1..b6998d67a2 100644
--- a/src/qemu/qemu_migration_params.h
+++ b/src/qemu/qemu_migration_params.h
@@ -88,7 +88,10 @@ qemuMigrationParamsFromFlags(virTypedParameterPtr params,
qemuMigrationParty party);
qemuMigrationParams *
-qemuMigrationParamsForSave(bool sparse, unsigned int flags);
+qemuMigrationParamsForSave(virTypedParameterPtr params,
+ int nparams,
+ bool sparse,
+ unsigned int flags);
int
qemuMigrationParamsDump(qemuMigrationParams *migParams,
--
2.43.0