mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-16 17:45:16 +00:00
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. (cherry picked from commit 84c59ffaecc983083e2e885fa59c4f0ec1812656)
This commit is contained in:
parent
0305c271fc
commit
7c4b6833bb
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user