qemu may quited unexpectedly when invoking a monitor command. And priv->mon will be NULL after qemuDomainObjExitMonitor* returns. So we must not use it. Unfortunately we still use it, and it will cause libvirtd crashed. As Eric suggested, qemuDomainObjExitMonitor* should be made to return the value of vm active after regaining lock, and marked ATTRIBUTE_RETURN_CHECK, to force all other callers to detect the case of a monitor command completing successfully but then the VM disappearing in the window between command completion and regaining the vm lock. --- src/qemu/qemu_domain.c | 28 +++++++- src/qemu/qemu_domain.h | 6 +- src/qemu/qemu_driver.c | 51 ++++++++------ src/qemu/qemu_hotplug.c | 177 ++++++++++++++++++++++----------------------- src/qemu/qemu_migration.c | 73 +++++++++++-------- src/qemu/qemu_process.c | 38 ++++++---- 6 files changed, 212 insertions(+), 161 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index a947b4e..44ad6a3 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -580,7 +580,7 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj) * * Should be paired with an earlier qemuDomainObjEnterMonitor() call */ -void qemuDomainObjExitMonitor(virDomainObjPtr obj) +int qemuDomainObjExitMonitor(virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; int refs; @@ -590,11 +590,22 @@ void qemuDomainObjExitMonitor(virDomainObjPtr obj) if (refs > 0) qemuMonitorUnlock(priv->mon); + /* Note: qemu may quited unexpectedly here, and the monitor will be freed. + * If it happened, priv->mon will be null. + */ + virDomainObjLock(obj); if (refs == 0) { priv->mon = NULL; } + + if (priv->mon == NULL) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + return -1; + } else + return 0; } @@ -623,8 +634,8 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, * * Should be paired with an earlier qemuDomainObjEnterMonitorWithDriver() call */ -void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, - virDomainObjPtr obj) +int qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, + virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; int refs; @@ -634,12 +645,23 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, if (refs > 0) qemuMonitorUnlock(priv->mon); + /* Note: qemu may quited unexpectedly here, and the monitor will be freed. + * If it happened, priv->mon will be null. + */ + qemuDriverLock(driver); virDomainObjLock(obj); if (refs == 0) { priv->mon = NULL; } + + if (priv->mon == NULL) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + return -1; + } else + return 0; } void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 8258900..92fccda 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -99,11 +99,11 @@ int qemuDomainObjBeginJobWithDriver(struct qemud_driver *driver, virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; int qemuDomainObjEndJob(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; void qemuDomainObjEnterMonitor(virDomainObjPtr obj); -void qemuDomainObjExitMonitor(virDomainObjPtr obj); +int qemuDomainObjExitMonitor(virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, virDomainObjPtr obj); -void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, - virDomainObjPtr obj); +int qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, + virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver, virDomainObjPtr obj); void qemuDomainObjExitRemoteWithDriver(struct qemud_driver *driver, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 04a5f65..cb9f3fa 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1452,7 +1452,8 @@ static int qemudDomainShutdown(virDomainPtr dom) { priv = vm->privateData; qemuDomainObjEnterMonitor(vm); ret = qemuMonitorSystemPowerdown(priv->mon); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) + ret = -1; endjob: if (qemuDomainObjEndJob(vm) == 0) @@ -1659,7 +1660,8 @@ static int qemudDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, priv = vm->privateData; qemuDomainObjEnterMonitor(vm); r = qemuMonitorSetBalloon(priv->mon, newmem); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) + r = -1; qemuAuditMemory(vm, vm->def->mem.cur_balloon, newmem, "update", r == 1); if (r < 0) @@ -1749,7 +1751,8 @@ static int qemudDomainGetInfo(virDomainPtr dom, else { qemuDomainObjEnterMonitor(vm); err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) + err = -1; } if (qemuDomainObjEndJob(vm) == 0) { vm = NULL; @@ -2524,7 +2527,8 @@ static int qemudDomainHotplugVcpus(virDomainObjPtr vm, unsigned int nvcpus) ret = 0; cleanup: - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) + ret = -1; vm->def->vcpus = vcpus; qemuAuditVcpu(vm, oldvcpus, nvcpus, "update", rc == 1); return ret; @@ -3295,7 +3299,8 @@ static char *qemudDomainDumpXML(virDomainPtr dom, qemuDomainObjEnterMonitorWithDriver(driver, vm); err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + err = -1; if (qemuDomainObjEndJob(vm) == 0) { vm = NULL; goto cleanup; @@ -4843,7 +4848,8 @@ qemudDomainBlockStats (virDomainPtr dom, &stats->wr_req, &stats->wr_bytes, &stats->errs); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) + ret = -1; endjob: if (qemuDomainObjEndJob(vm) == 0) @@ -4944,7 +4950,8 @@ qemudDomainMemoryStats (virDomainPtr dom, qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjEnterMonitor(vm); ret = qemuMonitorGetMemoryStats(priv->mon, stats, nr_stats); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) + ret = -1; } else { qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -5085,17 +5092,15 @@ qemudDomainMemoryPeek (virDomainPtr dom, priv = vm->privateData; qemuDomainObjEnterMonitor(vm); if (flags == VIR_MEMORY_VIRTUAL) { - if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) { - qemuDomainObjExitMonitor(vm); - goto endjob; - } + ret = qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp); } else { - if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) { - qemuDomainObjExitMonitor(vm); - goto endjob; - } + ret = qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp); } - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) + ret = -1; + + if (ret < -1) + goto endjob; /* Read the memory file into buffer. */ if (saferead (fd, buffer, size) == (ssize_t) -1) { @@ -5259,7 +5264,8 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom, ret = qemuMonitorGetBlockExtent(priv->mon, disk->info.alias, &info->allocation); - qemuDomainObjExitMonitor(vm); + if (qemuDomainObjExitMonitor(vm) < 0) + ret = -1; } if (qemuDomainObjEndJob(vm) == 0) @@ -6101,7 +6107,8 @@ qemuDomainSnapshotCreateActive(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; cleanup: if (resume && virDomainObjIsActive(vm) && @@ -6434,7 +6441,8 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, priv = vm->privateData; qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + rc = -1; if (rc < 0) goto endjob; } @@ -6557,7 +6565,7 @@ static int qemuDomainSnapshotDiscard(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); /* we continue on even in the face of error */ qemuMonitorDeleteSnapshot(priv->mon, snap->def->name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + ignore_value(qemuDomainObjExitMonitorWithDriver(driver, vm)); } if (snap == vm->current_snapshot) { @@ -6770,7 +6778,8 @@ static int qemuDomainMonitorCommand(virDomainPtr domain, const char *cmd, goto cleanup; qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorArbitraryCommand(priv->mon, cmd, result, hmp); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; if (qemuDomainObjEndJob(vm) == 0) { vm = NULL; goto cleanup; diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index b03f774..1ecac80 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -106,7 +106,8 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, } else { ret = qemuMonitorEjectMedia(priv->mon, driveAlias, force); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; qemuAuditDisk(vm, origdisk, disk, "update", ret >= 0); @@ -201,7 +202,8 @@ int qemuDomainAttachPciDiskDevice(struct qemud_driver *driver, memcpy(&disk->info.addr.pci, &guestAddr, sizeof(guestAddr)); } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; qemuAuditDisk(vm, NULL, disk, "attach", ret >= 0); @@ -277,7 +279,8 @@ int qemuDomainAttachPciControllerDevice(struct qemud_driver *driver, type, &controller->info.addr.pci); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; if (ret == 0) { controller->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; @@ -433,7 +436,8 @@ int qemuDomainAttachSCSIDisk(struct qemud_driver *driver, memcpy(&disk->info.addr.drive, &driveAddr, sizeof(driveAddr)); } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; qemuAuditDisk(vm, NULL, disk, "attach", ret >= 0); @@ -516,7 +520,8 @@ int qemuDomainAttachUsbMassstorageDevice(struct qemud_driver *driver, } else { ret = qemuMonitorAddUSBDisk(priv->mon, disk->src); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; qemuAuditDisk(vm, NULL, disk, "attach", ret >= 0); @@ -632,21 +637,19 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorAddNetdev(priv->mon, netstr, tapfd, tapfd_name, - vhostfd, vhostfd_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, NULL, net, "attach", false); - goto cleanup; - } + ret = qemuMonitorAddNetdev(priv->mon, netstr, tapfd, tapfd_name, + vhostfd, vhostfd_name); } else { - if (qemuMonitorAddHostNetwork(priv->mon, netstr, tapfd, tapfd_name, - vhostfd, vhostfd_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, NULL, net, "attach", false); - goto cleanup; - } + ret = qemuMonitorAddHostNetwork(priv->mon, netstr, tapfd, tapfd_name, + vhostfd, vhostfd_name); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; + + qemuAuditNet(vm, NULL, net, "attach", ret >= 0); + + if (ret < 0) + goto cleanup; VIR_FORCE_CLOSE(tapfd); VIR_FORCE_CLOSE(vhostfd); @@ -667,25 +670,23 @@ int qemuDomainAttachNetDevice(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorAddDevice(priv->mon, nicstr) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, NULL, net, "attach", false); - goto try_remove; - } + ret = qemuMonitorAddDevice(priv->mon, nicstr); } else { - if (qemuMonitorAddPCINetwork(priv->mon, nicstr, - &guestAddr) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, NULL, net, "attach", false); - goto try_remove; + ret = qemuMonitorAddPCINetwork(priv->mon, nicstr, + &guestAddr); + if (ret == 0) { + net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; + memcpy(&net->info.addr.pci, &guestAddr, sizeof(guestAddr)); } - net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; - memcpy(&net->info.addr.pci, &guestAddr, sizeof(guestAddr)); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; qemuAuditNet(vm, NULL, net, "attach", true); + if (ret < 0) + goto try_remove; + ret = 0; vm->def->nets[vm->def->nnets++] = net; @@ -723,7 +724,7 @@ try_remove: if (qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0) VIR_WARN("Failed to remove network backend for netdev %s", netdev_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + ignore_value(qemuDomainObjExitMonitorWithDriver(driver, vm)); VIR_FREE(netdev_name); } else { VIR_WARN0("Unable to remove network backend"); @@ -736,7 +737,7 @@ try_remove: if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) VIR_WARN("Failed to remove network backend for vlan %d, net %s", vlan, hostnet_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + ignore_value(qemuDomainObjExitMonitorWithDriver(driver, vm)); VIR_FREE(hostnet_name); } goto cleanup; @@ -795,7 +796,8 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr, configfd, configfd_name); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; } else { virDomainDevicePCIAddress guestAddr; @@ -803,7 +805,8 @@ int qemuDomainAttachHostPciDevice(struct qemud_driver *driver, ret = qemuMonitorAddPCIHostDevice(priv->mon, &hostdev->source.subsys.u.pci, &guestAddr); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; hostdev->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; memcpy(&hostdev->info.addr.pci, &guestAddr, sizeof(guestAddr)); @@ -886,7 +889,8 @@ int qemuDomainAttachHostUsbDevice(struct qemud_driver *driver, ret = qemuMonitorAddUSBDeviceExact(priv->mon, hostdev->source.subsys.u.usb.bus, hostdev->source.subsys.u.usb.device); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; qemuAuditHostdev(vm, hostdev, "attach", ret == 0); if (ret < 0) goto error; @@ -1145,25 +1149,24 @@ int qemuDomainDetachPciDiskDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); } else { - if (qemuMonitorRemovePCIDevice(priv->mon, - &detach->info.addr.pci) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorRemovePCIDevice(priv->mon, + &detach->info.addr.pci); } /* disconnect guest from host device */ - qemuMonitorDriveDel(priv->mon, drivestr); + if (ret == 0) + qemuMonitorDriveDel(priv->mon, drivestr); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitor(vm) < 0) + ret = -1; qemuAuditDisk(vm, detach, NULL, "detach", ret >= 0); + if (ret < 0) + goto cleanup; + if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0) VIR_WARN("Unable to release PCI address on %s", dev->data.disk->src); @@ -1235,18 +1238,20 @@ int qemuDomainDetachDiskDevice(struct qemud_driver *driver, } qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); /* disconnect guest from host device */ - qemuMonitorDriveDel(priv->mon, drivestr); + if (ret == 0) + qemuMonitorDriveDel(priv->mon, drivestr); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; qemuAuditDisk(vm, detach, NULL, "detach", ret >= 0); + if (ret < 0) + goto cleanup; + virDomainDiskRemove(vm->def, i); virDomainDiskDefFree(detach); @@ -1364,18 +1369,16 @@ int qemuDomainDetachPciControllerDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); } else { - if (qemuMonitorRemovePCIDevice(priv->mon, - &detach->info.addr.pci) < 0) { - qemuDomainObjExitMonitor(vm); - goto cleanup; - } + ret = qemuMonitorRemovePCIDevice(priv->mon, + &detach->info.addr.pci); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; + + if (ret < 0) + goto cleanup; if (vm->def->ncontrollers > 1) { memmove(vm->def->controllers + i, @@ -1452,37 +1455,30 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { - qemuDomainObjExitMonitor(vm); - qemuAuditNet(vm, detach, NULL, "detach", false); - goto cleanup; - } + ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); } else { - if (qemuMonitorRemovePCIDevice(priv->mon, - &detach->info.addr.pci) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, detach, NULL, "detach", false); - goto cleanup; - } + ret = qemuMonitorRemovePCIDevice(priv->mon, + &detach->info.addr.pci); } + if (ret < 0) + goto exitmonitor; + if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) && qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) { - if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, detach, NULL, "detach", false); - goto cleanup; - } + ret = qemuMonitorRemoveNetdev(priv->mon, hostnet_name); } else { - if (qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, detach, NULL, "detach", false); - goto cleanup; - } + ret = qemuMonitorRemoveHostNetwork(priv->mon, vlan, hostnet_name); } - qemuDomainObjExitMonitorWithDriver(driver, vm); - qemuAuditNet(vm, detach, NULL, "detach", true); +exitmonitor: + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; + + qemuAuditNet(vm, detach, NULL, "detach", ret >= 0); + + if (ret < 0) + goto cleanup; if (qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && qemuDomainPCIAddressReleaseAddr(priv->pciaddrs, &detach->info) < 0) @@ -1582,7 +1578,8 @@ int qemuDomainDetachHostPciDevice(struct qemud_driver *driver, } else { ret = qemuMonitorRemovePCIDevice(priv->mon, &detach->info.addr.pci); } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; qemuAuditHostdev(vm, detach, "detach", ret == 0); if (ret < 0) return -1; @@ -1681,7 +1678,8 @@ int qemuDomainDetachHostUsbDevice(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorDelDevice(priv->mon, detach->info.alias); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; qemuAuditHostdev(vm, detach, "detach", ret == 0); if (ret < 0) return -1; @@ -1798,7 +1796,8 @@ qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver, } cleanup: - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; return ret; } diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 43741e1..bdc05c0 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -125,7 +125,8 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) VIR_DEBUG0("Cancelling job at client request"); qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorMigrateCancel(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + rc = -1; if (rc < 0) { VIR_WARN0("Unable to cancel job"); } @@ -142,7 +143,8 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) VIR_DEBUG("Setting migration downtime to %llums", ms); qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorSetMigrationDowntime(priv->mon, ms); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + rc = -1; if (rc < 0) VIR_WARN0("Unable to set migration downtime"); } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_SPEED) { @@ -153,7 +155,8 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth); qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + rc = -1; if (rc < 0) VIR_WARN0("Unable to set migration speed"); } @@ -173,7 +176,8 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) &memProcessed, &memRemaining, &memTotal); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + rc = -1; if (rc < 0) { priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; @@ -608,11 +612,13 @@ static int doNativeMigrate(struct qemud_driver *driver, } qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (resource > 0 && - qemuMonitorSetMigrationSpeed(priv->mon, resource) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; - } + if (resource > 0) + ret = qemuMonitorSetMigrationSpeed(priv->mon, resource); + else + ret = 0; + + if (ret < 0) + goto exitmonitor; if (flags & VIR_MIGRATE_NON_SHARED_DISK) background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_DISK; @@ -620,12 +626,15 @@ static int doNativeMigrate(struct qemud_driver *driver, if (flags & VIR_MIGRATE_NON_SHARED_INC) background_flags |= QEMU_MONITOR_MIGRATE_NON_SHARED_INC; - if (qemuMonitorMigrateToHost(priv->mon, background_flags, uribits->server, - uribits->port) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + ret = qemuMonitorMigrateToHost(priv->mon, background_flags, uribits->server, + uribits->port); + +exitmonitor: + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; + + if (ret < 0) goto cleanup; - } - qemuDomainObjExitMonitorWithDriver(driver, vm); if (qemuMigrationWaitForCompletion(driver, vm) < 0) goto cleanup; @@ -824,7 +833,8 @@ static int doTunnelMigrate(struct qemud_driver *driver, } else { internalret = -1; } - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + internalret = -1; if (internalret < 0) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("tunnelled migration monitor command failed")); @@ -844,17 +854,15 @@ static int doTunnelMigrate(struct qemud_driver *driver, * rather failed later on. Check the output of "info migrate" */ qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorGetMigrationStatus(priv->mon, - &status, - &transferred, - &remaining, - &total) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cancel; - } - qemuDomainObjExitMonitorWithDriver(driver, vm); + retval = qemuMonitorGetMigrationStatus(priv->mon, + &status, + &transferred, + &remaining, + &total); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + retval = -1; - if (status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) { + if (retval < 0 || status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",_("migrate failed")); goto cancel; @@ -875,7 +883,7 @@ cancel: if (retval != 0 && virDomainObjIsActive(vm)) { qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuMonitorMigrateCancel(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + ignore_value(qemuDomainObjExitMonitorWithDriver(driver, vm)); } finish: @@ -1372,12 +1380,12 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm, if (virSetCloseExec(pipeFD[1]) < 0) { virReportSystemError(errno, "%s", _("Unable to set cloexec flag")); - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; + rc = -1; + goto exitmonitor; } if (virCommandRunAsync(cmd, NULL) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); - goto cleanup; + rc = -1; + goto exitmonitor; } rc = qemuMonitorMigrateToFd(priv->mon, QEMU_MONITOR_MIGRATE_BACKGROUND, @@ -1391,7 +1399,10 @@ qemuMigrationToFile(struct qemud_driver *driver, virDomainObjPtr vm, args, path, offset); } } - qemuDomainObjExitMonitorWithDriver(driver, vm); + +exitmonitor: + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + rc = -1; if (rc < 0) goto cleanup; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 7295f9e..374de0f 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -662,7 +662,8 @@ qemuConnectMonitor(struct qemud_driver *driver, virDomainObjPtr vm) qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorSetCapabilities(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; error: @@ -1070,7 +1071,8 @@ qemuProcessWaitForMonitor(struct qemud_driver* driver, priv = vm->privateData; qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorGetPtyPaths(priv->mon, paths); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; VIR_DEBUG("qemuMonitorGetPtyPaths returned %i", ret); if (ret == 0) @@ -1122,11 +1124,12 @@ qemuProcessDetectVcpuPIDs(struct qemud_driver *driver, /* What follows is now all KVM specific */ qemuDomainObjEnterMonitorWithDriver(driver, vm); - if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ncpupids = -1; + + if (ncpupids < 0) return -1; - } - qemuDomainObjExitMonitorWithDriver(driver, vm); /* Treat failure to get VCPU<->PID mapping as non-fatal */ if (ncpupids == 0) @@ -1322,7 +1325,8 @@ qemuProcessInitPasswords(virConnectPtr conn, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorSetDrivePassphrase(priv->mon, alias, secret); VIR_FREE(secret); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; if (ret < 0) goto cleanup; } @@ -1713,7 +1717,10 @@ qemuProcessInitPCIAddresses(struct qemud_driver *driver, qemuDomainObjEnterMonitorWithDriver(driver, vm); naddrs = qemuMonitorGetAllPCIAddresses(priv->mon, &addrs); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) { + VIR_FREE(addrs); + return -1; + } ret = qemuProcessDetectPCIAddresses(vm, addrs, naddrs); @@ -1890,7 +1897,8 @@ qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm, qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorStartCPUs(priv->mon, conn); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; if (ret == 0) { vm->state = VIR_DOMAIN_RUNNING; } @@ -1908,7 +1916,8 @@ int qemuProcessStopCPUs(struct qemud_driver *driver, virDomainObjPtr vm) vm->state = VIR_DOMAIN_PAUSED; qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorStopCPUs(priv->mon); - qemuDomainObjExitMonitorWithDriver(driver, vm); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; if (ret < 0) { vm->state = oldState; } @@ -2389,11 +2398,12 @@ int qemuProcessStart(virConnectPtr conn, VIR_DEBUG0("Setting initial memory amount"); cur_balloon = vm->def->mem.cur_balloon; qemuDomainObjEnterMonitorWithDriver(driver, vm); - if (qemuMonitorSetBalloon(priv->mon, cur_balloon) < 0) { - qemuDomainObjExitMonitorWithDriver(driver, vm); + ret = qemuMonitorSetBalloon(priv->mon, cur_balloon); + if (qemuDomainObjExitMonitorWithDriver(driver, vm) < 0) + ret = -1; + + if (ret < 0) goto cleanup; - } - qemuDomainObjExitMonitorWithDriver(driver, vm); if (!start_paused) { VIR_DEBUG0("Starting domain CPUs"); -- 1.7.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list