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:
parent
a8e63c0130
commit
112b55f0b0
3 changed files with 36 additions and 0 deletions
|
|
@ -445,11 +445,38 @@ INITIALIZE_MIGRATE_CAPS_SET(check_caps_background_snapshot,
|
|||
MIGRATION_CAPABILITY_VALIDATE_UUID,
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (caps[MIGRATION_CAPABILITY_XBZRLE]) {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ bool migrate_tls(void);
|
|||
|
||||
bool migrate_rdma_caps_check(bool *caps, Error **errp);
|
||||
bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp);
|
||||
bool migrate_can_snapshot(Error **errp);
|
||||
|
||||
/* parameters */
|
||||
|
||||
|
|
|
|||
|
|
@ -3322,6 +3322,10 @@ bool save_snapshot(const char *name, bool overwrite, const char *vmstate,
|
|||
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
if (!migrate_can_snapshot(errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (migration_is_blocked(errp)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -3507,6 +3511,10 @@ bool load_snapshot(const char *name, const char *vmstate,
|
|||
int ret;
|
||||
MigrationIncomingState *mis = migration_incoming_get_current();
|
||||
|
||||
if (!migrate_can_snapshot(errp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bdrv_all_can_snapshot(has_devices, devices, errp)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue