migration: qemu_savevm_complete*() helpers

Since we use the same save_complete() hook for both precopy and postcopy,
add a set of helpers to invoke the hook() to dedup the code.

Reviewed-by: Juraj Marcin <jmarcin@redhat.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Link: https://lore.kernel.org/r/20250613140801.474264-8-peterx@redhat.com
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
This commit is contained in:
Peter Xu 2025-06-13 10:07:57 -04:00 committed by Fabiano Rosas
parent 57c43e52bd
commit 7dd95a9630

View file

@ -1484,6 +1484,38 @@ bool should_send_vmdesc(void)
return !machine->suppress_vmdesc;
}
static bool qemu_savevm_complete_exists(SaveStateEntry *se)
{
return se->ops && se->ops->save_complete;
}
/*
* Invoke the ->save_complete() if necessary.
* Returns: 0 if skip the current SE or succeeded, <0 if error happened.
*/
static int qemu_savevm_complete(SaveStateEntry *se, QEMUFile *f)
{
int ret;
if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
return 0;
}
}
trace_savevm_section_start(se->idstr, se->section_id);
save_section_header(f, se, QEMU_VM_SECTION_END);
ret = se->ops->save_complete(f, se->opaque);
trace_savevm_section_end(se->idstr, se->section_id, ret);
save_section_footer(f, se);
if (ret < 0) {
qemu_file_set_error(f, ret);
}
return ret;
}
/*
* Complete saving any postcopy-able devices.
*
@ -1493,27 +1525,13 @@ bool should_send_vmdesc(void)
void qemu_savevm_state_complete_postcopy(QEMUFile *f)
{
SaveStateEntry *se;
int ret;
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!se->ops || !se->ops->save_complete) {
if (!qemu_savevm_complete_exists(se)) {
continue;
}
if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
}
trace_savevm_section_start(se->idstr, se->section_id);
/* Section type */
qemu_put_byte(f, QEMU_VM_SECTION_END);
qemu_put_be32(f, se->section_id);
ret = se->ops->save_complete(f, se->opaque);
trace_savevm_section_end(se->idstr, se->section_id, ret);
save_section_footer(f, se);
if (ret < 0) {
qemu_file_set_error(f, ret);
if (qemu_savevm_complete(se, f) < 0) {
return;
}
}
@ -1559,7 +1577,6 @@ int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy)
{
int64_t start_ts_each, end_ts_each;
SaveStateEntry *se;
int ret;
bool multifd_device_state = multifd_device_state_supported();
if (multifd_device_state) {
@ -1580,32 +1597,25 @@ int qemu_savevm_state_complete_precopy_iterable(QEMUFile *f, bool in_postcopy)
}
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
if (!se->ops ||
(in_postcopy && se->ops->has_postcopy &&
se->ops->has_postcopy(se->opaque)) ||
!se->ops->save_complete) {
if (!qemu_savevm_complete_exists(se)) {
continue;
}
if (se->ops->is_active) {
if (!se->ops->is_active(se->opaque)) {
continue;
}
if (in_postcopy && se->ops->has_postcopy &&
se->ops->has_postcopy(se->opaque)) {
/*
* If postcopy will start soon, and if the SE supports
* postcopy, then we can skip the SE for the postcopy phase.
*/
continue;
}
start_ts_each = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
trace_savevm_section_start(se->idstr, se->section_id);
save_section_header(f, se, QEMU_VM_SECTION_END);
ret = se->ops->save_complete(f, se->opaque);
trace_savevm_section_end(se->idstr, se->section_id, ret);
save_section_footer(f, se);
if (ret < 0) {
qemu_file_set_error(f, ret);
if (qemu_savevm_complete(se, f) < 0) {
goto ret_fail_abort_threads;
}
end_ts_each = qemu_clock_get_us(QEMU_CLOCK_REALTIME);
trace_vmstate_downtime_save("iterable", se->idstr, se->instance_id,
end_ts_each - start_ts_each);
}