diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7a2b012..f2887c6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3359,6 +3359,26 @@ virDomainDiskFindControllerModel(virDomainDefPtr def,
return model;
}
+virDomainDiskDefPtr
+virDomainDiskFindByBusAndDst(virDomainDefPtr def,
+ int bus,
+ char *dst)
+{
+ int i;
+
+ if (!dst)
+ return NULL;
+
+ for (i = 0 ; i< def->ndisks ; i++) {
+ if (def->disks[i]->bus == bus&&
+ STREQ(def->disks[i]->dst, dst)) {
+ return def->disks[i];
+ }
+ }
+
+ return NULL;
+}
+
int
virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def)
{
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 9232ff9..4ffa4aa 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1936,6 +1936,9 @@ void virDomainDiskHostDefFree(virDomainDiskHostDefPtr def);
int virDomainDiskFindControllerModel(virDomainDefPtr def,
virDomainDiskDefPtr disk,
int controllerType);
+virDomainDiskDefPtr virDomainDiskFindByBusAndDst(virDomainDefPtr def,
+ int bus,
+ char *dst);
void virDomainControllerDefFree(virDomainControllerDefPtr def);
void virDomainFSDefFree(virDomainFSDefPtr def);
void virDomainActualNetDefFree(virDomainActualNetDefPtr def);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index d8d5877..54ccf95 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -360,6 +360,7 @@ virDomainDiskDefGetSecurityLabelDef;
virDomainDiskDeviceTypeToString;
virDomainDiskErrorPolicyTypeFromString;
virDomainDiskErrorPolicyTypeToString;
+virDomainDiskFindByBusAndDst;
virDomainDiskFindControllerModel;
virDomainDiskGeometryTransTypeFromString;
virDomainDiskGeometryTransTypeToString;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5a3550d..18302e7 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5700,7 +5700,11 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
virDomainDeviceDefPtr dev)
{
virDomainDiskDefPtr disk = dev->data.disk;
+ virDomainDiskDefPtr orig_disk = NULL;
+ virDomainDeviceDefPtr dev_copy = NULL;
+ virDomainDiskDefPtr tmp = NULL;
virCgroupPtr cgroup = NULL;
+ virCapsPtr caps = NULL;
int ret = -1;
if (disk->driverName != NULL&& !STREQ(disk->driverName, "qemu")) {
@@ -5733,7 +5737,37 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn,
switch (disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
- ret = qemuDomainChangeEjectableMedia(driver, vm, disk, false);
+ if (!(orig_disk = virDomainDiskFindByBusAndDst(vm->def,
+ disk->bus, disk->dst))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("No device with bus '%s' and target '%s'"),
+ virDomainDiskBusTypeToString(disk->bus),
+ disk->dst);
+ goto end;
+ }
+
+ if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+ goto end;
+
+ tmp = dev->data.disk;
+ dev->data.disk = orig_disk;
+
+ if (!(dev_copy = virDomainDeviceDefCopy(caps, vm->def, dev))) {
+ dev->data.disk = tmp;
+ goto end;
+ }
+ dev->data.disk = tmp;
+
+ ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, false);
+
+ /* Need to remove the shared disk entry for the original disk src
+ * if the operation is either ejecting or updating.
+ */
+ if (ret == 0&&
+ orig_disk->src&&
+ STRNEQ_NULLABLE(orig_disk->src, disk->src))
+ ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk,
+ vm->def->name));
break;
case VIR_DOMAIN_DISK_DEVICE_DISK:
case VIR_DOMAIN_DISK_DEVICE_LUN:
@@ -5773,6 +5807,8 @@ end:
ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name));
if (cgroup)
virCgroupFree(&cgroup);
+ virObjectUnref(caps);
+ virDomainDeviceDefFree(dev_copy);
return ret;
}
@@ -5951,7 +5987,11 @@ qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
bool force)
{
virDomainDiskDefPtr disk = dev->data.disk;
+ virDomainDiskDefPtr orig_disk = NULL;
+ virDomainDiskDefPtr tmp = NULL;
virCgroupPtr cgroup = NULL;
+ virDomainDeviceDefPtr dev_copy = NULL;
+ virCapsPtr caps = NULL;
int ret = -1;
if (qemuDomainDetermineDiskChain(driver, disk, false)< 0)
@@ -5972,9 +6012,37 @@ qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
switch (disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM:
case VIR_DOMAIN_DISK_DEVICE_FLOPPY:
- ret = qemuDomainChangeEjectableMedia(driver, vm, disk, force);
- if (ret == 0)
+ if (!(orig_disk = virDomainDiskFindByBusAndDst(vm->def,
+ disk->bus, disk->dst))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("No device with bus '%s' and target '%s'"),
+ virDomainDiskBusTypeToString(disk->bus),
+ disk->dst);
+ goto end;
+ }
+
+ if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
+ goto end;
+
+ tmp = dev->data.disk;
+ dev->data.disk = orig_disk;
+
+ if (!(dev_copy = virDomainDeviceDefCopy(caps, vm->def, dev))) {
+ dev->data.disk = tmp;
+ goto end;
+ }
+ dev->data.disk = tmp;
+
+ ret = qemuDomainChangeEjectableMedia(driver, vm, disk, orig_disk, force);
+ if (ret == 0) {
dev->data.disk = NULL;
+ /* Need to remove the shared disk entry for the original
+ * disk src if the operation is either ejecting or updating.
+ */
+ if (orig_disk->src&& STRNEQ_NULLABLE(orig_disk->src, disk->src))
+ ignore_value(qemuRemoveSharedDisk(driver, dev_copy->data.disk,
+ vm->def->name));
+ }
break;
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -5991,6 +6059,8 @@ qemuDomainChangeDiskMediaLive(virDomainObjPtr vm,
end:
if (cgroup)
virCgroupFree(&cgroup);
+ virObjectUnref(caps);
+ virDomainDeviceDefFree(dev_copy);
return ret;
}
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 488a440..e631587 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -53,32 +53,15 @@
int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainDiskDefPtr disk,
+ virDomainDiskDefPtr origdisk,
bool force)
{
- virDomainDiskDefPtr origdisk = NULL;
- int i;
int ret = -1;
char *driveAlias = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData;
int retries = CHANGE_MEDIA_RETRIES;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
- for (i = 0 ; i< vm->def->ndisks ; i++) {
- if (vm->def->disks[i]->bus == disk->bus&&
- STREQ(vm->def->disks[i]->dst, disk->dst)) {
- origdisk = vm->def->disks[i];
- break;
- }
- }
-
- if (!origdisk) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("No device with bus '%s' and target '%s'"),
- virDomainDiskBusTypeToString(disk->bus),
- disk->dst);
- goto cleanup;
- }
-
if (!origdisk->info.alias) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("missing disk device alias name for %s"), origdisk->dst);
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 8f01d23..2a146fe 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -31,6 +31,7 @@
int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainDiskDefPtr disk,
+ virDomainDiskDefPtr orig_disk,
bool force);
int qemuDomainCheckEjectableMedia(virQEMUDriverPtr driver,
virDomainObjPtr vm,