Hi Fiona

On Mon, Jan 12, 2026 at 2:51 PM Fiona Ebner <[email protected]> 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:
>
>
But you can migrate a pre-10.1 machine with the new binary.


> > 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.
>
>
I am not sure this is the right way to handle this. There is already this
error when migrating to an older qemu, I am not sure we have to block
earlier and prevent the above case.



> Cc: [email protected]
> Fixes: 42000e0013 ("ui/vdagent: remove migration blocker")
> Signed-off-by: Fiona Ebner <[email protected]>
> ---
>  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 6411e68856..9a5241ce17 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -55,6 +55,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" },
>

Is there a precedent where such compat property was added to block
migration?


>  };
>  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 142a3691ac..15ecabb402 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"
> @@ -32,6 +34,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;
> @@ -677,6 +683,12 @@ static void vdagent_chr_open(Chardev *chr,
>      return;
>  #endif
>
> +    if (vd->migration_blocked) {
> +        if (migrate_add_blocker(&vd->migration_blocker, errp) != 0) {
> +            return;
> +        }
> +    }
> +
>      vd->mouse = VDAGENT_MOUSE_DEFAULT;
>      if (cfg->has_mouse) {
>          vd->mouse = cfg->mouse;
> @@ -920,6 +932,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);
> @@ -929,6 +954,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)
> @@ -1083,10 +1112,26 @@ static void vdagent_chr_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);
> @@ -1099,6 +1144,7 @@ static const TypeInfo vdagent_chr_type_info = {
>      .parent = TYPE_CHARDEV,
>      .instance_size = sizeof(VDAgentChardev),
>      .instance_init = vdagent_chr_init,
> +    .instance_post_init = vdagent_post_init,
>      .instance_finalize = vdagent_chr_fini,
>      .class_init = vdagent_chr_class_init,
>  };
> --
> 2.47.3
>
>
>

Reply via email to