From: Fiona Ebner Date: Tue, 10 Mar 2026 14:25:39 +0000 (+0100) Subject: ui/vdagent: add migration blocker when machine version < 10.1 X-Git-Tag: v11.0.0-rc0~4^2~13 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6f23dde620efa2de1cf3c56dfb474a20d9ce876d;p=thirdparty%2Fqemu.git ui/vdagent: add migration blocker when machine version < 10.1 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 Reviewed-by: Fabiano Rosas Reviewed-by: Marc-André Lureau Message-Id: <20260310142552.240877-1-f.ebner@proxmox.com> --- diff --git a/hw/core/machine.c b/hw/core/machine.c index a14ad05b9a6..6cf0e2f404e 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 5a5e4bf6818..bb0c4aa14ca 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, };