]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemuDomainChangeEjectableMedia: Unlock domain while waiting for event
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 20 May 2013 17:26:14 +0000 (19:26 +0200)
committerCole Robinson <crobinso@redhat.com>
Wed, 12 Jun 2013 20:29:12 +0000 (16:29 -0400)
In 84c59ffa I've tried to fix changing ejectable media process. The
process should go like this:

1) we need to call 'eject' on the monitor
2) we should wait for 'DEVICE_TRAY_MOVED' event
3) now we can issue 'change' command

However, while waiting in step 2) the domain monitor was locked. So
even if qemu reported the desired event, the proper callback was not
called immediately. The monitor handling code needs to lock the
monitor in order to read the event. So that's the first lock we must
not hold while waiting. The second one is the domain lock. When
monitor handling code reads an event, the appropriate callback is
called then. The first thing that each callback does is locking the
corresponding domain as a domain or its device is about to change
state. So we need to unlock both monitor and VM lock. Well, holding
any lock while sleep()-ing is not the best thing to do anyway.
(cherry picked from commit 543af79a14f06cd16844c28887210bbb93a455fa)

Conflicts:
src/qemu/qemu_hotplug.c

src/qemu/qemu_hotplug.c

index 876b3791b537c9186caf68ea62234d36d4b1f8bd..3cc1d8dd99d5ff70245d8c61ab9ec3ceb3e84a3e 100644 (file)
@@ -105,15 +105,20 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver,
 
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
     ret = qemuMonitorEjectMedia(priv->mon, driveAlias, force);
+    qemuDomainObjExitMonitor(driver, vm);
 
+    virObjectRef(vm);
     /* we don't want to report errors from media tray_open polling */
     while (retries--) {
         if (origdisk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN)
             break;
 
+        virDomainObjUnlock(vm);
         VIR_DEBUG("Waiting 500ms for tray to open. Retries left %d", retries);
         usleep(500 * 1000); /* sleep 500ms */
+        virDomainObjLock(vm);
     }
+    virObjectUnref(vm);
 
     if (disk->src) {
         /* deliberately don't depend on 'ret' as 'eject' may have failed for the
@@ -126,7 +131,7 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver,
         if (retries <= 0) {
             virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                            _("Unable to eject media before changing it"));
-            goto exit_monitor;
+            goto audit;
         }
 
         if (disk->type != VIR_DOMAIN_DISK_TYPE_DIR) {
@@ -135,13 +140,14 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *driver,
             else if (origdisk->driverType)
                 format = origdisk->driverType;
         }
+        qemuDomainObjEnterMonitor(driver, vm);
         ret = qemuMonitorChangeMedia(priv->mon,
                                      driveAlias,
                                      disk->src, format);
+        qemuDomainObjExitMonitor(driver, vm);
     }
-exit_monitor:
-    qemuDomainObjExitMonitorWithDriver(driver, vm);
 
+audit:
     virDomainAuditDisk(vm, origdisk->src, disk->src, "update", ret >= 0);
 
     if (ret < 0)