Re: [PATCH] qemu: respect locking rules

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Mar 14, 2011 at 08:38:09PM -0600, Eric Blake wrote:
> THREADS.txt states that the contents of vm should not be read or
> modified while the vm lock is not held, but that the lock must not
> be held while performing a monitor command.  This fixes all the
> offenders that I could find.
> 
> * src/qemu/qemu_process.c (qemuProcessStartCPUs)
> (qemuProcessInitPasswords, qemuProcessStart): Don't modify or
> refer to vm state outside lock.
> * src/qemu/qemu_driver.c (qemudDomainHotplugVcpus): Likewise.
> * src/qemu/qemu_hotplug.c (qemuDomainChangeGraphicsPasswords):
> Likewise.
> ---
> 
> Most of these just move the vm manipulation outside the monitor lock.
> qemu_hotplug is a case of checking if the vm is active in between two
> monitor commands while the monitor lock was not dropped.  Technically,
> this was wasted - the qemu process might have stopped (independently,
> such as from a guest shutdown), but as long as we hold the monitor
> lock, the monitor object will react correctly even if the underlying
> qemu process goes away in between the two monitor commands.  The
> alternative would have been to drop monitor lock, regain vm lock, keep
> the check that vm is still active but now under the correct lock, then
> regain monitor lock and drop vm lock.
> 
> My only question is whether qemuProcessStartCPUs needs to be careful
> to check if the VM is still active when it regains the vm lock, since
> it is possible that the guest shutdown in the window between the
> monitor command resuming the CPUs and when the vm lock is regained -
> that is, blindly setting vm->state to VIR_DOMAIN_RUNNING seems fishy
> if the vm went away during the window.  However, when I tested this
> under gdb, by setting a breakpoint in that window and causing the
> guest to shutdown, it looked like everything recovered gracefully.
> And if we do start checking after a monitor exit that the vm is still
> active before changing state of the vm object, then we should probably
> adopt that convention everywhere.
> 
>  src/qemu/qemu_driver.c  |   12 +++++++-----
>  src/qemu/qemu_hotplug.c |    7 -------
>  src/qemu/qemu_process.c |   18 +++++++++++-------
>  3 files changed, 18 insertions(+), 19 deletions(-)
> 
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index dac2bf2..c8870b1 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -2553,14 +2553,15 @@ static int qemudDomainHotplugVcpus(virDomainObjPtr vm, unsigned int nvcpus)
>      int i, rc = 1;
>      int ret = -1;
>      int oldvcpus = vm->def->vcpus;
> +    int vcpus = oldvcpus;
> 
>      qemuDomainObjEnterMonitor(vm);
> 
>      /* We need different branches here, because we want to offline
>       * in reverse order to onlining, so any partial fail leaves us in a
>       * reasonably sensible state */
> -    if (nvcpus > vm->def->vcpus) {
> -        for (i = vm->def->vcpus ; i < nvcpus ; i++) {
> +    if (nvcpus > vcpus) {
> +        for (i = vcpus ; i < nvcpus ; i++) {
>              /* Online new CPU */
>              rc = qemuMonitorSetCPU(priv->mon, i, 1);
>              if (rc == 0)
> @@ -2568,10 +2569,10 @@ static int qemudDomainHotplugVcpus(virDomainObjPtr vm, unsigned int nvcpus)
>              if (rc < 0)
>                  goto cleanup;
> 
> -            vm->def->vcpus++;
> +            vcpus++;
>          }
>      } else {
> -        for (i = vm->def->vcpus - 1 ; i >= nvcpus ; i--) {
> +        for (i = vcpus - 1 ; i >= nvcpus ; i--) {
>              /* Offline old CPU */
>              rc = qemuMonitorSetCPU(priv->mon, i, 0);
>              if (rc == 0)
> @@ -2579,7 +2580,7 @@ static int qemudDomainHotplugVcpus(virDomainObjPtr vm, unsigned int nvcpus)
>              if (rc < 0)
>                  goto cleanup;
> 
> -            vm->def->vcpus--;
> +            vcpus--;
>          }
>      }
> 
> @@ -2587,6 +2588,7 @@ static int qemudDomainHotplugVcpus(virDomainObjPtr vm, unsigned int nvcpus)
> 
>  cleanup:
>      qemuDomainObjExitMonitor(vm);
> +    vm->def->vcpus = vcpus;
>      qemuAuditVcpu(vm, oldvcpus, nvcpus, "update", rc == 1);
>      return ret;
> 
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index e4ba526..e1d9d29 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -1836,13 +1836,6 @@ qemuDomainChangeGraphicsPasswords(struct qemud_driver *driver,
>      if (ret != 0)
>          goto cleanup;
> 
> -    if (!virDomainObjIsActive(vm)) {
> -        ret = -1;
> -        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> -                        _("guest unexpectedly quit"));
> -        goto cleanup;
> -    }
> -
>      if (auth->expires) {
>          time_t lifetime = auth->validTo - now;
>          if (lifetime <= 0)
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index 740684a..793a43c 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -1008,8 +1008,8 @@ qemuProcessWaitForMonitor(struct qemud_driver* driver,
>      if (paths == NULL)
>          goto cleanup;
> 
> -    qemuDomainObjEnterMonitorWithDriver(driver, vm);
>      qemuDomainObjPrivatePtr priv = vm->privateData;
> +    qemuDomainObjEnterMonitorWithDriver(driver, vm);
>      ret = qemuMonitorGetPtyPaths(priv->mon, paths);
>      qemuDomainObjExitMonitorWithDriver(driver, vm);
> 
> @@ -1175,6 +1175,7 @@ qemuProcessInitPasswords(virConnectPtr conn,
>          for (i = 0 ; i < vm->def->ndisks ; i++) {
>              char *secret;
>              size_t secretLen;
> +            const char *alias;
> 
>              if (!vm->def->disks[i]->encryption ||
>                  !vm->def->disks[i]->src)
> @@ -1185,10 +1186,9 @@ qemuProcessInitPasswords(virConnectPtr conn,
>                                                     &secret, &secretLen) < 0)
>                  goto cleanup;
> 
> +            alias = vm->def->disks[i]->info.alias;
>              qemuDomainObjEnterMonitorWithDriver(driver, vm);
> -            ret = qemuMonitorSetDrivePassphrase(priv->mon,
> -                                                vm->def->disks[i]->info.alias,
> -                                                secret);
> +            ret = qemuMonitorSetDrivePassphrase(priv->mon, alias, secret);
>              VIR_FREE(secret);
>              qemuDomainObjExitMonitorWithDriver(driver, vm);
>              if (ret < 0)
> @@ -1727,17 +1727,19 @@ qemuProcessPrepareMonitorChr(struct qemud_driver *driver,
>  }
> 
> 
> -int qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm, virConnectPtr conn)
> +int
> +qemuProcessStartCPUs(struct qemud_driver *driver, virDomainObjPtr vm,
> +                     virConnectPtr conn)
>  {
>      int ret;
>      qemuDomainObjPrivatePtr priv = vm->privateData;
> 
>      qemuDomainObjEnterMonitorWithDriver(driver, vm);
>      ret = qemuMonitorStartCPUs(priv->mon, conn);
> +    qemuDomainObjExitMonitorWithDriver(driver, vm);
>      if (ret == 0) {
>          vm->state = VIR_DOMAIN_RUNNING;
>      }
> -    qemuDomainObjExitMonitorWithDriver(driver, vm);
> 
>      return ret;
>  }
> @@ -1901,6 +1903,7 @@ int qemuProcessStart(virConnectPtr conn,
>      qemuDomainObjPrivatePtr priv = vm->privateData;
>      virCommandPtr cmd = NULL;
>      struct qemuProcessHookData hookData;
> +    unsigned long cur_balloon;
> 
>      hookData.conn = conn;
>      hookData.vm = vm;
> @@ -2210,8 +2213,9 @@ int qemuProcessStart(virConnectPtr conn,
>      }
> 
>      VIR_DEBUG0("Setting initial memory amount");
> +    cur_balloon = vm->def->mem.cur_balloon;
>      qemuDomainObjEnterMonitorWithDriver(driver, vm);
> -    if (qemuMonitorSetBalloon(priv->mon, vm->def->mem.cur_balloon) < 0) {
> +    if (qemuMonitorSetBalloon(priv->mon, cur_balloon) < 0) {
>          qemuDomainObjExitMonitorWithDriver(driver, vm);
>          goto cleanup;
>      }

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 :|

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]