
On Fri, Feb 25, 2011 at 07:04:11PM +0100, Jiri Denemark wrote:
--- src/qemu/qemu_driver.c | 37 ++++++++++++++++++++++++++++++++----- 1 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index ba046d7..a02d1b9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6041,21 +6041,47 @@ cleanup:
/* The domain is expected to be locked and active. */ static int -qemuDomainSnapshotCreateActive(struct qemud_driver *driver, +qemuDomainSnapshotCreateActive(virConnectPtr conn, + struct qemud_driver *driver, virDomainObjPtr *vmptr, virDomainSnapshotObjPtr snap) { virDomainObjPtr vm = *vmptr; qemuDomainObjPrivatePtr priv = vm->privateData; - int ret; + bool resume = false; + int ret = -1;
if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) return -1;
+ if (vm->state == VIR_DOMAIN_RUNNING) { + /* savevm monitor command pauses the domain emitting an event which + * confuses libvirt since it's not notified when qemu resumes the + * domain. Thus we stop and start CPUs ourselves. + */
Not having a resume event from QEMU sounds like a QEMU bug, right ?
+ if (qemuProcessStopCPUs(driver, vm) < 0) + goto cleanup; + + resume = true; + if (!virDomainObjIsActive(vm)) { + qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("guest unexpectedly quit")); + goto cleanup; + } + } + qemuDomainObjEnterMonitorWithDriver(driver, vm); ret = qemuMonitorCreateSnapshot(priv->mon, snap->def->name); qemuDomainObjExitMonitorWithDriver(driver, vm);
+cleanup: + if (resume && virDomainObjIsActive(vm) && + qemuProcessStartCPUs(driver, vm, conn) < 0 && + virGetLastError() == NULL) { + qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("resuming after snapshot failed")); + } + if (qemuDomainObjEndJob(vm) == 0) *vmptr = NULL;
@@ -6100,18 +6126,19 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain, if (!(snap = virDomainSnapshotAssignDef(&vm->snapshots, def))) goto cleanup;
+ snap->def->state = vm->state; + /* actually do the snapshot */ if (!virDomainObjIsActive(vm)) { if (qemuDomainSnapshotCreateInactive(vm, snap) < 0) goto cleanup; } else { - if (qemuDomainSnapshotCreateActive(driver, &vm, snap) < 0) + if (qemuDomainSnapshotCreateActive(domain->conn, driver, + &vm, snap) < 0) goto cleanup; }
- snap->def->state = vm->state; - /* FIXME: if we fail after this point, there's not a whole lot we can * do; we've successfully taken the snapshot, and we are now running * on it, so we have to go forward the best we can
ACK Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|