[libvirt] [PATCH] Ignore qemu STOP event when stopping CPUs
Daniel Veillard
veillard at redhat.com
Tue Apr 27 09:51:50 UTC 2010
On Tue, Apr 27, 2010 at 11:20:39AM +0200, jdenemar at redhat.com wrote:
> From: Jiri Denemark <jdenemar at redhat.com>
>
> With JSON qemu monitor, we get a STOP event from qemu whenever qemu
> stops guests CPUs. The downside of it is that vm->state is changed to
> PAUSED and a new generic paused event is send to applications. However,
> when we ask qemu to stop the CPUs we are not really interested in qemu
> event and we usually want to issue a more specific event.
>
> By setting vm->status to PAUSED before actually sending the request to
> qemu (and resetting it back if the request fails) we can ignore the
> event since the event handler does nothing when the guest is already
> paused. This solution is quite hacky but unfortunately it's the best
> solution which I was able to come up with and it doesn't introduce a
> race condition.
> ---
> src/qemu/qemu_driver.c | 25 +++++++++++++++++++------
> 1 files changed, 19 insertions(+), 6 deletions(-)
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 3c4876e..8ccf0b7 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -4117,13 +4117,16 @@ static int qemudDomainSuspend(virDomainPtr dom) {
> }
> if (vm->state != VIR_DOMAIN_PAUSED) {
> int rc;
> + int state = vm->state;
>
> + vm->state = VIR_DOMAIN_PAUSED;
> qemuDomainObjEnterMonitorWithDriver(driver, vm);
> rc = qemuMonitorStopCPUs(priv->mon);
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> - if (rc < 0)
> + if (rc < 0) {
> + vm->state = state;
> goto endjob;
> - vm->state = VIR_DOMAIN_PAUSED;
> + }
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_SUSPENDED,
> VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
> @@ -4491,8 +4494,10 @@ qemuDomainMigrateOffline(struct qemud_driver *driver,
> virDomainObjPtr vm)
> {
> qemuDomainObjPrivatePtr priv = vm->privateData;
> + int state = vm->state;
> int ret;
>
> + vm->state = VIR_DOMAIN_PAUSED;
> qemuDomainObjEnterMonitorWithDriver(driver, vm);
> ret = qemuMonitorStopCPUs(priv->mon);
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> @@ -4500,13 +4505,13 @@ qemuDomainMigrateOffline(struct qemud_driver *driver,
> if (ret == 0) {
> virDomainEventPtr event;
>
> - vm->state = VIR_DOMAIN_PAUSED;
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_SUSPENDED,
> VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED);
> if (event)
> qemuDomainEventQueue(driver, event);
> - }
> + } else
> + vm->state = state;
>
> return ret;
> }
> @@ -4743,13 +4748,14 @@ static int qemudDomainSaveFlag(virDomainPtr dom, const char *path,
> /* Pause */
> if (vm->state == VIR_DOMAIN_RUNNING) {
> header.was_running = 1;
> + vm->state = VIR_DOMAIN_PAUSED;
> qemuDomainObjEnterMonitorWithDriver(driver, vm);
> if (qemuMonitorStopCPUs(priv->mon) < 0) {
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> + vm->state = VIR_DOMAIN_RUNNING;
> goto endjob;
> }
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> - vm->state = VIR_DOMAIN_PAUSED;
> }
>
> /* Get XML for the domain */
> @@ -5167,9 +5173,11 @@ static int qemudDomainCoreDump(virDomainPtr dom,
>
> /* Pause domain for non-live dump */
> if (!(flags & VIR_DUMP_LIVE) && vm->state == VIR_DOMAIN_RUNNING) {
> + vm->state = VIR_DOMAIN_PAUSED;
> qemuDomainObjEnterMonitorWithDriver(driver, vm);
> if (qemuMonitorStopCPUs(priv->mon) < 0) {
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> + vm->state = VIR_DOMAIN_RUNNING;
> goto endjob;
> }
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> @@ -5214,6 +5222,7 @@ endjob:
> "%s", _("resuming after dump failed"));
> }
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> + vm->state = VIR_DOMAIN_RUNNING;
> }
>
> if (qemuDomainObjEndJob(vm) == 0)
> @@ -11056,12 +11065,16 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
> /* qemu unconditionally starts the domain running again after
> * loadvm, so let's pause it to keep consistency
> */
> + int state = vm->state;
> priv = vm->privateData;
> + vm->state = VIR_DOMAIN_PAUSED;
> qemuDomainObjEnterMonitorWithDriver(driver, vm);
> rc = qemuMonitorStopCPUs(priv->mon);
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> - if (rc < 0)
> + if (rc < 0) {
> + vm->state = state;
> goto cleanup;
> + }
> }
>
> event = virDomainEventNewFromObj(vm,
Hum, that sounds reasonnable, yes. All those operations should already
emit a more specific event, if that's the case, ACK.
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list