[libvirt] [PATCH] qemu: check for vm after starting a job

Daniel P. Berrange berrange at redhat.com
Wed Oct 27 14:08:05 UTC 2010


On Tue, Oct 26, 2010 at 05:32:09PM -0600, Eric Blake wrote:
> https://bugzilla.redhat.com/show_bug.cgi?id=638285 - when migrating
> a guest, it was very easy to provoke a race where an application
> could query block information on a VM that had just been migrated
> away.  Any time qemu code obtains a job lock, it must also check
> that the VM was not taken down in the time where it was waiting
> for the lock.
> 
> * src/qemu/qemu_driver.c (qemudDomainSetMemory)
> (qemudDomainGetInfo, qemuDomainGetBlockInfo): Check that vm still
> exists after obtaining job lock, before starting monitor action.
> ---
>  src/qemu/qemu_driver.c |   25 ++++++++++++++++++++++---
>  1 files changed, 22 insertions(+), 3 deletions(-)
> 
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index ae1d833..af5126d 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -463,7 +463,8 @@ static int ATTRIBUTE_RETURN_CHECK qemuDomainObjEndJob(virDomainObjPtr obj)
>   * obj must be locked before calling, qemud_driver must be unlocked
>   *
>   * To be called immediately before any QEMU monitor API call
> - * Must have alrady called qemuDomainObjBeginJob().
> + * Must have already called qemuDomainObjBeginJob(), and checked
> + * that the VM is still active.
>   *
>   * To be followed with qemuDomainObjExitMonitor() once complete
>   */
> @@ -504,7 +505,7 @@ static void qemuDomainObjExitMonitor(virDomainObjPtr obj)
>   * obj must be locked before calling, qemud_driver must be locked
>   *
>   * To be called immediately before any QEMU monitor API call
> - * Must have alrady called qemuDomainObjBeginJob().
> + * Must have already called qemuDomainObjBeginJob().
>   *
>   * To be followed with qemuDomainObjExitMonitorWithDriver() once complete
>   */
> @@ -522,7 +523,7 @@ static void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver, vir
>  /* obj must NOT be locked before calling, qemud_driver must be unlocked,
>   * and will be locked after returning
>   *
> - * Should be paired with an earlier  qemuDomainObjEnterMonitor() call
> + * Should be paired with an earlier  qemuDomainObjEnterMonitorWithDriver() call
>   */
>  static void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver, virDomainObjPtr obj)
>  {
> @@ -4948,6 +4949,12 @@ static int qemudDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
>      if (qemuDomainObjBeginJob(vm) < 0)
>          goto cleanup;
> 
> +    if (!virDomainObjIsActive(vm)) {
> +        qemuReportError(VIR_ERR_OPERATION_INVALID,
> +                        "%s", _("domain is not running"));
> +        goto endjob;
> +    }
> +

There is already an IsActive check in this method, it is simply in
the wrong place wrt to the BeginJob call, so it is better to just
move the existing call, rather than duplicate it i reckon.

> @@ -5014,11 +5021,17 @@ static int qemudDomainGetInfo(virDomainPtr dom,
>          } else if (!priv->jobActive) {
>              if (qemuDomainObjBeginJob(vm) < 0)
>                  goto cleanup;
> +            if (!virDomainObjIsActive(vm)) {
> +                qemuReportError(VIR_ERR_OPERATION_INVALID,
> +                                "%s", _("domain is not running"));
> +                goto endjob;
> +            }
> 
>              qemuDomainObjEnterMonitor(vm);
>              err = qemuMonitorGetBalloonInfo(priv->mon, &balloon);
>              qemuDomainObjExitMonitor(vm);
>              if (err < 0) {
> +            endjob:
>                  if (qemuDomainObjEndJob(vm) == 0)
>                      vm = NULL;
>                  goto cleanup;
> @@ -10343,6 +10356,11 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
>          qemuDomainObjPrivatePtr priv = vm->privateData;
>          if (qemuDomainObjBeginJob(vm) < 0)
>              goto cleanup;
> +        if (!virDomainObjIsActive(vm)) {
> +            qemuReportError(VIR_ERR_OPERATION_INVALID,
> +                            "%s", _("domain is not running"));
> +            goto endjob;
> +        }
> 
>          qemuDomainObjEnterMonitor(vm);
>          ret = qemuMonitorGetBlockExtent(priv->mon,
> @@ -10350,6 +10368,7 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom,
>                                          &info->allocation);
>          qemuDomainObjExitMonitor(vm);
> 
> +    endjob:
>          if (qemuDomainObjEndJob(vm) == 0)
>              vm = NULL;
>      } else {

I'm not much of a fan of adding goto jump targets which are in the middle
of long methods. Could we just invert the IsActive checks in these two
methods & thus avoid the 'endjob' in the middle of the method.

Regards,
Daniel
-- 
|: Red Hat, Engineering, London    -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://deltacloud.org :|
|: http://autobuild.org        -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list