[libvirt] [PATCH 4/6] qemu: use virObject to manage reference-counting for qemu monitor
Daniel P. Berrange
berrange at redhat.com
Thu Apr 7 09:38:34 UTC 2011
On Wed, Apr 06, 2011 at 03:19:55PM +0800, Hu Tao wrote:
> ---
> src/qemu/qemu_domain.c | 30 ++-----------
> src/qemu/qemu_migration.c | 2 -
> src/qemu/qemu_monitor.c | 109 ++++++++++++++++++++++++--------------------
> src/qemu/qemu_monitor.h | 4 +-
> src/qemu/qemu_process.c | 32 +++++++-------
> 5 files changed, 81 insertions(+), 96 deletions(-)
>
> diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
> index 3a3c953..d11dc5f 100644
> --- a/src/qemu/qemu_domain.c
> +++ b/src/qemu/qemu_domain.c
> @@ -560,9 +560,8 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj)
> {
> qemuDomainObjPrivatePtr priv = obj->privateData;
>
> - qemuMonitorLock(priv->mon);
> - qemuMonitorRef(priv->mon);
> virDomainObjUnlock(obj);
> + qemuMonitorLock(priv->mon);
> }
>
>
> @@ -573,18 +572,9 @@ void qemuDomainObjEnterMonitor(virDomainObjPtr obj)
> void qemuDomainObjExitMonitor(virDomainObjPtr obj)
> {
> qemuDomainObjPrivatePtr priv = obj->privateData;
> - int refs;
> -
> - refs = qemuMonitorUnref(priv->mon);
> -
> - if (refs > 0)
> - qemuMonitorUnlock(priv->mon);
>
> + qemuMonitorUnlock(priv->mon);
> virDomainObjLock(obj);
> -
> - if (refs == 0) {
> - priv->mon = NULL;
> - }
> }
>
>
> @@ -601,10 +591,8 @@ void qemuDomainObjEnterMonitorWithDriver(struct qemud_driver *driver,
> {
> qemuDomainObjPrivatePtr priv = obj->privateData;
>
> - qemuMonitorLock(priv->mon);
> - qemuMonitorRef(priv->mon);
> virDomainObjUnlock(obj);
> - qemuDriverUnlock(driver);
> + qemuMonitorLock(priv->mon);
> }
>
>
> @@ -617,19 +605,9 @@ void qemuDomainObjExitMonitorWithDriver(struct qemud_driver *driver,
> virDomainObjPtr obj)
> {
> qemuDomainObjPrivatePtr priv = obj->privateData;
> - int refs;
> -
> - refs = qemuMonitorUnref(priv->mon);
> -
> - if (refs > 0)
> - qemuMonitorUnlock(priv->mon);
>
> - qemuDriverLock(driver);
> + qemuMonitorUnlock(priv->mon);
> virDomainObjLock(obj);
> -
> - if (refs == 0) {
> - priv->mon = NULL;
> - }
> }
This means that the 'driver' lock is now whenever any QEMU
monitor command is runing, which blocks the entire driver.
>
> void qemuDomainObjEnterRemoteWithDriver(struct qemud_driver *driver,
> diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
> index 462e6be..6af2e24 100644
> --- a/src/qemu/qemu_migration.c
> +++ b/src/qemu/qemu_migration.c
> @@ -224,11 +224,9 @@ qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm)
> }
>
> virDomainObjUnlock(vm);
> - qemuDriverUnlock(driver);
>
> nanosleep(&ts, NULL);
>
> - qemuDriverLock(driver);
> virDomainObjLock(vm);
> }
Holding the 'driver' lock while sleeping blocks the entire
QEMU driver.
> diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
> index 244b22a..4b9087f 100644
> --- a/src/qemu/qemu_process.c
> +++ b/src/qemu/qemu_process.c
> @@ -107,7 +107,6 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
>
> VIR_DEBUG("Received EOF on %p '%s'", vm, vm->def->name);
>
> - qemuDriverLock(driver);
> virDomainObjLock(vm);
>
> if (!virDomainObjIsActive(vm)) {
> @@ -133,15 +132,17 @@ qemuProcessHandleMonitorEOF(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
> qemuProcessStop(driver, vm, 0);
> qemuAuditDomainStop(vm, hasError ? "failed" : "shutdown");
>
> - if (!vm->persistent)
> + if (!vm->persistent) {
> + qemuDriverLock(driver);
> virDomainRemoveInactive(&driver->domains, vm);
> - else
> - virDomainObjUnlock(vm);
> + qemuDriverUnlock(driver);
> + }
> +
> + virDomainObjUnlock(vm);
>
> if (event) {
> qemuDomainEventQueue(driver, event);
> }
> - qemuDriverUnlock(driver);
> }
This violates the lock ordering rules. The 'driver' lock *must* be
obtained *before* any 'vm' lock is held.
Now we have some places in the code which do
lock(vm)
lock(driver)
and other places which do
lock(driver)
lock(vm)
so 2 threads can trivially deadlock waiting for each other
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 :|
More information about the libvir-list
mailing list