|
|
7a3408 |
From cc6d958b1ba9efb26ca5b28c575369e335b1e7a0 Mon Sep 17 00:00:00 2001
|
|
|
7a3408 |
Message-Id: <cc6d958b1ba9efb26ca5b28c575369e335b1e7a0@dist-git>
|
|
|
7a3408 |
From: Pavel Hrdina <phrdina@redhat.com>
|
|
|
7a3408 |
Date: Fri, 10 Jul 2015 12:39:32 +0200
|
|
|
7a3408 |
Subject: [PATCH] qemu_hotplug: try harder to eject media
|
|
|
7a3408 |
|
|
|
7a3408 |
Some guests lock the tray and QEMU eject command will simply fail to
|
|
|
7a3408 |
eject the media. But the guest OS can handle this attempt to eject the
|
|
|
7a3408 |
media and can unlock the tray and open it. In this case, we should try
|
|
|
7a3408 |
again to actually eject the media.
|
|
|
7a3408 |
|
|
|
7a3408 |
If the first attempt fails to detect a tray_open we will fail with
|
|
|
7a3408 |
error, from monitor. If we receive that event, we know, that the guest
|
|
|
7a3408 |
properly reacted to the eject request, unlocked the tray and opened it.
|
|
|
7a3408 |
In this case, we need to run the command again to actually eject the
|
|
|
7a3408 |
media from the device. The reason to call it again is, that QEMU
|
|
|
7a3408 |
doesn't wait for the guest to react and report an error, that the tray
|
|
|
7a3408 |
is locked.
|
|
|
7a3408 |
|
|
|
7a3408 |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1147471
|
|
|
7a3408 |
|
|
|
7a3408 |
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
|
|
|
7a3408 |
(cherry picked from commit 28554080ecbcd1e57266b29734feb76799c2ee48)
|
|
|
7a3408 |
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
|
|
|
7a3408 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
7a3408 |
---
|
|
|
7a3408 |
src/qemu/qemu_hotplug.c | 73 +++++++++++++++++++++++--------------------------
|
|
|
7a3408 |
src/qemu/qemu_process.c | 2 ++
|
|
|
7a3408 |
2 files changed, 36 insertions(+), 39 deletions(-)
|
|
|
7a3408 |
|
|
|
7a3408 |
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
|
|
|
7a3408 |
index 79338cf..1ea397f 100644
|
|
|
7a3408 |
--- a/src/qemu/qemu_hotplug.c
|
|
|
7a3408 |
+++ b/src/qemu/qemu_hotplug.c
|
|
|
7a3408 |
@@ -59,7 +59,7 @@
|
|
|
7a3408 |
|
|
|
7a3408 |
VIR_LOG_INIT("qemu.qemu_hotplug");
|
|
|
7a3408 |
|
|
|
7a3408 |
-#define CHANGE_MEDIA_RETRIES 10
|
|
|
7a3408 |
+#define CHANGE_MEDIA_TIMEOUT 5000
|
|
|
7a3408 |
|
|
|
7a3408 |
/* Wait up to 5 seconds for device removal to finish. */
|
|
|
7a3408 |
unsigned long long qemuDomainRemoveDeviceWaitTime = 1000ull * 5;
|
|
|
7a3408 |
@@ -166,12 +166,13 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
|
|
|
7a3408 |
virStorageSourcePtr newsrc,
|
|
|
7a3408 |
bool force)
|
|
|
7a3408 |
{
|
|
|
7a3408 |
- int ret = -1;
|
|
|
7a3408 |
+ int ret = -1, rc;
|
|
|
7a3408 |
char *driveAlias = NULL;
|
|
|
7a3408 |
qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
|
7a3408 |
- int retries = CHANGE_MEDIA_RETRIES;
|
|
|
7a3408 |
const char *format = NULL;
|
|
|
7a3408 |
char *sourcestr = NULL;
|
|
|
7a3408 |
+ bool ejectRetry = false;
|
|
|
7a3408 |
+ unsigned long long now;
|
|
|
7a3408 |
|
|
|
7a3408 |
if (!disk->info.alias) {
|
|
|
7a3408 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
7a3408 |
@@ -193,36 +194,31 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
|
|
|
7a3408 |
if (!(driveAlias = qemuDeviceDriveHostAlias(disk, priv->qemuCaps)))
|
|
|
7a3408 |
goto error;
|
|
|
7a3408 |
|
|
|
7a3408 |
- qemuDomainObjEnterMonitor(driver, vm);
|
|
|
7a3408 |
- ret = qemuMonitorEjectMedia(priv->mon, driveAlias, force);
|
|
|
7a3408 |
- if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
7a3408 |
- ret = -1;
|
|
|
7a3408 |
- goto cleanup;
|
|
|
7a3408 |
- }
|
|
|
7a3408 |
+ do {
|
|
|
7a3408 |
+ qemuDomainObjEnterMonitor(driver, vm);
|
|
|
7a3408 |
+ rc = qemuMonitorEjectMedia(priv->mon, driveAlias, force);
|
|
|
7a3408 |
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
7a3408 |
+ goto cleanup;
|
|
|
7a3408 |
|
|
|
7a3408 |
- if (ret < 0)
|
|
|
7a3408 |
- goto error;
|
|
|
7a3408 |
+ if (rc == -2) {
|
|
|
7a3408 |
+ /* we've already tried, error out */
|
|
|
7a3408 |
+ if (ejectRetry)
|
|
|
7a3408 |
+ goto error;
|
|
|
7a3408 |
+ VIR_DEBUG("tray is locked, wait for the guest to unlock "
|
|
|
7a3408 |
+ "the tray and try to eject it again");
|
|
|
7a3408 |
+ ejectRetry = true;
|
|
|
7a3408 |
+ } else if (rc < 0) {
|
|
|
7a3408 |
+ goto error;
|
|
|
7a3408 |
+ }
|
|
|
7a3408 |
|
|
|
7a3408 |
- virObjectRef(vm);
|
|
|
7a3408 |
- /* we don't want to report errors from media tray_open polling */
|
|
|
7a3408 |
- while (retries) {
|
|
|
7a3408 |
- if (disk->tray_status == VIR_DOMAIN_DISK_TRAY_OPEN)
|
|
|
7a3408 |
- break;
|
|
|
7a3408 |
+ if (virTimeMillisNow(&now) < 0)
|
|
|
7a3408 |
+ goto error;
|
|
|
7a3408 |
|
|
|
7a3408 |
- retries--;
|
|
|
7a3408 |
- virObjectUnlock(vm);
|
|
|
7a3408 |
- VIR_DEBUG("Waiting 500ms for tray to open. Retries left %d", retries);
|
|
|
7a3408 |
- usleep(500 * 1000); /* sleep 500ms */
|
|
|
7a3408 |
- virObjectLock(vm);
|
|
|
7a3408 |
- }
|
|
|
7a3408 |
- virObjectUnref(vm);
|
|
|
7a3408 |
-
|
|
|
7a3408 |
- if (retries <= 0) {
|
|
|
7a3408 |
- virReportError(VIR_ERR_OPERATION_FAILED, "%s",
|
|
|
7a3408 |
- _("Unable to eject media"));
|
|
|
7a3408 |
- ret = -1;
|
|
|
7a3408 |
- goto error;
|
|
|
7a3408 |
- }
|
|
|
7a3408 |
+ while (disk->tray_status != VIR_DOMAIN_DISK_TRAY_OPEN) {
|
|
|
7a3408 |
+ if (virDomainObjWaitUntil(vm, now + CHANGE_MEDIA_TIMEOUT) != 0)
|
|
|
7a3408 |
+ goto error;
|
|
|
7a3408 |
+ }
|
|
|
7a3408 |
+ } while (ejectRetry && rc != 0);
|
|
|
7a3408 |
|
|
|
7a3408 |
if (!virStorageSourceIsEmpty(newsrc)) {
|
|
|
7a3408 |
if (qemuGetDriveSourceString(newsrc, conn, &sourcestr) < 0)
|
|
|
7a3408 |
@@ -237,19 +233,17 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
|
|
|
7a3408 |
}
|
|
|
7a3408 |
}
|
|
|
7a3408 |
qemuDomainObjEnterMonitor(driver, vm);
|
|
|
7a3408 |
- ret = qemuMonitorChangeMedia(priv->mon,
|
|
|
7a3408 |
- driveAlias,
|
|
|
7a3408 |
- sourcestr,
|
|
|
7a3408 |
- format);
|
|
|
7a3408 |
- if (qemuDomainObjExitMonitor(driver, vm) < 0) {
|
|
|
7a3408 |
- ret = -1;
|
|
|
7a3408 |
+ rc = qemuMonitorChangeMedia(priv->mon,
|
|
|
7a3408 |
+ driveAlias,
|
|
|
7a3408 |
+ sourcestr,
|
|
|
7a3408 |
+ format);
|
|
|
7a3408 |
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
|
|
7a3408 |
goto cleanup;
|
|
|
7a3408 |
- }
|
|
|
7a3408 |
}
|
|
|
7a3408 |
|
|
|
7a3408 |
- virDomainAuditDisk(vm, disk->src, newsrc, "update", ret >= 0);
|
|
|
7a3408 |
+ virDomainAuditDisk(vm, disk->src, newsrc, "update", rc >= 0);
|
|
|
7a3408 |
|
|
|
7a3408 |
- if (ret < 0)
|
|
|
7a3408 |
+ if (rc < 0)
|
|
|
7a3408 |
goto error;
|
|
|
7a3408 |
|
|
|
7a3408 |
/* remove the old source from shared device list */
|
|
|
7a3408 |
@@ -259,6 +253,7 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
|
|
|
7a3408 |
virStorageSourceFree(disk->src);
|
|
|
7a3408 |
disk->src = newsrc;
|
|
|
7a3408 |
newsrc = NULL;
|
|
|
7a3408 |
+ ret = 0;
|
|
|
7a3408 |
|
|
|
7a3408 |
cleanup:
|
|
|
7a3408 |
VIR_FREE(driveAlias);
|
|
|
7a3408 |
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
|
|
7a3408 |
index 9f1ae5a..c5f467b 100644
|
|
|
7a3408 |
--- a/src/qemu/qemu_process.c
|
|
|
7a3408 |
+++ b/src/qemu/qemu_process.c
|
|
|
7a3408 |
@@ -1155,6 +1155,8 @@ qemuProcessHandleTrayChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|
|
7a3408 |
VIR_WARN("Unable to save status on vm %s after tray moved event",
|
|
|
7a3408 |
vm->def->name);
|
|
|
7a3408 |
}
|
|
|
7a3408 |
+
|
|
|
7a3408 |
+ virDomainObjBroadcast(vm);
|
|
|
7a3408 |
}
|
|
|
7a3408 |
|
|
|
7a3408 |
virObjectUnlock(vm);
|
|
|
7a3408 |
--
|
|
|
7a3408 |
2.4.5
|
|
|
7a3408 |
|