提交 55bbb011 编写于 作者: P Peter Krempa

qemu: snapshot: Avoid libvirtd crash when qemu crashes while snapshotting

We shouldn't access the domain definition while we are in the monitor
section as the domain is unlocked. Additionally after we exit from the
monitor we need to check if the VM is still alive. Not doing so resulted
in a crash if qemu exits while attempting to do an external VM snapshot.
上级 08d07e5f
...@@ -12564,7 +12564,8 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver, ...@@ -12564,7 +12564,8 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
virDomainDiskDefPtr disk, virDomainDiskDefPtr disk,
virDomainDiskDefPtr persistDisk, virDomainDiskDefPtr persistDisk,
virJSONValuePtr actions, virJSONValuePtr actions,
bool reuse) bool reuse,
enum qemuDomainAsyncJob asyncJob)
{ {
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
char *device = NULL; char *device = NULL;
...@@ -12616,8 +12617,25 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver, ...@@ -12616,8 +12617,25 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
/* create the actual snapshot */ /* create the actual snapshot */
if (snap->format) if (snap->format)
formatStr = virStorageFileFormatTypeToString(snap->format); formatStr = virStorageFileFormatTypeToString(snap->format);
/* The monitor is only accessed if qemu doesn't support transactions.
* Otherwise the following monitor command only constructs the command.
*/
if (!actions &&
qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
goto cleanup;
ret = qemuMonitorDiskSnapshot(priv->mon, actions, device, source, ret = qemuMonitorDiskSnapshot(priv->mon, actions, device, source,
formatStr, reuse); formatStr, reuse);
if (!actions) {
qemuDomainObjExitMonitor(driver, vm);
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("domain crashed while taking the snapshot"));
ret = -1;
}
}
virDomainAuditDisk(vm, disk->src, source, "snapshot", ret >= 0); virDomainAuditDisk(vm, disk->src, source, "snapshot", ret >= 0);
if (ret < 0) if (ret < 0)
goto cleanup; goto cleanup;
...@@ -12723,9 +12741,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver, ...@@ -12723,9 +12741,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
* Based on earlier qemuDomainSnapshotPrepare, all * Based on earlier qemuDomainSnapshotPrepare, all
* disks in this list are now either SNAPSHOT_NO, or * disks in this list are now either SNAPSHOT_NO, or
* SNAPSHOT_EXTERNAL with a valid file name and qcow2 format. */ * SNAPSHOT_EXTERNAL with a valid file name and qcow2 format. */
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
goto cleanup;
for (i = 0; i < snap->def->ndisks; i++) { for (i = 0; i < snap->def->ndisks; i++) {
virDomainDiskDefPtr persistDisk = NULL; virDomainDiskDefPtr persistDisk = NULL;
...@@ -12735,24 +12750,36 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver, ...@@ -12735,24 +12750,36 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
int indx = virDomainDiskIndexByName(vm->newDef, int indx = virDomainDiskIndexByName(vm->newDef,
vm->def->disks[i]->dst, vm->def->disks[i]->dst,
false); false);
if (indx >= 0) { if (indx >= 0)
persistDisk = vm->newDef->disks[indx]; persistDisk = vm->newDef->disks[indx];
persist = true;
}
} }
ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm, ret = qemuDomainSnapshotCreateSingleDiskActive(driver, vm,
&snap->def->disks[i], &snap->def->disks[i],
vm->def->disks[i], vm->def->disks[i],
persistDisk, actions, persistDisk, actions,
reuse); reuse, asyncJob);
if (ret < 0) if (ret < 0)
break; break;
} }
if (actions) { if (actions) {
if (ret == 0) if (ret == 0) {
ret = qemuMonitorTransaction(priv->mon, actions); if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) == 0) {
ret = qemuMonitorTransaction(priv->mon, actions);
qemuDomainObjExitMonitor(driver, vm);
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("domain crashed while taking the snapshot"));
ret = -1;
}
} else {
/* failed to enter monitor, clean stuff up and quit */
ret = -1;
}
}
virJSONValueFree(actions); virJSONValueFree(actions);
if (ret < 0) { if (ret < 0) {
/* Transaction failed; undo the changes to vm. */ /* Transaction failed; undo the changes to vm. */
bool need_unlink = !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT); bool need_unlink = !(flags & VIR_DOMAIN_SNAPSHOT_CREATE_REUSE_EXT);
...@@ -12766,8 +12793,11 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver, ...@@ -12766,8 +12793,11 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
int indx = virDomainDiskIndexByName(vm->newDef, int indx = virDomainDiskIndexByName(vm->newDef,
vm->def->disks[i]->dst, vm->def->disks[i]->dst,
false); false);
if (indx >= 0) if (indx >= 0) {
persistDisk = vm->newDef->disks[indx]; persistDisk = vm->newDef->disks[indx];
persist = true;
}
} }
qemuDomainSnapshotUndoSingleDiskActive(driver, vm, qemuDomainSnapshotUndoSingleDiskActive(driver, vm,
...@@ -12778,7 +12808,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver, ...@@ -12778,7 +12808,6 @@ qemuDomainSnapshotCreateDiskActive(virQEMUDriverPtr driver,
} }
} }
} }
qemuDomainObjExitMonitor(driver, vm);
cleanup: cleanup:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册