qemu: hotplug: Split out media change code from disk hotplug

Disk hotplug has slightly different semantics from media changing. Move
the media change code out and add proper initialization of the new
source object and proper cleanups if something fails.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
Peter Krempa 2018-09-25 14:47:36 +02:00
parent a05bdd5533
commit a1d3fc09f8
2 changed files with 51 additions and 41 deletions

View File

@ -7851,12 +7851,6 @@ qemuDomainChangeDiskLive(virDomainObjPtr vm,
virDomainDeviceDef oldDev = { .type = dev->type };
int ret = -1;
if (virDomainDiskTranslateSourcePool(disk) < 0)
goto cleanup;
if (qemuDomainDetermineDiskChain(driver, vm, disk, true) < 0)
goto cleanup;
if (!(orig_disk = virDomainDiskFindByBusAndDst(vm->def,
disk->bus, disk->dst))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
@ -7885,16 +7879,9 @@ qemuDomainChangeDiskLive(virDomainObjPtr vm,
goto cleanup;
}
/* Add the new disk src into shared disk hash table */
if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0)
goto cleanup;
if (qemuDomainChangeEjectableMedia(driver, vm, orig_disk,
dev->data.disk->src, force) < 0) {
ignore_value(qemuRemoveSharedDisk(driver, dev->data.disk,
vm->def->name));
dev->data.disk->src, force) < 0)
goto cleanup;
}
dev->data.disk->src = NULL;
}

View File

@ -733,11 +733,23 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
qemuDomainObjPrivatePtr priv = vm->privateData;
virStorageSourcePtr oldsrc = disk->src;
bool sharedAdded = false;
int ret = -1;
int rc;
disk->src = newsrc;
if (virDomainDiskTranslateSourcePool(disk) < 0)
goto cleanup;
if (qemuAddSharedDisk(driver, disk, vm->def->name) < 0)
goto cleanup;
sharedAdded = true;
if (qemuDomainDetermineDiskChain(driver, vm, disk, true) < 0)
goto cleanup;
if (qemuDomainPrepareDiskSource(disk, priv, cfg) < 0)
goto cleanup;
@ -754,10 +766,8 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
virDomainAuditDisk(vm, oldsrc, newsrc, "update", rc >= 0);
if (rc < 0) {
ignore_value(qemuHotplugPrepareDiskAccess(driver, vm, disk, newsrc, true));
if (rc < 0)
goto cleanup;
}
/* remove the old source from shared device list */
disk->src = oldsrc;
@ -769,11 +779,21 @@ qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
oldsrc = NULL;
disk->src = newsrc;
ignore_value(qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE));
ret = 0;
cleanup:
/* undo changes to the new disk */
if (ret < 0) {
if (sharedAdded)
ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
ignore_value(qemuHotplugPrepareDiskAccess(driver, vm, disk, newsrc, true));
}
/* remove PR manager object if unneeded */
ignore_value(qemuHotplugRemoveManagedPR(driver, vm, QEMU_ASYNC_JOB_NONE));
/* revert old image do the disk definition */
if (oldsrc)
disk->src = oldsrc;
@ -1072,9 +1092,15 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver,
{
size_t i;
virDomainDiskDefPtr disk = dev->data.disk;
virDomainDiskDefPtr orig_disk = NULL;
int ret = -1;
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
_("cdrom/floppy device hotplug isn't supported"));
return -1;
}
if (virDomainDiskTranslateSourcePool(disk) < 0)
goto cleanup;
@ -1088,27 +1114,6 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver,
goto cleanup;
switch ((virDomainDiskDevice) disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
if (!(orig_disk = virDomainDiskFindByBusAndDst(vm->def,
disk->bus, disk->dst))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("No device with bus '%s' and target '%s'. "
"cdrom and floppy device hotplug isn't supported "
"by libvirt"),
virDomainDiskBusTypeToString(disk->bus),
disk->dst);
goto cleanup;
}
if (qemuDomainChangeEjectableMedia(driver, vm, orig_disk,
disk->src, false) < 0)
goto cleanup;
disk->src = NULL;
ret = 0;
break;
case VIR_DOMAIN_DISK_DEVICE_DISK:
case VIR_DOMAIN_DISK_DEVICE_LUN:
for (i = 0; i < vm->def->ndisks; i++) {
@ -1150,6 +1155,8 @@ qemuDomainAttachDeviceDiskLiveInternal(virQEMUDriverPtr driver,
}
break;
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
case VIR_DOMAIN_DISK_DEVICE_LAST:
break;
}
@ -1176,6 +1183,22 @@ qemuDomainAttachDeviceDiskLive(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev)
{
virDomainDiskDefPtr disk = dev->data.disk;
virDomainDiskDefPtr orig_disk = NULL;
/* this API overloads media change semantics on disk hotplug
* for devices supporting media changes */
if ((disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) &&
(orig_disk = virDomainDiskFindByBusAndDst(vm->def, disk->bus, disk->dst))) {
if (qemuDomainChangeEjectableMedia(driver, vm, orig_disk,
disk->src, false) < 0)
return -1;
disk->src = NULL;
return 0;
}
return qemuDomainAttachDeviceDiskLiveInternal(driver, vm, dev);
}