From: Peter Xu Date: Tue, 27 Jan 2026 18:52:49 +0000 (-0500) Subject: migration: Refactor qemu_savevm_state_setup() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b1f774767f2f4e07a1f46512e6c7915822e0546a;p=thirdparty%2Fqemu.git migration: Refactor qemu_savevm_state_setup() Split it into two smaller chunks: - Dump of early_setup VMSDs - Dump of save_setup() sections They're mutual exclusive, hence we can run two loops and do them sequentially. This will cause migration thread to loop one more time, but it should be fine when migration just started and only do it once. It's needed because we will need to reuse the early_vmsd helper later to deduplicate code elsewhere. QEMU almost sticks with qemu_savevm_state_XXX() to represent the dump of vmstates's section XXX. With that in mind, this patch renamed the original qemu_savevm_state_setup() to qemu_savevm_state_do_setup() instead. So after this patch: - qemu_savevm_state_non_iterable_early() dumps early_vmsds only, - qemu_savevm_state_setup() dumps save_setup() sections only, - qemu_savevm_state_do_setup() does all things needed during setup phase (including migration SETUP notifies) Signed-off-by: Peter Xu Reviewed-by: Fabiano Rosas Tested-by: Lukas Straub Link: https://lore.kernel.org/qemu-devel/20260127185254.3954634-20-peterx@redhat.com Signed-off-by: Fabiano Rosas --- diff --git a/migration/migration.c b/migration/migration.c index 27e4456429..f81ac21d4e 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -3540,7 +3540,7 @@ static void *migration_thread(void *opaque) } bql_lock(); - ret = qemu_savevm_state_setup(s->to_dst_file, &local_err); + ret = qemu_savevm_state_do_setup(s->to_dst_file, &local_err); bql_unlock(); qemu_savevm_wait_unplug(s, MIGRATION_STATUS_SETUP, @@ -3663,7 +3663,7 @@ static void *bg_migration_thread(void *opaque) bql_lock(); qemu_savevm_state_header(s->to_dst_file); - ret = qemu_savevm_state_setup(s->to_dst_file, &local_err); + ret = qemu_savevm_state_do_setup(s->to_dst_file, &local_err); bql_unlock(); qemu_savevm_wait_unplug(s, MIGRATION_STATUS_SETUP, diff --git a/migration/savevm.c b/migration/savevm.c index 0683a103c8..b04a21ffc9 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1367,29 +1367,33 @@ int qemu_savevm_state_prepare(Error **errp) return 0; } -int qemu_savevm_state_setup(QEMUFile *f, Error **errp) +int qemu_savevm_state_non_iterable_early(QEMUFile *f, + JSONWriter *vmdesc, + Error **errp) { - ERRP_GUARD(); - MigrationState *ms = migrate_get_current(); - JSONWriter *vmdesc = ms->vmdesc; SaveStateEntry *se; - int ret = 0; - - if (vmdesc) { - json_writer_int64(vmdesc, "page_size", qemu_target_page_size()); - json_writer_start_array(vmdesc, "devices"); - } + int ret; - trace_savevm_state_setup(); QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { if (se->vmsd && se->vmsd->early_setup) { ret = vmstate_save(f, se, vmdesc, errp); if (ret) { - break; + return ret; } - continue; } + } + + return 0; +} + +static int qemu_savevm_state_setup(QEMUFile *f, Error **errp) +{ + SaveStateEntry *se; + int ret; + + trace_savevm_state_setup(); + QTAILQ_FOREACH(se, &savevm_state.handlers, entry) { if (!se->ops || !se->ops->save_setup) { continue; } @@ -1399,14 +1403,34 @@ int qemu_savevm_state_setup(QEMUFile *f, Error **errp) } } save_section_header(f, se, QEMU_VM_SECTION_START); - ret = se->ops->save_setup(f, se->opaque, errp); save_section_footer(f, se); if (ret < 0) { - break; + return ret; } } + return 0; +} + +int qemu_savevm_state_do_setup(QEMUFile *f, Error **errp) +{ + ERRP_GUARD(); + MigrationState *ms = migrate_get_current(); + JSONWriter *vmdesc = ms->vmdesc; + int ret; + + if (vmdesc) { + json_writer_int64(vmdesc, "page_size", qemu_target_page_size()); + json_writer_start_array(vmdesc, "devices"); + } + + ret = qemu_savevm_state_non_iterable_early(f, vmdesc, errp); + if (ret) { + return ret; + } + + ret = qemu_savevm_state_setup(f, errp); if (ret) { return ret; } @@ -1826,7 +1850,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) ms->to_dst_file = f; qemu_savevm_state_header(f); - ret = qemu_savevm_state_setup(f, errp); + ret = qemu_savevm_state_do_setup(f, errp); if (ret) { goto cleanup; } diff --git a/migration/savevm.h b/migration/savevm.h index bded5e2a6c..f2750eca09 100644 --- a/migration/savevm.h +++ b/migration/savevm.h @@ -34,7 +34,7 @@ bool qemu_savevm_state_blocked(Error **errp); void qemu_savevm_non_migratable_list(strList **reasons); int qemu_savevm_state_prepare(Error **errp); -int qemu_savevm_state_setup(QEMUFile *f, Error **errp); +int qemu_savevm_state_do_setup(QEMUFile *f, Error **errp); bool qemu_savevm_state_guest_unplug_pending(void); int qemu_savevm_state_resume_prepare(MigrationState *s); void qemu_savevm_send_header(QEMUFile *f); @@ -75,7 +75,9 @@ int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis, int qemu_load_device_state(QEMUFile *f, Error **errp); int qemu_loadvm_approve_switchover(void); int qemu_savevm_state_non_iterable(QEMUFile *f); - +int qemu_savevm_state_non_iterable_early(QEMUFile *f, + JSONWriter *vmdesc, + Error **errp); bool qemu_loadvm_load_state_buffer(const char *idstr, uint32_t instance_id, char *buf, size_t len, Error **errp);