hw/core/machine.c | 1 + ui/vdagent.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+)
In QEMU 10.1, commit 5d56bff11e ("ui/vdagent: add migration support")
added migration support for the vdagent chardev and commit 42000e0013
("ui/vdagent: remove migration blocker") removed the migration
blocker. No compat for older machine versions was added, so migration
with pre-10.1 machine version, from a 10.1 binary to a pre-10.1 binary
will result in a failure when loading the VM state in the target
instance:
> Unknown savevm section or instance 'vdagent' 0. Make sure that your
> current VM setup matches your saved VM setup, including any
> hotplugged devices
Add a compat flag to block migration when the machine version is less
than 10.1 to avoid this.
Cc: qemu-stable@nongnu.org
Fixes: 42000e0013 ("ui/vdagent: remove migration blocker")
Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
---
Changes in v2:
* rebase on current master, adapting to commit 8c84f31ace
("chardev: .chr_open(): add boolean return value")
hw/core/machine.c | 1 +
ui/vdagent.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index a14ad05b9a..6cf0e2f404 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -57,6 +57,7 @@ GlobalProperty hw_compat_10_0[] = {
{ "vfio-pci", "x-migration-load-config-after-iter", "off" },
{ "ramfb", "use-legacy-x86-rom", "true"},
{ "vfio-pci-nohotplug", "use-legacy-x86-rom", "true" },
+ { "chardev-qemu-vdagent", "x-migration-blocked", "true" },
};
const size_t hw_compat_10_0_len = G_N_ELEMENTS(hw_compat_10_0);
diff --git a/ui/vdagent.c b/ui/vdagent.c
index 5a5e4bf681..bb0c4aa14c 100644
--- a/ui/vdagent.c
+++ b/ui/vdagent.c
@@ -6,6 +6,8 @@
#include "qemu/option.h"
#include "qemu/units.h"
#include "hw/core/qdev.h"
+#include "hw/core/qdev-properties.h"
+#include "migration/blocker.h"
#include "ui/clipboard.h"
#include "ui/console.h"
#include "ui/input.h"
@@ -24,6 +26,10 @@
struct VDAgentChardev {
Chardev parent;
+ /* needed for machine versions < 10.1 when migration was not supported */
+ Error *migration_blocker;
+ bool migration_blocked;
+
/* config */
bool mouse;
bool clipboard;
@@ -657,6 +663,12 @@ static bool vdagent_chr_open(Chardev *chr, ChardevBackend *backend,
return false;
#endif
+ if (vd->migration_blocked) {
+ if (migrate_add_blocker(&vd->migration_blocker, errp) != 0) {
+ return false;
+ }
+ }
+
vd->mouse = VDAGENT_MOUSE_DEFAULT;
if (cfg->has_mouse) {
vd->mouse = cfg->mouse;
@@ -901,6 +913,19 @@ static void vdagent_chr_parse(QemuOpts *opts, ChardevBackend *backend,
/* ------------------------------------------------------------------ */
+static bool get_migration_blocked(Object *o, Error **errp)
+{
+ VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(o);
+ return vd->migration_blocked;
+}
+
+static void set_migration_blocked(Object *o, bool migration_blocked,
+ Error **errp)
+{
+ VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(o);
+ vd->migration_blocked = migration_blocked;
+}
+
static void vdagent_chr_class_init(ObjectClass *oc, const void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
@@ -910,6 +935,10 @@ static void vdagent_chr_class_init(ObjectClass *oc, const void *data)
cc->chr_write = vdagent_chr_write;
cc->chr_set_fe_open = vdagent_chr_set_fe_open;
cc->chr_accept_input = vdagent_chr_accept_input;
+
+ object_class_property_add_bool(oc, "x-migration-blocked",
+ get_migration_blocked,
+ set_migration_blocked);
}
static int post_load(void *opaque, int version_id)
@@ -1064,10 +1093,26 @@ static void vdagent_chr_instance_init(Object *obj)
vmstate_register_any(NULL, &vmstate_vdagent, vd);
}
+static void vdagent_post_init(Object *obj)
+{
+ VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj);
+
+ object_apply_compat_props(obj);
+
+ if (vd->migration_blocked) {
+ error_setg(&vd->migration_blocker,
+ "The vdagent chardev doesn't support migration with machine"
+ " version less than 10.1");
+ }
+}
+
static void vdagent_chr_fini(Object *obj)
{
VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj);
+ if (vd->migration_blocked) {
+ migrate_del_blocker(&vd->migration_blocker);
+ }
vdagent_disconnect(vd);
if (vd->mouse_hs) {
qemu_input_handler_unregister(vd->mouse_hs);
@@ -1080,6 +1125,7 @@ static const TypeInfo vdagent_chr_type_info = {
.parent = TYPE_CHARDEV,
.instance_size = sizeof(VDAgentChardev),
.instance_init = vdagent_chr_instance_init,
+ .instance_post_init = vdagent_post_init,
.instance_finalize = vdagent_chr_fini,
.class_init = vdagent_chr_class_init,
};
--
2.47.3
Fiona Ebner <f.ebner@proxmox.com> writes:
> In QEMU 10.1, commit 5d56bff11e ("ui/vdagent: add migration support")
> added migration support for the vdagent chardev and commit 42000e0013
> ("ui/vdagent: remove migration blocker") removed the migration
> blocker. No compat for older machine versions was added, so migration
> with pre-10.1 machine version, from a 10.1 binary to a pre-10.1 binary
> will result in a failure when loading the VM state in the target
> instance:
>
>> Unknown savevm section or instance 'vdagent' 0. Make sure that your
>> current VM setup matches your saved VM setup, including any
>> hotplugged devices
>
> Add a compat flag to block migration when the machine version is less
> than 10.1 to avoid this.
>
> Cc: qemu-stable@nongnu.org
> Fixes: 42000e0013 ("ui/vdagent: remove migration blocker")
> Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Hi
On Tue, Mar 10, 2026 at 6:27 PM Fiona Ebner <f.ebner@proxmox.com> wrote:
>
> In QEMU 10.1, commit 5d56bff11e ("ui/vdagent: add migration support")
> added migration support for the vdagent chardev and commit 42000e0013
> ("ui/vdagent: remove migration blocker") removed the migration
> blocker. No compat for older machine versions was added, so migration
> with pre-10.1 machine version, from a 10.1 binary to a pre-10.1 binary
> will result in a failure when loading the VM state in the target
> instance:
>
> > Unknown savevm section or instance 'vdagent' 0. Make sure that your
> > current VM setup matches your saved VM setup, including any
> > hotplugged devices
>
> Add a compat flag to block migration when the machine version is less
> than 10.1 to avoid this.
>
> Cc: qemu-stable@nongnu.org
> Fixes: 42000e0013 ("ui/vdagent: remove migration blocker")
> Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
Ah yes, I didn't think about that case!
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>
> Changes in v2:
> * rebase on current master, adapting to commit 8c84f31ace
> ("chardev: .chr_open(): add boolean return value")
>
> hw/core/machine.c | 1 +
> ui/vdagent.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 47 insertions(+)
>
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index a14ad05b9a..6cf0e2f404 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -57,6 +57,7 @@ GlobalProperty hw_compat_10_0[] = {
> { "vfio-pci", "x-migration-load-config-after-iter", "off" },
> { "ramfb", "use-legacy-x86-rom", "true"},
> { "vfio-pci-nohotplug", "use-legacy-x86-rom", "true" },
> + { "chardev-qemu-vdagent", "x-migration-blocked", "true" },
> };
> const size_t hw_compat_10_0_len = G_N_ELEMENTS(hw_compat_10_0);
>
> diff --git a/ui/vdagent.c b/ui/vdagent.c
> index 5a5e4bf681..bb0c4aa14c 100644
> --- a/ui/vdagent.c
> +++ b/ui/vdagent.c
> @@ -6,6 +6,8 @@
> #include "qemu/option.h"
> #include "qemu/units.h"
> #include "hw/core/qdev.h"
> +#include "hw/core/qdev-properties.h"
> +#include "migration/blocker.h"
> #include "ui/clipboard.h"
> #include "ui/console.h"
> #include "ui/input.h"
> @@ -24,6 +26,10 @@
> struct VDAgentChardev {
> Chardev parent;
>
> + /* needed for machine versions < 10.1 when migration was not supported */
> + Error *migration_blocker;
> + bool migration_blocked;
> +
> /* config */
> bool mouse;
> bool clipboard;
> @@ -657,6 +663,12 @@ static bool vdagent_chr_open(Chardev *chr, ChardevBackend *backend,
> return false;
> #endif
>
> + if (vd->migration_blocked) {
> + if (migrate_add_blocker(&vd->migration_blocker, errp) != 0) {
> + return false;
> + }
> + }
> +
> vd->mouse = VDAGENT_MOUSE_DEFAULT;
> if (cfg->has_mouse) {
> vd->mouse = cfg->mouse;
> @@ -901,6 +913,19 @@ static void vdagent_chr_parse(QemuOpts *opts, ChardevBackend *backend,
>
> /* ------------------------------------------------------------------ */
>
> +static bool get_migration_blocked(Object *o, Error **errp)
> +{
> + VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(o);
> + return vd->migration_blocked;
> +}
> +
> +static void set_migration_blocked(Object *o, bool migration_blocked,
> + Error **errp)
> +{
> + VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(o);
> + vd->migration_blocked = migration_blocked;
> +}
> +
> static void vdagent_chr_class_init(ObjectClass *oc, const void *data)
> {
> ChardevClass *cc = CHARDEV_CLASS(oc);
> @@ -910,6 +935,10 @@ static void vdagent_chr_class_init(ObjectClass *oc, const void *data)
> cc->chr_write = vdagent_chr_write;
> cc->chr_set_fe_open = vdagent_chr_set_fe_open;
> cc->chr_accept_input = vdagent_chr_accept_input;
> +
> + object_class_property_add_bool(oc, "x-migration-blocked",
> + get_migration_blocked,
> + set_migration_blocked);
> }
>
> static int post_load(void *opaque, int version_id)
> @@ -1064,10 +1093,26 @@ static void vdagent_chr_instance_init(Object *obj)
> vmstate_register_any(NULL, &vmstate_vdagent, vd);
> }
>
> +static void vdagent_post_init(Object *obj)
> +{
> + VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj);
> +
> + object_apply_compat_props(obj);
> +
> + if (vd->migration_blocked) {
> + error_setg(&vd->migration_blocker,
> + "The vdagent chardev doesn't support migration with machine"
> + " version less than 10.1");
> + }
> +}
> +
> static void vdagent_chr_fini(Object *obj)
> {
> VDAgentChardev *vd = QEMU_VDAGENT_CHARDEV(obj);
>
> + if (vd->migration_blocked) {
> + migrate_del_blocker(&vd->migration_blocker);
> + }
> vdagent_disconnect(vd);
> if (vd->mouse_hs) {
> qemu_input_handler_unregister(vd->mouse_hs);
> @@ -1080,6 +1125,7 @@ static const TypeInfo vdagent_chr_type_info = {
> .parent = TYPE_CHARDEV,
> .instance_size = sizeof(VDAgentChardev),
> .instance_init = vdagent_chr_instance_init,
> + .instance_post_init = vdagent_post_init,
> .instance_finalize = vdagent_chr_fini,
> .class_init = vdagent_chr_class_init,
> };
> --
> 2.47.3
>
>
>
--
Marc-André Lureau
© 2016 - 2026 Red Hat, Inc.