File libvirt-qemu-support-to-drop-disk-with-optional-startupPolicy.patch of Package libvirt

From 9a0c357d472067f74d76105bd967883ffc734695 Mon Sep 17 00:00:00 2001
Message-Id: <9a0c357d472067f74d76105bd967883ffc734695@dist-git>
From: Guannan Ren <gren@redhat.com>
Date: Fri, 11 Apr 2014 16:34:03 +0200
Subject: [PATCH] qemu: support to drop disk with 'optional' startupPolicy

Go through disks of guest, if one disk doesn't exist or its backing
chain is broken, with 'optional' startupPolicy, for CDROM and Floppy
we only discard its source path definition in xml, for disks we drop
it from disk list and free it.

(cherry picked from commit 8a160f11afe916284c569d4c23adb24f755e459e)

(https://bugzilla.redhat.com/show_bug.cgi?id=1014730)

Conflicts:
	src/qemu/qemu_domain.c

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 include/libvirt/libvirt.h.in |  1 +
 src/qemu/qemu_domain.c       | 68 ++++++++++++++++++++++++++++++++------------
 2 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index f0c63e2..038dadf 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -4100,6 +4100,7 @@ typedef void (*virConnectDomainEventBlockJobCallback)(virConnectPtr conn,
  */
 typedef enum {
     VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START = 0, /* oldSrcPath is set */
+    VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START = 1,
 
 #ifdef VIR_ENUM_SENTINELS
     VIR_DOMAIN_EVENT_DISK_CHANGE_LAST
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 33f999e..c34f149 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -1864,13 +1864,53 @@ qemuDomainSetFakeReboot(struct qemud_driver *driver,
 }
 
 static int
+qemuDomainCheckRemoveOptionalDisk(struct qemud_driver *driver,
+                                  virDomainObjPtr vm,
+                                  virDomainDiskDefPtr disk)
+{
+    char uuid[VIR_UUID_STRING_BUFLEN];
+    virDomainEventPtr event = NULL;
+    virDomainDiskDefPtr del_disk = NULL;
+
+    virUUIDFormat(vm->def->uuid, uuid);
+
+    VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
+              "due to inaccessible source '%s'",
+              disk->dst, vm->def->name, uuid, disk->src);
+
+    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ||
+        disk->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
+
+        event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
+                                                   disk->info.alias,
+                                                   VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
+        VIR_FREE(disk->src);
+    } else {
+        event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL,
+                                                   disk->info.alias,
+                                                   VIR_DOMAIN_EVENT_DISK_DROP_MISSING_ON_START);
+
+        if (!(del_disk = virDomainDiskRemoveByName(vm->def, disk->src))) {
+            virReportError(VIR_ERR_INVALID_ARG,
+                           _("no source device %s"), disk->src);
+            return -1;
+        }
+        virDomainDiskDefFree(del_disk);
+    }
+
+    if (event)
+        qemuDomainEventQueue(driver, event);
+
+    return 0;
+}
+
+static int
 qemuDomainCheckDiskStartupPolicy(struct qemud_driver *driver,
                                  virDomainObjPtr vm,
                                  virDomainDiskDefPtr disk,
                                  bool cold_boot)
 {
     char uuid[VIR_UUID_STRING_BUFLEN];
-    virDomainEventPtr event = NULL;
     int startupPolicy = disk->startupPolicy;
 
     virUUIDFormat(vm->def->uuid, uuid);
@@ -1893,17 +1933,8 @@ qemuDomainCheckDiskStartupPolicy(struct qemud_driver *driver,
             break;
     }
 
-    virResetLastError();
-    VIR_DEBUG("Dropping disk '%s' on domain '%s' (UUID '%s') "
-              "due to inaccessible source '%s'",
-              disk->dst, vm->def->name, uuid, disk->src);
-
-    event = virDomainEventDiskChangeNewFromObj(vm, disk->src, NULL, disk->info.alias,
-                                               VIR_DOMAIN_EVENT_DISK_CHANGE_MISSING_ON_START);
-    if (event)
-        qemuDomainEventQueue(driver, event);
-
-    VIR_FREE(disk->src);
+    if (qemuDomainCheckRemoveOptionalDisk(driver, vm, disk) < 0)
+        goto error;
 
     return 0;
 
@@ -1921,8 +1952,8 @@ qemuDomainCheckDiskPresence(struct qemud_driver *driver,
     virDomainDiskDefPtr disk;
 
     VIR_DEBUG("Checking for disk presence");
-    for (i = 0; i < vm->def->ndisks; i++) {
-        disk = vm->def->disks[i];
+    for (i = vm->def->ndisks; i > 0; i--) {
+        disk = vm->def->disks[i - 1];
 
         if (!disk->src)
             continue;
@@ -1931,10 +1962,11 @@ qemuDomainCheckDiskPresence(struct qemud_driver *driver,
             qemuDiskChainCheckBroken(disk) >= 0)
             continue;
 
-        if (disk->startupPolicy) {
-            if (qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
-                                                 cold_boot) >= 0)
-                continue;
+        if (disk->startupPolicy &&
+            qemuDomainCheckDiskStartupPolicy(driver, vm, disk,
+                                             cold_boot) >= 0) {
+            virResetLastError();
+            continue;
         }
 
         goto error;
-- 
1.9.2

openSUSE Build Service is sponsored by