In preparation of the monitor I/O process becoming fully asynchronous, it is neccessary to ensure all access to internals of the qemuMonitorPtr object is protected by a mutex lock. * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add mutex for locking monitor. * src/qemu/qemu_driver.c: Add locking around all monitor commands --- src/qemu/qemu_driver.c | 299 +++++++++++++++++++++++++++++++++++------------ src/qemu/qemu_monitor.c | 19 +++ src/qemu/qemu_monitor.h | 3 + 3 files changed, 248 insertions(+), 73 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0fbd20f..82cad69 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -141,6 +141,22 @@ static void qemuDomainObjPrivateFree(void *data) } +static void qemuDomainObjEnterMonitor(virDomainObjPtr obj) +{ + qemuDomainObjPrivatePtr priv = obj->privateData; + + qemuMonitorLock(priv->mon); +} + + +static void qemuDomainObjExitMonitor(virDomainObjPtr obj) +{ + qemuDomainObjPrivatePtr priv = obj->privateData; + + qemuMonitorUnlock(priv->mon); +} + + static int qemuCgroupControllerActive(struct qemud_driver *driver, int controller) { @@ -1139,8 +1155,12 @@ qemuDetectVcpuPIDs(virConnectPtr conn, /* What follows is now all KVM specific */ - if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) < 0) + qemuDomainObjEnterMonitor(vm); + if ((ncpupids = qemuMonitorGetCPUInfo(priv->mon, &cpupids)) < 0) { + qemuDomainObjExitMonitor(vm); return -1; + } + qemuDomainObjExitMonitor(vm); /* Treat failure to get VCPU<->PID mapping as non-fatal */ if (ncpupids == 0) @@ -1197,14 +1217,18 @@ qemudInitCpus(virConnectPtr conn, } #endif /* HAVE_SCHED_GETAFFINITY */ + /* XXX This resume doesn't really belong here. Move it up to caller */ if (migrateFrom == NULL) { /* Allow the CPUS to start executing */ + qemuDomainObjEnterMonitor(vm); if (qemuMonitorStartCPUs(priv->mon, conn) < 0) { if (virGetLastError() == NULL) qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resume operation failed")); + qemuDomainObjExitMonitor(vm); return -1; } + qemuDomainObjExitMonitor(vm); } return 0; @@ -1221,10 +1245,12 @@ qemuInitPasswords(struct qemud_driver *driver, vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC && (vm->def->graphics[0]->data.vnc.passwd || driver->vncPassword)) { + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorSetVNCPassword(priv->mon, vm->def->graphics[0]->data.vnc.passwd ? vm->def->graphics[0]->data.vnc.passwd : driver->vncPassword); + qemuDomainObjExitMonitor(vm); } return ret; @@ -1910,6 +1936,7 @@ static int qemudStartVMDaemon(virConnectPtr conn, char ebuf[1024]; char *pidfile = NULL; int logfile; + qemuDomainObjPrivatePtr priv = vm->privateData; struct qemudHookData hookData; hookData.conn = conn; @@ -2082,26 +2109,37 @@ static int qemudStartVMDaemon(virConnectPtr conn, VIR_FREE(tapfds); } - if (ret == -1) + if (ret == -1) /* The VM failed to start */ goto cleanup; - if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) || - (qemuDetectVcpuPIDs(conn, vm) < 0) || - (qemudInitCpus(conn, vm, migrateFrom) < 0) || - (qemuInitPasswords(driver, vm) < 0) || - (qemuMonitorSetBalloon(((qemuDomainObjPrivatePtr)vm->privateData)->mon, vm->def->memory) < 0) || - (virDomainSaveStatus(conn, driver->stateDir, vm) < 0)) { - qemudShutdownVMDaemon(conn, driver, vm); - ret = -1; - /* No need for 'goto cleanup' now since qemudShutdownVMDaemon does enough */ + if (qemudWaitForMonitor(conn, driver, vm, pos) < 0) + goto abort; + + if (qemuDetectVcpuPIDs(conn, vm) < 0) + goto abort; + + if (qemudInitCpus(conn, vm, migrateFrom) < 0) + goto abort; + + if (qemuInitPasswords(driver, vm) < 0) + goto abort; + + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorSetBalloon(priv->mon, vm->def->memory) < 0) { + qemuDomainObjExitMonitor(vm); + goto abort; } + qemuDomainObjExitMonitor(vm); - if (logfile != -1) - close(logfile); + if (virDomainSaveStatus(conn, driver->stateDir, vm) < 0) + goto abort; - return ret; + return 0; cleanup: + /* We jump here if we failed to start the VM for any reason + * XXX investigate if we can kill this block and safely call + * qemudShutdownVMDaemon even though no PID is running */ if (vm->def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) { VIR_FREE(vm->def->seclabel.model); VIR_FREE(vm->def->seclabel.label); @@ -2116,6 +2154,16 @@ cleanup: close(logfile); vm->def->id = -1; return -1; + +abort: + /* We jump here if we failed to initialize the now running VM + * killing it off and pretend we never started it */ + qemudShutdownVMDaemon(conn, driver, vm); + + if (logfile != -1) + close(logfile); + + return -1; } @@ -2649,8 +2697,12 @@ static int qemudDomainSuspend(virDomainPtr dom) { } if (vm->state != VIR_DOMAIN_PAUSED) { qemuDomainObjPrivatePtr priv = vm->privateData; - if (qemuMonitorStopCPUs(priv->mon) < 0) + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorStopCPUs(priv->mon) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } + qemuDomainObjExitMonitor(vm); vm->state = VIR_DOMAIN_PAUSED; event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED, @@ -2694,12 +2746,15 @@ static int qemudDomainResume(virDomainPtr dom) { } if (vm->state == VIR_DOMAIN_PAUSED) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) { + qemuDomainObjExitMonitor(vm); if (virGetLastError() == NULL) qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("resume operation failed")); goto cleanup; } + qemuDomainObjExitMonitor(vm); vm->state = VIR_DOMAIN_RUNNING; event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED, @@ -2743,10 +2798,9 @@ static int qemudDomainShutdown(virDomainPtr dom) { } qemuDomainObjPrivatePtr priv = vm->privateData; - if (qemuMonitorSystemPowerdown(priv->mon) < 0) - goto cleanup; - - ret = 0; + qemuDomainObjEnterMonitor(vm); + ret = qemuMonitorSystemPowerdown(priv->mon); + qemuDomainObjExitMonitor(vm); cleanup: if (vm) @@ -2905,7 +2959,9 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) { if (virDomainObjIsActive(vm)) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); int r = qemuMonitorSetBalloon(priv->mon, newmem); + qemuDomainObjExitMonitor(vm); if (r < 0) goto cleanup; @@ -2960,7 +3016,9 @@ static int qemudDomainGetInfo(virDomainPtr dom, if (virDomainObjIsActive(vm)) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); + qemuDomainObjExitMonitor(vm); if (err < 0) goto cleanup; @@ -3069,8 +3127,12 @@ static int qemudDomainSave(virDomainPtr dom, if (vm->state == VIR_DOMAIN_RUNNING) { qemuDomainObjPrivatePtr priv = vm->privateData; header.was_running = 1; - if (qemuMonitorStopCPUs(priv->mon) < 0) + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorStopCPUs(priv->mon) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } + qemuDomainObjExitMonitor(vm); vm->state = VIR_DOMAIN_PAUSED; } @@ -3113,7 +3175,9 @@ static int qemudDomainSave(virDomainPtr dom, if (header.compressed == QEMUD_SAVE_FORMAT_RAW) { const char *args[] = { "cat", NULL }; qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorMigrateToCommand(priv->mon, 0, args, path); + qemuDomainObjExitMonitor(vm); } else { const char *prog = qemudSaveCompressionTypeToString(header.compressed); qemuDomainObjPrivatePtr priv = vm->privateData; @@ -3122,7 +3186,9 @@ static int qemudDomainSave(virDomainPtr dom, "-c", NULL }; + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorMigrateToCommand(priv->mon, 0, args, path); + qemuDomainObjExitMonitor(vm); } if (ret < 0) @@ -3193,12 +3259,18 @@ static int qemudDomainCoreDump(virDomainPtr dom, /* Pause domain for non-live dump */ if (vm->state == VIR_DOMAIN_RUNNING) { - if (qemuMonitorStopCPUs(priv->mon) < 0) + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorStopCPUs(priv->mon) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } + qemuDomainObjExitMonitor(vm); paused = 1; } + qemuDomainObjEnterMonitor(vm); ret = qemuMonitorMigrateToCommand(priv->mon, 0, args, path); + qemuDomainObjExitMonitor(vm); paused = 1; cleanup: @@ -3206,11 +3278,13 @@ cleanup: will support synchronous operations so we always get here after the migration is complete. */ if (resume && paused) { + qemuDomainObjEnterMonitor(vm); if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) { if (virGetLastError() == NULL) qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("resuming after dump failed")); } + qemuDomainObjExitMonitor(vm); } if (vm) virDomainObjUnlock(vm); @@ -3724,12 +3798,15 @@ static int qemudDomainRestore(virConnectPtr conn, /* If it was running before, resume it now. */ if (header.was_running) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); if (qemuMonitorStartCPUs(priv->mon, conn) < 0) { if (virGetLastError() == NULL) qemudReportError(conn, NULL, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("failed to resume domain")); + qemuDomainObjExitMonitor(vm); goto cleanup; } + qemuDomainObjExitMonitor(vm); vm->state = VIR_DOMAIN_RUNNING; virDomainSaveStatus(conn, driver->stateDir, vm); } @@ -3772,7 +3849,9 @@ static char *qemudDomainDumpXML(virDomainPtr dom, /* Refresh current memory based on balloon info */ if (virDomainObjIsActive(vm)) { qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); + qemuDomainObjExitMonitor(vm); if (err < 0) goto cleanup; if (err > 0) @@ -4343,11 +4422,13 @@ static int qemudDomainChangeEjectableMedia(virConnectPtr conn, } qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); if (newdisk->src) { ret = qemuMonitorChangeMedia(priv->mon, devname, newdisk->src); } else { ret = qemuMonitorEjectMedia(priv->mon, devname); } + qemuDomainObjExitMonitor(vm); if (ret == 0) { VIR_FREE(origdisk->src); @@ -4364,7 +4445,7 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn, virDomainObjPtr vm, virDomainDeviceDefPtr dev) { - int i; + int i, ret; const char* type = virDomainDiskBusTypeToString(dev->data.disk->bus); qemuDomainObjPrivatePtr priv = vm->privateData; @@ -4381,17 +4462,19 @@ static int qemudDomainAttachPciDiskDevice(virConnectPtr conn, return -1; } - if (qemuMonitorAddPCIDisk(priv->mon, - dev->data.disk->src, - type, - &dev->data.disk->pci_addr.domain, - &dev->data.disk->pci_addr.bus, - &dev->data.disk->pci_addr.slot) < 0) - return -1; + qemuDomainObjEnterMonitor(vm); + ret = qemuMonitorAddPCIDisk(priv->mon, + dev->data.disk->src, + type, + &dev->data.disk->pci_addr.domain, + &dev->data.disk->pci_addr.bus, + &dev->data.disk->pci_addr.slot); + qemuDomainObjExitMonitor(vm); - virDomainDiskInsertPreAlloced(vm->def, dev->data.disk); + if (ret == 0) + virDomainDiskInsertPreAlloced(vm->def, dev->data.disk); - return 0; + return ret; } static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn, @@ -4399,7 +4482,7 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn, virDomainDeviceDefPtr dev) { qemuDomainObjPrivatePtr priv = vm->privateData; - int i; + int i, ret; for (i = 0 ; i < vm->def->ndisks ; i++) { if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) { @@ -4420,12 +4503,14 @@ static int qemudDomainAttachUsbMassstorageDevice(virConnectPtr conn, return -1; } - if (qemuMonitorAddUSBDisk(priv->mon, dev->data.disk->src) < 0) - return -1; + qemuDomainObjEnterMonitor(vm); + ret = qemuMonitorAddUSBDisk(priv->mon, dev->data.disk->src); + qemuDomainObjExitMonitor(vm); - virDomainDiskInsertPreAlloced(vm->def, dev->data.disk); + if (ret == 0) + virDomainDiskInsertPreAlloced(vm->def, dev->data.disk); - return 0; + return ret; } static int qemudDomainAttachNetDevice(virConnectPtr conn, @@ -4481,16 +4566,24 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, if (virAsprintf(&tapfd_name, "fd-%s", net->hostnet_name) < 0) goto no_memory; - if (qemuMonitorSendFileHandle(priv->mon, tapfd_name, tapfd) < 0) + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorSendFileHandle(priv->mon, tapfd_name, tapfd) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } + qemuDomainObjExitMonitor(vm); } if (qemuBuildHostNetStr(conn, net, ' ', net->vlan, tapfd_name, &netstr) < 0) goto try_tapfd_close; - if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorAddHostNetwork(priv->mon, netstr) < 0) { + qemuDomainObjExitMonitor(vm); goto try_tapfd_close; + } + qemuDomainObjExitMonitor(vm); if (tapfd != -1) close(tapfd); @@ -4499,11 +4592,15 @@ static int qemudDomainAttachNetDevice(virConnectPtr conn, if (qemuBuildNicStr(conn, net, NULL, net->vlan, &nicstr) < 0) goto try_remove; + qemuDomainObjEnterMonitor(vm); if (qemuMonitorAddPCINetwork(priv->mon, nicstr, &net->pci_addr.domain, &net->pci_addr.bus, - &net->pci_addr.slot) < 0) + &net->pci_addr.slot) < 0) { + qemuDomainObjExitMonitor(vm); goto try_remove; + } + qemuDomainObjExitMonitor(vm); ret = 0; @@ -4521,15 +4618,22 @@ cleanup: try_remove: if (!net->hostnet_name || net->vlan == 0) VIR_WARN0(_("Unable to remove network backend\n")); - else if (qemuMonitorRemoveHostNetwork(priv->mon, net->vlan, net->hostnet_name) < 0) - VIR_WARN(_("Failed to remove network backend for vlan %d, net %s"), - net->vlan, net->hostnet_name); + else { + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorRemoveHostNetwork(priv->mon, net->vlan, net->hostnet_name) < 0) + VIR_WARN(_("Failed to remove network backend for vlan %d, net %s"), + net->vlan, net->hostnet_name); + qemuDomainObjExitMonitor(vm); + } goto cleanup; try_tapfd_close: - if (tapfd_name && - qemuMonitorCloseFileHandle(priv->mon, tapfd_name) < 0) - VIR_WARN(_("Failed to close tapfd with '%s'\n"), tapfd_name); + if (tapfd_name) { + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorCloseFileHandle(priv->mon, tapfd_name) < 0) + VIR_WARN(_("Failed to close tapfd with '%s'\n"), tapfd_name); + qemuDomainObjExitMonitor(vm); + } goto cleanup; @@ -4546,6 +4650,7 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn, qemuDomainObjPrivatePtr priv = vm->privateData; virDomainHostdevDefPtr hostdev = dev->data.hostdev; pciDevice *pci; + int ret; if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0) { virReportOOMError(conn); @@ -4571,14 +4676,17 @@ static int qemudDomainAttachHostPciDevice(virConnectPtr conn, return -1; } - if (qemuMonitorAddPCIHostDevice(priv->mon, - hostdev->source.subsys.u.pci.domain, - hostdev->source.subsys.u.pci.bus, - hostdev->source.subsys.u.pci.slot, - hostdev->source.subsys.u.pci.function, - &hostdev->source.subsys.u.pci.guest_addr.domain, - &hostdev->source.subsys.u.pci.guest_addr.bus, - &hostdev->source.subsys.u.pci.guest_addr.slot) < 0) + qemuDomainObjEnterMonitor(vm); + ret = qemuMonitorAddPCIHostDevice(priv->mon, + hostdev->source.subsys.u.pci.domain, + hostdev->source.subsys.u.pci.bus, + hostdev->source.subsys.u.pci.slot, + hostdev->source.subsys.u.pci.function, + &hostdev->source.subsys.u.pci.guest_addr.domain, + &hostdev->source.subsys.u.pci.guest_addr.bus, + &hostdev->source.subsys.u.pci.guest_addr.slot); + qemuDomainObjExitMonitor(vm); + if (ret < 0) goto error; vm->def->hostdevs[vm->def->nhostdevs++] = hostdev; @@ -4603,6 +4711,7 @@ static int qemudDomainAttachHostUsbDevice(virConnectPtr conn, return -1; } + qemuDomainObjEnterMonitor(vm); if (dev->data.hostdev->source.subsys.u.usb.vendor) { ret = qemuMonitorAddUSBDeviceMatch(priv->mon, dev->data.hostdev->source.subsys.u.usb.vendor, @@ -4612,6 +4721,7 @@ static int qemudDomainAttachHostUsbDevice(virConnectPtr conn, dev->data.hostdev->source.subsys.u.usb.bus, dev->data.hostdev->source.subsys.u.usb.device); } + qemuDomainObjExitMonitor(vm); if (ret != -1) vm->def->hostdevs[vm->def->nhostdevs++] = dev->data.hostdev; @@ -4804,11 +4914,15 @@ static int qemudDomainDetachPciDiskDevice(virConnectPtr conn, goto cleanup; } + qemuDomainObjEnterMonitor(vm); if (qemuMonitorRemovePCIDevice(priv->mon, detach->pci_addr.domain, detach->pci_addr.bus, - detach->pci_addr.slot) < 0) + detach->pci_addr.slot) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } + qemuDomainObjExitMonitor(vm); if (vm->def->ndisks > 1) { memmove(vm->def->disks + i, @@ -4864,14 +4978,20 @@ qemudDomainDetachNetDevice(virConnectPtr conn, goto cleanup; } + qemuDomainObjEnterMonitor(vm); if (qemuMonitorRemovePCIDevice(priv->mon, detach->pci_addr.domain, detach->pci_addr.bus, - detach->pci_addr.slot) < 0) + detach->pci_addr.slot) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } - if (qemuMonitorRemoveHostNetwork(priv->mon, detach->vlan, detach->hostnet_name) < 0) + if (qemuMonitorRemoveHostNetwork(priv->mon, detach->vlan, detach->hostnet_name) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } + qemuDomainObjExitMonitor(vm); if (vm->def->nnets > 1) { memmove(vm->def->nets + i, @@ -4935,11 +5055,15 @@ static int qemudDomainDetachHostPciDevice(virConnectPtr conn, return -1; } + qemuDomainObjEnterMonitor(vm); if (qemuMonitorRemovePCIDevice(priv->mon, detach->source.subsys.u.pci.guest_addr.domain, detach->source.subsys.u.pci.guest_addr.bus, - detach->source.subsys.u.pci.guest_addr.slot) < 0) + detach->source.subsys.u.pci.guest_addr.slot) < 0) { + qemuDomainObjExitMonitor(vm); return -1; + } + qemuDomainObjExitMonitor(vm); ret = 0; @@ -5369,16 +5493,15 @@ qemudDomainBlockStats (virDomainPtr dom, goto cleanup; qemuDomainObjPrivatePtr priv = vm->privateData; - if (qemuMonitorGetBlockStatsInfo(priv->mon, - qemu_dev_name, - &stats->rd_req, - &stats->rd_bytes, - &stats->wr_req, - &stats->wr_bytes, - &stats->errs) < 0) - goto cleanup; - - ret = 0; + qemuDomainObjEnterMonitor(vm); + ret = qemuMonitorGetBlockStatsInfo(priv->mon, + qemu_dev_name, + &stats->rd_req, + &stats->rd_bytes, + &stats->wr_req, + &stats->wr_bytes, + &stats->errs); + qemuDomainObjExitMonitor(vm); cleanup: VIR_FREE(qemu_dev_name); @@ -5568,13 +5691,19 @@ qemudDomainMemoryPeek (virDomainPtr dom, } qemuDomainObjPrivatePtr priv = vm->privateData; + qemuDomainObjEnterMonitor(vm); if (flags == VIR_MEMORY_VIRTUAL) { - if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) + if (qemuMonitorSaveVirtualMemory(priv->mon, offset, size, tmp) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } } else { - if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) + if (qemuMonitorSavePhysicalMemory(priv->mon, offset, size, tmp) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } } + qemuDomainObjExitMonitor(vm); /* Read the memory file into buffer. */ if (saferead (fd, buffer, size) == (ssize_t) -1) { @@ -6346,12 +6475,17 @@ static int doNativeMigrate(virDomainPtr dom, goto cleanup; } + qemuDomainObjEnterMonitor(vm); if (resource > 0 && - qemuMonitorSetMigrationSpeed(priv->mon, resource) < 0) + qemuMonitorSetMigrationSpeed(priv->mon, resource) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } - if (qemuMonitorMigrateToHost(priv->mon, 0, uribits->server, uribits->port) < 0) + if (qemuMonitorMigrateToHost(priv->mon, 0, uribits->server, uribits->port) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } /* it is also possible that the migrate didn't fail initially, but * rather failed later on. Check the output of "info migrate" @@ -6361,8 +6495,10 @@ static int doNativeMigrate(virDomainPtr dom, &transferred, &remaining, &total) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; } + qemuDomainObjExitMonitor(vm); if (status != QEMU_MONITOR_MIGRATION_STATUS_COMPLETED) { qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, @@ -6519,6 +6655,7 @@ static int doTunnelMigrate(virDomainPtr dom, goto cleanup; /* 3. start migration on source */ + qemuDomainObjEnterMonitor(vm); if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_UNIX) internalret = qemuMonitorMigrateToUnix(priv->mon, 1, unixfile); else if (qemuCmdFlags & QEMUD_CMD_FLAG_MIGRATE_QEMU_EXEC) { @@ -6527,6 +6664,7 @@ static int doTunnelMigrate(virDomainPtr dom, } else { internalret = -1; } + qemuDomainObjExitMonitor(vm); if (internalret < 0) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, "%s", _("tunnelled migration monitor command failed")); @@ -6539,13 +6677,16 @@ static int doTunnelMigrate(virDomainPtr dom, /* it is also possible that the migrate didn't fail initially, but * rather failed later on. Check the output of "info migrate" */ + qemuDomainObjEnterMonitor(vm); if (qemuMonitorGetMigrationStatus(priv->mon, &status, &transferred, &remaining, &total) < 0) { + qemuDomainObjExitMonitor(vm); goto cancel; } + qemuDomainObjExitMonitor(vm); if (status == QEMU_MONITOR_MIGRATION_STATUS_ERROR) { qemudReportError(dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED, @@ -6565,8 +6706,11 @@ static int doTunnelMigrate(virDomainPtr dom, retval = doTunnelSendAll(dom, st, client_sock); cancel: - if (retval != 0) + if (retval != 0) { + qemuDomainObjEnterMonitor(vm); qemuMonitorMigrateCancel(priv->mon); + qemuDomainObjExitMonitor(vm); + } finish: dname = dname ? dname : dom->name; @@ -6729,8 +6873,12 @@ qemudDomainMigratePerform (virDomainPtr dom, if (!(flags & VIR_MIGRATE_LIVE)) { qemuDomainObjPrivatePtr priv = vm->privateData; /* Pause domain for non-live migration */ - if (qemuMonitorStopCPUs(priv->mon) < 0) + qemuDomainObjEnterMonitor(vm); + if (qemuMonitorStopCPUs(priv->mon) < 0) { + qemuDomainObjExitMonitor(vm); goto cleanup; + } + qemuDomainObjExitMonitor(vm); paused = 1; event = virDomainEventNewFromObj(vm, @@ -6768,6 +6916,7 @@ cleanup: if (paused) { qemuDomainObjPrivatePtr priv = vm->privateData; /* we got here through some sort of failure; start the domain again */ + qemuDomainObjEnterMonitor(vm); if (qemuMonitorStartCPUs(priv->mon, dom->conn) < 0) { /* Hm, we already know we are in error here. We don't want to * overwrite the previous error, though, so we just throw something @@ -6776,6 +6925,7 @@ cleanup: VIR_ERROR(_("Failed to resume guest %s after failure\n"), vm->def->name); } + qemuDomainObjExitMonitor(vm); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED, @@ -6853,12 +7003,15 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn, * >= 0.10.6 to work properly. This isn't strictly necessary on * older qemu's, but it also doesn't hurt anything there */ + qemuDomainObjEnterMonitor(vm); if (qemuMonitorStartCPUs(priv->mon, dconn) < 0) { if (virGetLastError() == NULL) qemudReportError(dconn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("resume operation failed")); + qemuDomainObjExitMonitor(vm); goto cleanup; } + qemuDomainObjExitMonitor(vm); vm->state = VIR_DOMAIN_RUNNING; event = virDomainEventNewFromObj(vm, diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 46d5d9f..fd1c5e9 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -39,6 +39,8 @@ #define VIR_FROM_THIS VIR_FROM_QEMU struct _qemuMonitor { + virMutex lock; + int fd; int watch; int hasSendFD; @@ -49,6 +51,16 @@ struct _qemuMonitor { qemuMonitorDiskSecretLookup secretCB; }; +void qemuMonitorLock(qemuMonitorPtr mon) +{ + virMutexLock(&mon->lock); +} + +void qemuMonitorUnlock(qemuMonitorPtr mon) +{ + virMutexUnlock(&mon->lock); +} + /* Return -1 for error, 1 to continue reading and 0 for success */ typedef int qemuMonitorHandleOutput(virDomainObjPtr vm, const char *output); @@ -292,6 +304,12 @@ qemuMonitorOpen(virDomainObjPtr vm, return NULL; } + if (virMutexInit(&mon->lock) < 0) { + qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot initialize monitor mutex")); + VIR_FREE(mon); + return NULL; + } mon->fd = -1; mon->vm = vm; mon->eofCB = eofCB; @@ -343,6 +361,7 @@ void qemuMonitorClose(qemuMonitorPtr mon) if (mon->fd != -1) close(mon->fd); + virMutexDestroy(&mon->lock); VIR_FREE(mon); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 5f06155..a8d517c 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -54,6 +54,9 @@ qemuMonitorPtr qemuMonitorOpen(virDomainObjPtr vm, void qemuMonitorClose(qemuMonitorPtr mon); +void qemuMonitorLock(qemuMonitorPtr mon); +void qemuMonitorUnlock(qemuMonitorPtr mon); + void qemuMonitorRegisterDiskSecretLookup(qemuMonitorPtr mon, qemuMonitorDiskSecretLookup secretCB); -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list