]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: Remove the shared disk entry if the operation is ejecting or updating
authorOsier Yang <jyang@redhat.com>
Tue, 19 Feb 2013 12:27:45 +0000 (20:27 +0800)
committerOsier Yang <jyang@redhat.com>
Wed, 20 Feb 2013 16:31:24 +0000 (00:31 +0800)
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
src/conf/domain_conf.h
src/libvirt_private.syms
src/qemu/qemu_driver.c
src/qemu/qemu_hotplug.c
src/qemu/qemu_hotplug.h

index 7a2b012fd9f196ebfd725020f4fba344f46f3a30..f2887c65b5542328c5411fe8afac8b69cebeaa4e 100644 (file)
@@ -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)
 {
index 9232ff99ffabf66a9cfecee094d9def41d1e83b6..4ffa4aa3183c8899e55c5be53bebbe3abe49335b 100644 (file)
@@ -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);
index 3c44cc31cd39084779e83903bd061a918a7b2fa1..f399871b6847de3c46d5e5f79016fd3f8f4f7a12 100644 (file)
@@ -143,6 +143,7 @@ virDomainDiskDefGetSecurityLabelDef;
 virDomainDiskDeviceTypeToString;
 virDomainDiskErrorPolicyTypeFromString;
 virDomainDiskErrorPolicyTypeToString;
+virDomainDiskFindByBusAndDst;
 virDomainDiskFindControllerModel;
 virDomainDiskGeometryTransTypeFromString;
 virDomainDiskGeometryTransTypeToString;
index 297f2657c9b8651c43006b56d1e5b274a4fe43fb..7eb5f5dd8f6b6481a9c87ecca5a1cccf4d3cb2d7 100644 (file)
@@ -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;
 }
 
index 4b3412294bd028d90c5869ac84e99f0bf9cebcaf..78961a7ddbe4ae2ecb8c6973fe20406aaaccb936 100644 (file)
 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);
index 8f01d235f51ed641e0f63519352f5bac378fedee..2a146fed98704d817191fa114dcf1f3744baced5 100644 (file)
@@ -31,6 +31,7 @@
 int qemuDomainChangeEjectableMedia(virQEMUDriverPtr driver,
                                    virDomainObjPtr vm,
                                    virDomainDiskDefPtr disk,
+                                   virDomainDiskDefPtr orig_disk,
                                    bool force);
 int qemuDomainCheckEjectableMedia(virQEMUDriverPtr driver,
                                   virDomainObjPtr vm,