[PATCH v1 1/1] qemu: add support for zero-page-detection migration parameter
QEMU supports a migration parameter to determine whether zero-page checking should be performed and if yes, where it should be performed (i.e., in the main migration thread or multifd threads). Add support for this parameter in libvirt. Signed-off-by: Tejus GK <tejus.gk@nutanix.com> --- include/libvirt/libvirt-domain.h | 11 +++++++++++ src/qemu/qemu_migration.c | 1 + src/qemu/qemu_migration_params.c | 8 ++++++++ src/qemu/qemu_migration_params.h | 1 + tools/virsh-domain.c | 13 +++++++++++++ 5 files changed, 34 insertions(+) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 99208137c3..5a4875770b 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -1468,6 +1468,17 @@ typedef enum { */ # define VIR_MIGRATE_PARAM_TLS_DESTINATION "tls.destination" +/** + * VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION: + * + * virDomainMigrate* params field: zero page detection method as + * VIR_TYPED_PARAM_STRING. Supported values are 'none', 'legacy', and + * 'multifd'. + * + * Since: 12.8.0 + */ +# define VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION "zero_page_detection" + /* Domain migration. */ virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn, unsigned long flags, const char *dname, diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 4a43ab83b0..f25506e590 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -110,6 +110,7 @@ const virTypedParamValidationTemplate qemuMigrationParametersValidation[] = { { VIR_MIGRATE_PARAM_TLS_DESTINATION, VIR_TYPED_PARAM_STRING }, { VIR_MIGRATE_PARAM_DISKS_URI, VIR_TYPED_PARAM_STRING }, { VIR_MIGRATE_PARAM_BANDWIDTH_AVAIL_SWITCHOVER, VIR_TYPED_PARAM_ULLONG }, + { VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION, VIR_TYPED_PARAM_STRING}, { "", 0 } }; diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index dd47516742..7064140379 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -131,6 +131,7 @@ VIR_ENUM_IMPL(qemuMigrationParam, "multifd-zstd-level", "avail-switchover-bandwidth", "direct-io", + "zero-page-detection", ); typedef struct _qemuMigrationParamsAlwaysOnItem qemuMigrationParamsAlwaysOnItem; @@ -274,6 +275,10 @@ static const qemuMigrationParamsTPMapItem qemuMigrationParamsTPMap[] = { .unit = 1024 * 1024, /* MiB/s */ .param = QEMU_MIGRATION_PARAM_AVAIL_SWITCHOVER_BANDWIDTH, .party = QEMU_MIGRATION_SOURCE}, + + {.typedParam = VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION, + .param = QEMU_MIGRATION_PARAM_ZERO_PAGE_DETECTION, + .party = QEMU_MIGRATION_SOURCE}, }; static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = { @@ -332,6 +337,9 @@ static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = { [QEMU_MIGRATION_PARAM_DIRECT_IO] = { .type = QEMU_MIGRATION_PARAM_TYPE_BOOL, }, + [QEMU_MIGRATION_PARAM_ZERO_PAGE_DETECTION] = { + .type = QEMU_MIGRATION_PARAM_TYPE_STRING, + }, }; G_STATIC_ASSERT(G_N_ELEMENTS(qemuMigrationParamInfo) == QEMU_MIGRATION_PARAM_LAST); diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h index b7a829b85a..131fe82fc0 100644 --- a/src/qemu/qemu_migration_params.h +++ b/src/qemu/qemu_migration_params.h @@ -67,6 +67,7 @@ typedef enum { QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL, QEMU_MIGRATION_PARAM_AVAIL_SWITCHOVER_BANDWIDTH, QEMU_MIGRATION_PARAM_DIRECT_IO, + QEMU_MIGRATION_PARAM_ZERO_PAGE_DETECTION, QEMU_MIGRATION_PARAM_LAST } qemuMigrationParam; diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 2c64f19a19..519d8427bd 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -11432,6 +11432,10 @@ static const vshCmdOptDef opts_migrate[] = { .type = VSH_OT_INT, .help = N_("bandwidth (in MiB/s) available for the final phase of migration") }, + {.name = "zero-page-detection", + .type = VSH_OT_STRING, + .help = N_("zero page detection method for migration") + }, {.name = NULL} }; @@ -11733,6 +11737,15 @@ doMigrate(void *opaque) goto save_error; } + if ((rv = vshCommandOptString(ctl, cmd, "zero-page-detection", &opt)) < 0) { + goto out; + } else if (rv > 0) { + if (virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION, + opt) < 0) + goto save_error; + } + if ((rv = vshCommandOptInt(ctl, cmd, "comp-zlib-level", &intOpt)) < 0) { goto out; } else if (rv > 0) { -- 2.43.7
Ping, for reviews :) regards, tejus
On 17 Sep 2026, at 11:50 AM, Tejus GK <tejus.gk@nutanix.com> wrote:
QEMU supports a migration parameter to determine whether zero-page checking should be performed and if yes, where it should be performed (i.e., in the main migration thread or multifd threads). Add support for this parameter in libvirt.
Signed-off-by: Tejus GK <tejus.gk@nutanix.com> --- include/libvirt/libvirt-domain.h | 11 +++++++++++ src/qemu/qemu_migration.c | 1 + src/qemu/qemu_migration_params.c | 8 ++++++++ src/qemu/qemu_migration_params.h | 1 + tools/virsh-domain.c | 13 +++++++++++++ 5 files changed, 34 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 99208137c3..5a4875770b 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -1468,6 +1468,17 @@ typedef enum { */ # define VIR_MIGRATE_PARAM_TLS_DESTINATION "tls.destination"
+/** + * VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION: + * + * virDomainMigrate* params field: zero page detection method as + * VIR_TYPED_PARAM_STRING. Supported values are 'none', 'legacy', and + * 'multifd'. + * + * Since: 12.8.0 + */ +# define VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION "zero_page_detection" + /* Domain migration. */ virDomainPtr virDomainMigrate (virDomainPtr domain, virConnectPtr dconn, unsigned long flags, const char *dname, diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 4a43ab83b0..f25506e590 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -110,6 +110,7 @@ const virTypedParamValidationTemplate qemuMigrationParametersValidation[] = { { VIR_MIGRATE_PARAM_TLS_DESTINATION, VIR_TYPED_PARAM_STRING }, { VIR_MIGRATE_PARAM_DISKS_URI, VIR_TYPED_PARAM_STRING }, { VIR_MIGRATE_PARAM_BANDWIDTH_AVAIL_SWITCHOVER, VIR_TYPED_PARAM_ULLONG }, + { VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION, VIR_TYPED_PARAM_STRING}, { "", 0 } };
diff --git a/src/qemu/qemu_migration_params.c b/src/qemu/qemu_migration_params.c index dd47516742..7064140379 100644 --- a/src/qemu/qemu_migration_params.c +++ b/src/qemu/qemu_migration_params.c @@ -131,6 +131,7 @@ VIR_ENUM_IMPL(qemuMigrationParam, "multifd-zstd-level", "avail-switchover-bandwidth", "direct-io", + "zero-page-detection", );
typedef struct _qemuMigrationParamsAlwaysOnItem qemuMigrationParamsAlwaysOnItem; @@ -274,6 +275,10 @@ static const qemuMigrationParamsTPMapItem qemuMigrationParamsTPMap[] = { .unit = 1024 * 1024, /* MiB/s */ .param = QEMU_MIGRATION_PARAM_AVAIL_SWITCHOVER_BANDWIDTH, .party = QEMU_MIGRATION_SOURCE}, + + {.typedParam = VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION, + .param = QEMU_MIGRATION_PARAM_ZERO_PAGE_DETECTION, + .party = QEMU_MIGRATION_SOURCE}, };
static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = { @@ -332,6 +337,9 @@ static const qemuMigrationParamInfoItem qemuMigrationParamInfo[] = { [QEMU_MIGRATION_PARAM_DIRECT_IO] = { .type = QEMU_MIGRATION_PARAM_TYPE_BOOL, }, + [QEMU_MIGRATION_PARAM_ZERO_PAGE_DETECTION] = { + .type = QEMU_MIGRATION_PARAM_TYPE_STRING, + }, }; G_STATIC_ASSERT(G_N_ELEMENTS(qemuMigrationParamInfo) == QEMU_MIGRATION_PARAM_LAST);
diff --git a/src/qemu/qemu_migration_params.h b/src/qemu/qemu_migration_params.h index b7a829b85a..131fe82fc0 100644 --- a/src/qemu/qemu_migration_params.h +++ b/src/qemu/qemu_migration_params.h @@ -67,6 +67,7 @@ typedef enum { QEMU_MIGRATION_PARAM_MULTIFD_ZSTD_LEVEL, QEMU_MIGRATION_PARAM_AVAIL_SWITCHOVER_BANDWIDTH, QEMU_MIGRATION_PARAM_DIRECT_IO, + QEMU_MIGRATION_PARAM_ZERO_PAGE_DETECTION,
QEMU_MIGRATION_PARAM_LAST } qemuMigrationParam; diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 2c64f19a19..519d8427bd 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -11432,6 +11432,10 @@ static const vshCmdOptDef opts_migrate[] = { .type = VSH_OT_INT, .help = N_("bandwidth (in MiB/s) available for the final phase of migration") }, + {.name = "zero-page-detection", + .type = VSH_OT_STRING, + .help = N_("zero page detection method for migration") + }, {.name = NULL} };
@@ -11733,6 +11737,15 @@ doMigrate(void *opaque) goto save_error; }
+ if ((rv = vshCommandOptString(ctl, cmd, "zero-page-detection", &opt)) < 0) { + goto out; + } else if (rv > 0) { + if (virTypedParamsAddString(¶ms, &nparams, &maxparams, + VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION, + opt) < 0) + goto save_error; + } + if ((rv = vshCommandOptInt(ctl, cmd, "comp-zlib-level", &intOpt)) < 0) { goto out; } else if (rv > 0) { -- 2.43.7
On Thu, Sep 17, 2026 at 06:20:29 +0000, Tejus GK wrote:
QEMU supports a migration parameter to determine whether zero-page checking should be performed and if yes, where it should be performed (i.e., in the main migration thread or multifd threads). Add support for this parameter in libvirt.
Signed-off-by: Tejus GK <tejus.gk@nutanix.com> --- include/libvirt/libvirt-domain.h | 11 +++++++++++ src/qemu/qemu_migration.c | 1 + src/qemu/qemu_migration_params.c | 8 ++++++++ src/qemu/qemu_migration_params.h | 1 + tools/virsh-domain.c | 13 +++++++++++++ 5 files changed, 34 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 99208137c3..5a4875770b 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -1468,6 +1468,17 @@ typedef enum { */ # define VIR_MIGRATE_PARAM_TLS_DESTINATION "tls.destination"
+/** + * VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION: + * + * virDomainMigrate* params field: zero page detection method as + * VIR_TYPED_PARAM_STRING. Supported values are 'none', 'legacy', and + * 'multifd'. + * + * Since: 12.8.0 + */ +# define VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION "zero_page_detection" +
Historically zero page detection has always been performed and it was done in the main thread. Which is what is happening when this parameter is not set as QEMU defaults to "legacy". Given that the "multifd" value fallbacks to "legacy" if multifd migration is not enabled and that I can't think of a reason to disable the detection completely, I think should just always set this parameter to "multifd" when QEMU is new enough to support it. That said, if for some reason we'd want to allow users to disable zero page detection, we should do it via a boolean parameter that would select between "none" and "multifd" as there's no reason for exposing "legacy" Jirka
On 16 Oct 2026, at 6:37 PM, Jiri Denemark <jdenemar@redhat.com> wrote:
!-------------------------------------------------------------------| CAUTION: External Email
|-------------------------------------------------------------------!
On Thu, Sep 17, 2026 at 06:20:29 +0000, Tejus GK wrote:
QEMU supports a migration parameter to determine whether zero-page checking should be performed and if yes, where it should be performed (i.e., in the main migration thread or multifd threads). Add support for this parameter in libvirt.
Signed-off-by: Tejus GK <tejus.gk@nutanix.com> --- include/libvirt/libvirt-domain.h | 11 +++++++++++ src/qemu/qemu_migration.c | 1 + src/qemu/qemu_migration_params.c | 8 ++++++++ src/qemu/qemu_migration_params.h | 1 + tools/virsh-domain.c | 13 +++++++++++++ 5 files changed, 34 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 99208137c3..5a4875770b 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -1468,6 +1468,17 @@ typedef enum { */ # define VIR_MIGRATE_PARAM_TLS_DESTINATION "tls.destination"
+/** + * VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION: + * + * virDomainMigrate* params field: zero page detection method as + * VIR_TYPED_PARAM_STRING. Supported values are 'none', 'legacy', and + * 'multifd'. + * + * Since: 12.8.0 + */ +# define VIR_MIGRATE_PARAM_ZERO_PAGE_DETECTION "zero_page_detection" +
Historically zero page detection has always been performed and it was done in the main thread. Which is what is happening when this parameter is not set as QEMU defaults to "legacy". Given that the "multifd" value fallbacks to "legacy" if multifd migration is not enabled and that I can't think of a reason to disable the detection completely, I think should just always set this parameter to "multifd" when QEMU is new enough to support it.
That said, if for some reason we'd want to allow users to disable zero page detection, we should do it via a boolean parameter that would select between "none" and "multifd" as there's no reason for exposing "legacy"
Jirka
Hi Jiri, thank you for the review! I’ll respin this patch by changing the param to a boolean one instead, and send a V2 shortly. regards, tejus
participants (2)
-
Jiri Denemark -
Tejus GK