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

[libvirt] [PATCH v2] qemu_hotplug: Rework media changing process



https://bugzilla.redhat.com/show_bug.cgi?id=892289

It seems like with new udev within guest OS, the tray is locked,
so we need to:
- 'eject'
- wait for tray to open
- 'change'

Moreover, even when doing bare 'eject', we should check for
'tray_open' as guest may have locked the tray. However, the
waiting phase shouldn't be unbounded, so I've chosen 10 retries
maximum, each per 500ms. This should give enough time for guest
to eject a media and open the tray.
---

diff to v1:
- listen to TRAY event instead of active polling

 src/qemu/qemu_hotplug.c | 30 +++++++++++++++++++++++++++---
 1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 8103183..18c4109 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -48,6 +48,7 @@
 #include "virstoragefile.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
+#define CHANGE_MEDIA_RETRIES 10
 
 int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
                                    virDomainObjPtr vm,
@@ -59,6 +60,7 @@ int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
     int ret;
     char *driveAlias = NULL;
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    int retries = CHANGE_MEDIA_RETRIES;
 
     for (i = 0 ; i < vm->def->ndisks ; i++) {
         if (vm->def->disks[i]->bus == disk->bus &&
@@ -86,7 +88,7 @@ int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
         origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("Removable media not supported for %s device"),
-                        virDomainDiskDeviceTypeToString(disk->device));
+                       virDomainDiskDeviceTypeToString(disk->device));
         return -1;
     }
 
@@ -105,8 +107,31 @@ int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
         goto error;
 
     qemuDomainObjEnterMonitorWithDriver(driver, vm);
+    ret = qemuMonitorEjectMedia(priv->mon, driveAlias, force);
+
+    /* we don't want to report errors from media tray_open polling */
+    while (retries--) {
+        if (origdisk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN)
+            break;
+
+        VIR_DEBUG("Waiting 500ms for tray to open. Retries left %d", retries);
+        usleep(500 * 1000); /* sleep 500ms */
+    }
+
     if (disk->src) {
+        /* deliberately don't depend on 'ret' as 'eject' may have failed for the
+         * fist time and we are gonna check the drive state anyway */
         const char *format = NULL;
+
+        /* We haven't succeeded yet */
+        ret = -1;
+
+        if (retries <= 0) {
+            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                           _("Unable to eject media before changing it"));
+            goto exit_monitor;
+        }
+
         if (disk->type != VIR_DOMAIN_DISK_TYPE_DIR) {
             if (disk->format > 0)
                 format = virStorageFileFormatTypeToString(disk->format);
@@ -116,9 +141,8 @@ int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
         ret = qemuMonitorChangeMedia(priv->mon,
                                      driveAlias,
                                      disk->src, format);
-    } else {
-        ret = qemuMonitorEjectMedia(priv->mon, driveAlias, force);
     }
+exit_monitor:
     qemuDomainObjExitMonitorWithDriver(driver, vm);
 
     virDomainAuditDisk(vm, origdisk->src, disk->src, "update", ret >= 0);
-- 
1.8.0.2


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