mirror of
https://github.com/xemu-project/xemu.git
synced 2026-07-11 01:24:41 +02:00
migration/savevm: Add a compatibility check for capabilities
It has always been possible to enable arbitrary migration capabilities and attempt to take a snapshot of the VM with the savevm/loadvm commands as well as their QMP counterparts snapshot-save/snapshot-load. Most migration capabilities are not meant to be used with snapshots and there's a risk of crashing QEMU or producing incorrect behavior. Ideally, every migration capability would either be implemented for savevm or explicitly rejected. Add a compatibility check routine and reject the snapshot command if an incompatible capability is enabled. For now only act on the the two that actually cause a crash: multifd and mapped-ram. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2881 Signed-off-by: Fabiano Rosas <farosas@suse.de> Link: https://lore.kernel.org/r/20251007184213.5990-1-farosas@suse.de Signed-off-by: Peter Xu <peterx@redhat.com>
This commit is contained in:
@@ -445,11 +445,38 @@ INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
|
|||||||
MIGRATION_CAPABILITY_VALIDATE_UUID,
|
MIGRATION_CAPABILITY_VALIDATE_UUID,
|
||||||
MIGRATION_CAPABILITY_ZERO_COPY_SEND);
|
MIGRATION_CAPABILITY_ZERO_COPY_SEND);
|
||||||
|
|
||||||
|
/* Snapshot compatibility check list */
|
||||||
|
static const
|
||||||
|
INITIALIZE_MIGRATE_CAPS_SET(check_caps_savevm,
|
||||||
|
MIGRATION_CAPABILITY_MULTIFD,
|
||||||
|
MIGRATION_CAPABILITY_MAPPED_RAM,
|
||||||
|
);
|
||||||
|
|
||||||
static bool migrate_incoming_started(void)
|
static bool migrate_incoming_started(void)
|
||||||
{
|
{
|
||||||
return !!migration_incoming_get_current()->transport_data;
|
return !!migration_incoming_get_current()->transport_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool migrate_can_snapshot(Error **errp)
|
||||||
|
{
|
||||||
|
MigrationState *s = migrate_get_current();
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < check_caps_savevm.size; i++) {
|
||||||
|
int incomp_cap = check_caps_savevm.caps[i];
|
||||||
|
|
||||||
|
if (s->capabilities[incomp_cap]) {
|
||||||
|
error_setg(errp,
|
||||||
|
"Snapshots are not compatible with %s",
|
||||||
|
MigrationCapability_str(incomp_cap));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool migrate_rdma_caps_check(bool *caps, Error **errp)
|
bool migrate_rdma_caps_check(bool *caps, Error **errp)
|
||||||
{
|
{
|
||||||
if (caps[MIGRATION_CAPABILITY_XBZRLE]) {
|
if (caps[MIGRATION_CAPABILITY_XBZRLE]) {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ bool migrate_tls(void);
|
|||||||
|
|
||||||
bool migrate_rdma_caps_check(bool *caps, Error **errp);
|
bool migrate_rdma_caps_check(bool *caps, Error **errp);
|
||||||
bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp);
|
bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp);
|
||||||
|
bool migrate_can_snapshot(Error **errp);
|
||||||
|
|
||||||
/* parameters */
|
/* parameters */
|
||||||
|
|
||||||
|
|||||||
@@ -3322,6 +3322,10 @@ bool save_snapshot(const char *name, bool overwrite, const char *vmstate,
|
|||||||
|
|
||||||
GLOBAL_STATE_CODE();
|
GLOBAL_STATE_CODE();
|
||||||
|
|
||||||
|
if (!migrate_can_snapshot(errp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (migration_is_blocked(errp)) {
|
if (migration_is_blocked(errp)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3507,6 +3511,10 @@ bool load_snapshot(const char *name, const char *vmstate,
|
|||||||
int ret;
|
int ret;
|
||||||
MigrationIncomingState *mis = migration_incoming_get_current();
|
MigrationIncomingState *mis = migration_incoming_get_current();
|
||||||
|
|
||||||
|
if (!migrate_can_snapshot(errp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!bdrv_all_can_snapshot(has_devices, devices, errp)) {
|
if (!bdrv_all_can_snapshot(has_devices, devices, errp)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user