On Fri, Jul 25, 2025 at 4:22 PM Arun Menon <armenon@redhat.com> wrote:
> This is an incremental step in converting vmstate loading
> code to report error via Error objects instead of directly
> printing it to console/monitor.
> postcopy_ram_listen_thread() calls qemu_loadvm_state_main()
> to load the vm, and in case of a failure, it should set the error
> in the migration object.
>
> When postcopy live migration runs, the device states are loaded by
> both the qemu coroutine process_incoming_migration_co() and the
> postcopy_ram_listen_thread(). Therefore, it is important that the
> coroutine also reports the error in case of failure, with
> error_report_err(). Otherwise, the source qemu will not display
> any errors before going into the postcopy pause state.
>
> Signed-off-by: Arun Menon <armenon@redhat.com>
>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> migration/migration.c | 2 +-
> migration/savevm.c | 10 ++++++++--
> 2 files changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/migration/migration.c b/migration/migration.c
> index
> 0a5a8d5948b2b0a3f85163795e84f71903870d25..4a76d7ed730589bae87115368b0bf4819f8b161e
> 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -925,7 +925,7 @@ fail:
> migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
> MIGRATION_STATUS_FAILED);
> migrate_set_error(s, local_err);
> - error_free(local_err);
> + error_report_err(local_err);
>
> migration_incoming_state_destroy();
>
> diff --git a/migration/savevm.c b/migration/savevm.c
> index
> 810bba9799246c8d57514be0927bb474edee8e9b..202bb9f494c9185434a50967c439ce84e0b3acee
> 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -2095,6 +2095,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
> QEMUFile *f = mis->from_src_file;
> int load_res;
> MigrationState *migr = migrate_get_current();
> + Error *local_err = NULL;
>
> object_ref(OBJECT(migr));
>
> @@ -2111,7 +2112,7 @@ static void *postcopy_ram_listen_thread(void *opaque)
> qemu_file_set_blocking(f, true);
>
> /* TODO: sanity check that only postcopiable data will be loaded here
> */
> - load_res = qemu_loadvm_state_main(f, mis, NULL);
> + load_res = qemu_loadvm_state_main(f, mis, &local_err);
>
> /*
> * This is tricky, but, mis->from_src_file can change after it
> @@ -2137,7 +2138,12 @@ static void *postcopy_ram_listen_thread(void
> *opaque)
> __func__, load_res);
> load_res = 0; /* prevent further exit() */
> } else {
> - error_report("%s: loadvm failed: %d", __func__, load_res);
> + if (local_err != NULL) {
> + error_prepend(&local_err,
> + "loadvm failed during postcopy: %d: ",
> load_res);
> + migrate_set_error(migr, local_err);
> + error_report_err(local_err);
> + }
> migrate_set_state(&mis->state,
> MIGRATION_STATUS_POSTCOPY_ACTIVE,
> MIGRATION_STATUS_FAILED);
> }
>
> --
> 2.50.0
>
>