From d0172d2b1b5d865aaa042070d7c2d00effb2ff8c Mon Sep 17 00:00:00 2001 From: Osier Yang Date: Tue, 19 Feb 2013 20:27:45 +0800 Subject: [PATCH] qemu: Remove the shared disk entry if the operation is ejecting or updating For both AttachDevice and UpdateDevice APIs, if the disk device is 'cdrom' or 'floppy', the operations could be ejecting, updating, and inserting. For either ejecting or updating, the shared disk entry of the original disk src has to be removed, because it's not useful anymore. And since the original disk def will be changed, new disk def passed as argument will be free'ed in qemuDomainChangeEjectableMedia, so we need to copy the orignal disk def before qemuDomainChangeEjectableMedia, to use it for qemuRemoveSharedDisk. --- src/conf/domain_conf.c | 20 +++++++++++ src/conf/domain_conf.h | 3 ++ src/libvirt_private.syms | 1 + src/qemu/qemu_driver.c | 76 ++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_hotplug.c | 19 +--------- src/qemu/qemu_hotplug.h | 1 + 6 files changed, 99 insertions(+), 21 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 7a2b012fd9..f2887c65b5 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 9232ff99ff..4ffa4aa318 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 3c44cc31cd..f399871b68 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -143,6 +143,7 @@ virDomainDiskDefGetSecurityLabelDef; virDomainDiskDeviceTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; +virDomainDiskFindByBusAndDst; virDomainDiskFindControllerModel; virDomainDiskGeometryTransTypeFromString; virDomainDiskGeometryTransTypeToString; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 297f2657c9..7eb5f5dd8f 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5704,7 +5704,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")) { @@ -5737,7 +5741,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: @@ -5777,6 +5811,8 @@ end: ignore_value(qemuRemoveSharedDisk(driver, disk, vm->def->name)); if (cgroup) virCgroupFree(&cgroup); + virObjectUnref(caps); + virDomainDeviceDefFree(dev_copy); return ret; } @@ -5955,7 +5991,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) @@ -5976,9 +6016,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, @@ -5995,6 +6063,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 4b3412294b..78961a7ddb 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 8f01d235f5..2a146fed98 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, -- 2.39.5