qemu/include/migration/register.h
Maciej S. Szmigiero 4e55cb3cde migration: Add MIG_CMD_SWITCHOVER_START and its load handler
This QEMU_VM_COMMAND sub-command and its switchover_start SaveVMHandler is
used to mark the switchover point in main migration stream.

It can be used to inform the destination that all pre-switchover main
migration stream data has been sent/received so it can start to process
post-switchover data that it might have received via other migration
channels like the multifd ones.

Add also the relevant MigrationState bit stream compatibility property and
its hw_compat entry.

Reviewed-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Zhang Chen <zhangckid@gmail.com> # for the COLO part
Signed-off-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
Link: https://lore.kernel.org/qemu-devel/311be6da85fc7e49a7598684d80aa631778dcbce.1741124640.git.maciej.szmigiero@oracle.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
2025-03-06 06:47:33 +01:00

320 lines
9.9 KiB
C

/*
* QEMU migration vmstate registration
*
* Copyright IBM, Corp. 2008
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
*/
#ifndef MIGRATION_REGISTER_H
#define MIGRATION_REGISTER_H
#include "hw/vmstate-if.h"
/**
* struct SaveVMHandlers: handler structure to finely control
* migration of complex subsystems and devices, such as RAM, block and
* VFIO.
*/
typedef struct SaveVMHandlers {
/* The following handlers run inside the BQL. */
/**
* @save_state
*
* Saves state section on the source using the latest state format
* version.
*
* Legacy method. Should be deprecated when all users are ported
* to VMStateDescription.
*
* @f: QEMUFile where to send the data
* @opaque: data pointer passed to register_savevm_live()
*/
void (*save_state)(QEMUFile *f, void *opaque);
/**
* @save_prepare
*
* Called early, even before migration starts, and can be used to
* perform early checks.
*
* @opaque: data pointer passed to register_savevm_live()
* @errp: pointer to Error*, to store an error if it happens.
*
* Returns zero to indicate success and negative for error
*/
int (*save_prepare)(void *opaque, Error **errp);
/**
* @save_setup
*
* Initializes the data structures on the source and transmits
* first section containing information on the device
*
* @f: QEMUFile where to send the data
* @opaque: data pointer passed to register_savevm_live()
* @errp: pointer to Error*, to store an error if it happens.
*
* Returns zero to indicate success and negative for error
*/
int (*save_setup)(QEMUFile *f, void *opaque, Error **errp);
/**
* @save_cleanup
*
* Uninitializes the data structures on the source.
* Note that this handler can be called even if save_setup
* wasn't called earlier.
*
* @opaque: data pointer passed to register_savevm_live()
*/
void (*save_cleanup)(void *opaque);
/**
* @save_live_complete_postcopy
*
* Called at the end of postcopy for all postcopyable devices.
*
* @f: QEMUFile where to send the data
* @opaque: data pointer passed to register_savevm_live()
*
* Returns zero to indicate success and negative for error
*/
int (*save_live_complete_postcopy)(QEMUFile *f, void *opaque);
/**
* @save_live_complete_precopy
*
* Transmits the last section for the device containing any
* remaining data at the end of a precopy phase. When postcopy is
* enabled, devices that support postcopy will skip this step,
* where the final data will be flushed at the end of postcopy via
* @save_live_complete_postcopy instead.
*
* @f: QEMUFile where to send the data
* @opaque: data pointer passed to register_savevm_live()
*
* Returns zero to indicate success and negative for error
*/
int (*save_live_complete_precopy)(QEMUFile *f, void *opaque);
/* This runs both outside and inside the BQL. */
/**
* @is_active
*
* Will skip a state section if not active
*
* @opaque: data pointer passed to register_savevm_live()
*
* Returns true if state section is active else false
*/
bool (*is_active)(void *opaque);
/**
* @has_postcopy
*
* Checks if a device supports postcopy
*
* @opaque: data pointer passed to register_savevm_live()
*
* Returns true for postcopy support else false
*/
bool (*has_postcopy)(void *opaque);
/**
* @is_active_iterate
*
* As #SaveVMHandlers.is_active(), will skip an inactive state
* section in qemu_savevm_state_iterate.
*
* For example, it is needed for only-postcopy-states, which needs
* to be handled by qemu_savevm_state_setup() and
* qemu_savevm_state_pending(), but do not need iterations until
* not in postcopy stage.
*
* @opaque: data pointer passed to register_savevm_live()
*
* Returns true if state section is active else false
*/
bool (*is_active_iterate)(void *opaque);
/* This runs outside the BQL in the migration case, and
* within the lock in the savevm case. The callback had better only
* use data that is local to the migration thread or protected
* by other locks.
*/
/**
* @save_live_iterate
*
* Should send a chunk of data until the point that stream
* bandwidth limits tell it to stop. Each call generates one
* section.
*
* @f: QEMUFile where to send the data
* @opaque: data pointer passed to register_savevm_live()
*
* Returns 0 to indicate that there is still more data to send,
* 1 that there is no more data to send and
* negative to indicate an error.
*/
int (*save_live_iterate)(QEMUFile *f, void *opaque);
/* This runs outside the BQL! */
/**
* @state_pending_estimate
*
* This estimates the remaining data to transfer
*
* Sum of @can_postcopy and @must_postcopy is the whole amount of
* pending data.
*
* @opaque: data pointer passed to register_savevm_live()
* @must_precopy: amount of data that must be migrated in precopy
* or in stopped state, i.e. that must be migrated
* before target start.
* @can_postcopy: amount of data that can be migrated in postcopy
* or in stopped state, i.e. after target start.
* Some can also be migrated during precopy (RAM).
* Some must be migrated after source stops
* (block-dirty-bitmap)
*/
void (*state_pending_estimate)(void *opaque, uint64_t *must_precopy,
uint64_t *can_postcopy);
/**
* @state_pending_exact
*
* This calculates the exact remaining data to transfer
*
* Sum of @can_postcopy and @must_postcopy is the whole amount of
* pending data.
*
* @opaque: data pointer passed to register_savevm_live()
* @must_precopy: amount of data that must be migrated in precopy
* or in stopped state, i.e. that must be migrated
* before target start.
* @can_postcopy: amount of data that can be migrated in postcopy
* or in stopped state, i.e. after target start.
* Some can also be migrated during precopy (RAM).
* Some must be migrated after source stops
* (block-dirty-bitmap)
*/
void (*state_pending_exact)(void *opaque, uint64_t *must_precopy,
uint64_t *can_postcopy);
/**
* @load_state
*
* Load sections generated by any of the save functions that
* generate sections.
*
* Legacy method. Should be deprecated when all users are ported
* to VMStateDescription.
*
* @f: QEMUFile where to receive the data
* @opaque: data pointer passed to register_savevm_live()
* @version_id: the maximum version_id supported
*
* Returns zero to indicate success and negative for error
*/
int (*load_state)(QEMUFile *f, void *opaque, int version_id);
/**
* @load_setup
*
* Initializes the data structures on the destination.
*
* @f: QEMUFile where to receive the data
* @opaque: data pointer passed to register_savevm_live()
* @errp: pointer to Error*, to store an error if it happens.
*
* Returns zero to indicate success and negative for error
*/
int (*load_setup)(QEMUFile *f, void *opaque, Error **errp);
/**
* @load_cleanup
*
* Uninitializes the data structures on the destination.
* Note that this handler can be called even if load_setup
* wasn't called earlier.
*
* @opaque: data pointer passed to register_savevm_live()
*
* Returns zero to indicate success and negative for error
*/
int (*load_cleanup)(void *opaque);
/**
* @resume_prepare
*
* Called when postcopy migration wants to resume from failure
*
* @s: Current migration state
* @opaque: data pointer passed to register_savevm_live()
*
* Returns zero to indicate success and negative for error
*/
int (*resume_prepare)(MigrationState *s, void *opaque);
/**
* @switchover_ack_needed
*
* Checks if switchover ack should be used. Called only on
* destination.
*
* @opaque: data pointer passed to register_savevm_live()
*
* Returns true if switchover ack should be used and false
* otherwise
*/
bool (*switchover_ack_needed)(void *opaque);
/**
* @switchover_start
*
* Notifies that the switchover has started. Called only on
* the destination.
*
* @opaque: data pointer passed to register_savevm_live()
*
* Returns zero to indicate success and negative for error
*/
int (*switchover_start)(void *opaque);
} SaveVMHandlers;
/**
* register_savevm_live: Register a set of custom migration handlers
*
* @idstr: state section identifier
* @instance_id: instance id
* @version_id: version id supported
* @ops: SaveVMHandlers structure
* @opaque: data pointer passed to SaveVMHandlers handlers
*/
int register_savevm_live(const char *idstr,
uint32_t instance_id,
int version_id,
const SaveVMHandlers *ops,
void *opaque);
/**
* unregister_savevm: Unregister custom migration handlers
*
* @obj: object associated with state section
* @idstr: state section identifier
* @opaque: data pointer passed to register_savevm_live()
*/
void unregister_savevm(VMStateIf *obj, const char *idstr, void *opaque);
#endif