diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index bcf3081a07..876b3791b5 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -46,6 +46,7 @@ #include "device_conf.h" #define VIR_FROM_THIS VIR_FROM_QEMU +#define CHANGE_MEDIA_RETRIES 10 int qemuDomainChangeEjectableMedia(struct qemud_driver *driver, virDomainObjPtr vm, @@ -57,6 +58,7 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *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 && @@ -84,7 +86,7 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *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; } @@ -102,8 +104,31 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *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->driverType) format = disk->driverType; @@ -113,9 +138,8 @@ int qemuDomainChangeEjectableMedia(struct qemud_driver *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);