mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
snapshot: qemu: Fix segfault and vanishing snapshots when redefining
When the disk alignment check done while redefining an existing snapshot failed, the qemu driver attempted to free the existing snapshot. As in the cleanup path the definition of the snapshot wasn't assigned, the cleanup code dereferenced a NULL pointer. This patch changes the behavior on error paths while redefining snapshot in two ways: 1) On failure, modifications done on the snapshot definition object are rolled back. 2) The previous definition of the data isn't freed until it's certain it won't be needed any more. This change avoids the segfault and additionally the snapshot doesn't vanish if redefinition fails for some reason.
This commit is contained in:
parent
4494b11f8f
commit
709b0f37c5
@ -11408,6 +11408,24 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
|
||||
}
|
||||
}
|
||||
|
||||
if (def->dom) {
|
||||
if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
|
||||
def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
|
||||
align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
|
||||
align_match = false;
|
||||
}
|
||||
|
||||
if (virDomainSnapshotAlignDisks(def, align_location,
|
||||
align_match) < 0) {
|
||||
/* revert stealing of the snapshot domain definition */
|
||||
if (def->dom && !other->def->dom) {
|
||||
other->def->dom = def->dom;
|
||||
def->dom = NULL;
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (other == vm->current_snapshot) {
|
||||
update_current = true;
|
||||
vm->current_snapshot = NULL;
|
||||
@ -11417,18 +11435,20 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
|
||||
* child relations by reusing snap. */
|
||||
virDomainSnapshotDropParent(other);
|
||||
virDomainSnapshotDefFree(other->def);
|
||||
other->def = NULL;
|
||||
other->def = def;
|
||||
def = NULL;
|
||||
snap = other;
|
||||
}
|
||||
if (def->dom) {
|
||||
if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
|
||||
def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
|
||||
align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
|
||||
align_match = false;
|
||||
} else {
|
||||
if (def->dom) {
|
||||
if (def->state == VIR_DOMAIN_DISK_SNAPSHOT ||
|
||||
def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
|
||||
align_location = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
|
||||
align_match = false;
|
||||
}
|
||||
if (virDomainSnapshotAlignDisks(def, align_location,
|
||||
align_match) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
if (virDomainSnapshotAlignDisks(def, align_location,
|
||||
align_match) < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
/* Easiest way to clone inactive portion of vm->def is via
|
||||
@ -11463,11 +11483,12 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (snap)
|
||||
snap->def = def;
|
||||
else if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
|
||||
goto cleanup;
|
||||
def = NULL;
|
||||
if (!snap) {
|
||||
if (!(snap = virDomainSnapshotAssignDef(vm->snapshots, def)))
|
||||
goto cleanup;
|
||||
|
||||
def = NULL;
|
||||
}
|
||||
|
||||
if (update_current)
|
||||
snap->def->current = true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user