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